...
This page documents the existing Yang Parser used in ONAP and OpenDayLight and will investigate if they can be used for 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.
...
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 file data files in java code.
...
...
Code Block |
---|
...
Code Block | language | xml|||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
<properties> <maven.compiler.version>3.8.1</maven.compiler.version> <maven.compiler.release>11</maven.compiler.release> <org.opendaylight <odl.yangtools.version>5.0.3<5</org.opendaylightodl.yangtools.version> </properties> <build> <plugins> <plugin> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>${maven.compiler.version}</version> <configuration> <configuration> <release>${maven.compiler.release}</release> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <dependency> <groupId>org.opendaylight.yangtools</groupId> <artifactId>yang-parser-api</artifactId> <version>${org.opendaylight <version>${odl.yangtools.version}</version> </dependency> <dependency> <dependency> <groupId>org.opendaylight.yangtools</groupId> <artifactId>yang-parser-impl</artifactId> <version>${org.opendaylight. <version>${odl.yangtools.version}</version> </dependency> <dependency> </dependency> <dependency> <groupId>org.opendaylight.yangtools</groupId> <artifactId>yang-model-util</artifactId> <version>${org.opendaylight <version>${odl.yangtools.version}</version> </dependency> <dependency> <groupId>org.opendaylight.yangtools</groupId> <artifactId>yang-data-codec-xml</artifactId> <version>${org.opendaylight <version>${odl.yangtools.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.6.1</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.6.1</version> </dependency> </dependencies> |
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
Code Block | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
static YangParserFactory PARSER_FACTORY; static { <dependency> <groupId>org.opendaylight.yangtools</groupId> <artifactId>yang-data-codec-gson</artifactId> <version>${odl.yangtools.version}</version> </dependency> <!-- SLF4J API --> <dependency> final Iterator<YangParserFactory> it = ServiceLoader.load(YangParserFactory.class).iterator();<groupId>org.slf4j</groupId> if (!it.hasNext()) {<artifactId>slf4j-api</artifactId> <version>1.6.1</version> throw new IllegalStateException("No YangParserFactory found"); </dependency> } <!-- LOG4J --> PARSER_FACTORY<dependency> = it.next(); } <groupId>org...slf4j</groupId> File file = new File(ClassLoader.getSystemClassLoader().getResource("example.yang").getFile());<artifactId>slf4j-log4j12</artifactId> YangTextSchemaSource source = YangTextSchemaSource.forFile(file);<version>1.6.1</version> </dependency> final YangParser yangParser = PARSER_FACTORY.createParser(StatementParserMode.</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
Code Block | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
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() |
...
Description | Yang | Java Object View | Notes | XML Validation | JSON |
---|---|---|---|---|---|
Datatypes and basic constraints | |||||
Basic String |
| TypeStatement TypeAwareDeclaredStatement.getType() | Yes | Yes | |
Mandatory Basic String |
|
| No | No | |
Limited String | leaf pnf-name { type string { length "0..256"; } |
| Yes | Yes | |
typedef (String) with pattern |
| List<PatternConstraint> RestrictedStringType.getPatternConstraints() | Yes | Yes | |
Limited uint64 | leaf cid { type uint64 { range "0..503"; } } | org.opendaylight.yangtools.yang.model.util.type.RestrictedUint64Type | Yes | Yes | |
boolean with default value |
| org.opendaylight.yangtools.yang.model.util.type.DerivedBooleanType | N/A | N/A | |
Unique | |||||
Unique | list server { key "name"; unique "ip port"; leaf name { type string; } leaf ip { type dotted-quad; } leaf port { type uint32; } } | org.opendaylight.yangtools.yang.model.api.stmt.UniqueStatement | No | No | |
Choice | |||||
Choice | choice transfer-method { leaf transfer-interval { type uint64 { range "15..2880"; } units minutes; } leaf transfer-on-commit { type empty; } } | org.opendaylight.yangtools.yang.model.api.stmt.ChoiceStatement | N/A | N/A | |
Must | |||||
Must | leaf ifType { type enumeration { enum ethernet; enum atm; } } leaf ifMTU { type uint32; } must "ifType != 'ethernet' or " + "(ifType = 'ethernet' and ifMTU = 1500)" error-message 466px"An ethernet MTU must be 1500"; } | org.opendaylight.yangtools.yang.model.api.stmt.ErrorMessageStatement | No | No | |
When | |||||
When | leaf a { type boolean; } leaf b { type string; when "../a = 'true'"; } | org.opendaylight.yangtools.yang.model.api.stmt.WhenStatement | No | No | |
Extension | |||||
Extension declaration |
| N/A | |||
Extension usage | leaf attribute-with-temporal-storage { type string; cm-notify-api:store-state-ext "3 d"; } | extension is stored as 'UnknownNode' and refers back to the extension declaration | N/A | ||
Augmentation | |||||
augment "server" { when "port = '8787'"; leaf enable-debug { type boolean; } } | 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
Code Block | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
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(); } |
...
- 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
Conclusions
...
- for XML Data Parsing
Conclusion
Pros
- The YangTools model parser is comprehensive and covers all possible Yang Language elements we might require
- Extensively used throughout ONAP and ODL projects
- Mature code, dates back to 2013 with contributions from many companies including Cisco and Redhat
- Parsing of JSON and XML data with validated for a a (parsed) model included
Cons
- Due to its completeness it also is a complicated piece of software which will take some time to get familiar with
- Documentation out of date, this page hopes to address that somewhat