...
Description | Yang | Java Object View | Notes | XML Validation | JSON |
---|---|---|---|---|---|
Datatypes and basic constraints | |||||
Basic String |
| Yes | Yes | ||
Mandatory Basic String |
| No | No | ||
Limited String | leaf pnf-name { type string { length "0..256"; } | Specialized class to hold length limitation | Yes | Yes | |
typedef (String) with pattern |
| Checked by XmlParser | Yes | Yes | |
Limited uint64 | leaf cid {325px400 type uint64 { range "0..503"; } } | Yes | Yes | ||
boolean with default value |
| 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; } } | No | No | ||
Choice | |||||
Choice | choice transfer-method { leaf transfer-interval { type uint64 { range "15..2880"; } units minutes; } leaf transfer-on-commit { type empty; } } | 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"; } | No | No | ||
When | |||||
When | leaf a { type boolean; } leaf b { type string; when "../a = 'true'"; } | 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 |
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(); } |
...
The table in the sections above has has a column with the XML validation findings.
JSON Parsing
Code Block | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
SchemaContext schemaContext = ... (see previous snippets) JSONCodecFactory jsonCodecFactory = JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02.getShared(schemaContext); final NormalizedNodeResult result = new NormalizedNodeResult(); final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result); final JsonParserStream jsonParser = JsonParserStream.create(streamWriter, jsonCodecFactory); final InputStream resourceAsStream = ClassLoader.getSystemClassLoader().getResourceAsStream("example2data.json"); final JsonReader jsonReader = new JsonReader(new InputStreamReader(resourceAsStream)); jsonParser.parse(jsonReader); final NormalizedNode<?, ?> transformedInput = result.getResult(); |
...
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
Conclusions
- The YangTools model parser is comprehensive and cover all disposable Yang Language elements we might require
- complicated, no clear interface
- documentation out of data,