Existing Yang Parser
- 1 Overview
- 1.1 Resources
- 2 Mini-PoC
- 2.1 Maven dependency
- 2.1.1 pom.xml
- 2.2 Documentation Code Updates
- 2.2.1 Corrected Code
- 2.1 Maven dependency
- 3 Generated Java Object Structures per Yang concept
- 3.1 Object Structure
- 3.2 Main data types
- 3.3 Datatypes and basic constraints
- 3.4 Unique
- 3.5 Choice
- 3.6 Must
- 3.7 When
- 3.8 Extension
- 3.9 Augmentation
- 3.10 RPC
- 4 Yang Data Parsing and Validation
- 4.1 XML Parsing
- 4.1.1.1 XML Parsing Example
- 4.1.2 XML Validation Findings
- 4.2 JSON Parsing
- 4.2.1.1 JSON Parsing Example
- 4.2.2 JSON Validation Findings
- 4.1 XML Parsing
- 5 Conclusion
Work in Progress
This page documents the existing Yang Parser used in ONAP and OpenDayLight and will investigate if it fulfill the needs of the C&PS.
Overview
The Yang parser used in ONAP (CCSDK / SDNC) was developed (and still is) a OpenDayLight Library.
There are 2 different usage patterns within CCSDK, though.
Most of CCSDK/SDNC is using Yang primarily to define their northbound interfaces. In that context, there’s a maven plugin (org.opendaylight.yangtools:yang-maven-plugin) that is used to generate source code from the Yang model. Our application code in that case doesn’t really do anything directly with the Yang, since all of the that is handled for us by the generated code.
In ccsdk/sli/plugins, there is a plugin called restconf-client which was contributed by Huawei. That code uses the yangtool parser more directly so that it can interpret the results being returned when it calls a restconf interface.
Resources
Additional Resources (still to be examined)
*Although this documentation link is to the latest ODL doc revision, it is very outdated and the code examples need significant updates, see findings in Mini-PoC below (bug reported: https://jira.opendaylight.org/browse/DOCS-126)
Mini-PoC
To help this evaluation I will create a small sample project with the goal to pare a yang file using the ODL Yang Tools. I will report my findings here
Maven dependency
The documentation mentioned above lists many modules but the code examples do not clarify which exactly are needed to parse a Yang model and Yang data files in java code.
pom.xml
<properties>
<maven.compiler.version>3.8.1</maven.compiler.version>
<maven.compiler.release>11</maven.compiler.release>
<odl.yangtools.version>5.0.5</odl.yangtools.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.version}</version>
<configuration>
<release>${maven.compiler.release}</release>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-parser-api</artifactId>
<version>${odl.yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-parser-impl</artifactId>
<version>${odl.yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-model-util</artifactId>
<version>${odl.yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-codec-xml</artifactId>
<version>${odl.yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-codec-gson</artifactId>
<version>${odl.yangtools.version}</version>
</dependency>
<!-- SLF4J API -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.1</version>
</dependency>
<!-- LOG4J -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.1</version>
</dependency>
</dependencies>
Note. SLF4J has also been added as the implementation requires an enabled logger
Documentation Code Updates
The sample code provided in the documentation is faulty (using == for assigning?!) and is using some long deprecated and even removed classes and methods.
Bug reported: https://jira.opendaylight.org/browse/DOCS-126
Corrected Code
static YangParserFactory PARSER_FACTORY;
static {
final Iterator<YangParserFactory> it = ServiceLoader.load(YangParserFactory.class).iterator();
if (!it.hasNext()) {
throw new IllegalStateException("No YangParserFactory found");
}
PARSER_FACTORY = it.next();
}
...
File file = new File(ClassLoader.getSystemClassLoader().getResource("example.yang").getFile());
YangTextSchemaSource source = YangTextSchemaSource.forFile(file);
final YangParser yangParser = PARSER_FACTORY.createParser(StatementParserMode.DEFAULT_MODE);
yangParser.addSource(source);
SchemaContext schemaContext = yangParser.buildEffectiveModel();
schemaContext.getModules()
This is the kind of object (module) that gets created:
Generated Java Object Structures per Yang concept
Object Structure
The SchemaContext
object generated by the Yang Parser in java has the following possible structures (java collections)
SchemaTree
is implemented as a ImmutableMap<QName, SchemaTreeEffectiveStatement<?>>
The SchemaTree
can represent a tree of any Yang Leaf, List or Container. All leafs implement the LeafStatement interface which provides methods for many Yang Language features including
getType()
getUnits()
getMandatory()
getWhenStatement()
getMustStatments()
Main data types
The package org.opendaylight.yangtools.yang.model.util.type contains classes for all the possible data types including:
BaseBinaryType
BaseBitsType
BaseBooleanType
BaseDecimalType
BaseEnumerationType
BaseInt8Type
BaseInt16Type
BaseInt32Type
BaseInt64Type
BaseStringType
BaseUint8Type
BaseUint16Type
BaseUint32Type
BaseUint64Type
There are also some special data types such as:
BaseEmptyType
BaseIdentityrefType
BaseInstanceIdentifierType
BaseLeafrefType
BaseUnionType
And also 'restricted' versions of the base types such as:
RestrictedStringType
RestrictedUint64Type
Description | Yang | Java Object View | Notes | XML Validation | JSON |
---|---|---|---|---|---|
Datatypes and basic constraints | |||||
Basic String |
|
| Yes | Yes | |
Mandatory Basic String |
|
| No | No | |
Limited String |
|
| Yes | Yes | |
typedef (String) with pattern |
|
| Yes | Yes | |
Limited uint64 |
|
| Yes | Yes | |
boolean with default value |
|
| N/A | N/A | |
Unique | |||||
Unique |
|
| No | No | |
Choice | |||||
Choice |
|
| N/A | N/A | |
Must | |||||
Must |
|
| No | No | |
When | |||||
When | leaf a { type boolean; } leaf b { type string; when "../a = 'true'"; } |
| No | No | |
Extension | |||||
Extension declaration |
| N/A | |||
Extension usage |
|
which extends public interface UnknownStatement<A> extends DeclaredStatement<A> { | N/A | ||
Augmentation | |||||
| The additional leaf just appears in the SchemaTree (without any reference that it is an augmentation) | N/A | |||
RPC | |||||
rpc | rpc nbrlist-change-notification { | N/A | |||
rpc input | input { in a neighbor list for this fap service"; } | N/A | |||
rpc output | output { | N/A |
Yang Data Parsing and Validation
XML Parsing
XML Parsing Example
SchemaContext schemaContext = ... (see previous snippets)
final Module module = schemaContext.findModules("ultraconfig-interfaces").iterator().next();
QName qName = QName.create(module.getQNameModule(),"interfaces");
final Optional<DataSchemaNode> node = module.findDataChildByName(qName);
if (node.isPresent()) {
final InputStream resourceAsStream = ClassLoader.getSystemClassLoader().getResourceAsStream("example2data.xml");
final XMLStreamReader reader = UntrustedXML.createXMLStreamReader(resourceAsStream);
final NormalizedNodeResult result = new NormalizedNodeResult();
final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, node.get() );
xmlParser.parse(reader);
final NormalizedNode<?, ?> transformedInput = result.getResult();
}
*Note: the DataSchemaNode being used when creating the XmlParserStream HAS to be the root node of the xml data!
XML Validation Findings
The XML Parser is found to do basic data type checks including range checks and (regex) pattern validation. If the dat input doesn't conform those a clear exception detailing the problem is thrown
Features such as 'mandatory' and 'unique' are to be validated
More advanced features such as 'must', 'when', 'choice' etc have not yet been tested
The table in the sections above has a column with the XML validation findings.
JSON Parsing
JSON Parsing Example
JSON Validation Findings
As expected the parsing of string, originating form XML or JSON is done by the same code and the results are identical to those for XML Data Parsing
Conclusion
Pros
EXTENSIVE - The YangTools model parser is comprehensive and covers all possible Yang Language elements we might require
AVAILABLE - Extensively used throughout ONAP and ODL projects (able to convert to Java objects, code & API). These parsers are already used in many ONAP platform projects.
MATURE CODE - Mature code, dates back to 2013 with contributions from many companies including Cisco and Redhat and Pantheon Tech. (No need for licenses, these are also open source Yang parser). ODL is open source.
VALIDATION - Testing with parsing of JSON and XML data with validated for a (parsed) model included. Files to objects and vice versa is possible. Model violation & compilation validation is available.
OBJECTIVES - Meets our two high-level requirements & objectives. Parse models from SDC into Java objects relate to persistence of data. Parsing of documents compliant to those schemas.
Cons
LEARNING CURVE - Due to its completeness it also is a complicated piece of software which will take some time to get familiar with.
DOCUMENTATION - Documentation out of date, this page hopes to address that somewhat