Team
Name | Organization | |
---|---|---|
Adarsh M | Huawei Technologies | adarsh.m@huawei.com |
Bharat Saraswal | Huawei Technologies | bharat.saraswal@huawei.com |
Gaurav Agrawal | Huawei Technologies | gaurav.agrawal@huawei.com |
Janani B | Huawei Technologies | janani.b@huawei.com |
Sathish Kumar M | Huawei Technologies | sathishkumar.m@huawei.com |
Suchitra H N | Huawei Technologies | suchitra.hn@huawei.com |
Vidyashree Rama | Huawei Technologies | vidyashree.rama@huawei.com |
Vinod Kumar S | Huawei Technologies | vinods.kumar@huawei.com |
Shankara | Huawei Technologies | |
Mahesh Poojary S | Huawei Technologies | |
Rama Subba Reddy S | Huawei Technologies |
Requirements for Hummingbird Release
Requested By | Requirements | Suggested Priority (high - Middle -Low) | Current Status |
---|---|---|---|
Thomas Vachuska | Thanks for the demo of the YANG utilities at today’s TST meeting. While a lot of good work was done in the last release, I was a little bit surprised that the codec functionality was pushed off to the next release - and that NB-related concerns superseded SB-related ones. In my view, this is the basic value of using the YANG models - as it provides the ability to consume/produce XML payloads that are complaint with the model in a structured manner via Java API. We have a set of use-cases for this to control/configure devices via NETCONF. Presently we have to accomplish this using hand-crafted XML and we were hoping to use the YANG tools-generated codecs for this. Consequently the SB use of YANG is of much more importance to us than the NB use of YANG - at least for the near-term. In the Hummingbird release we need to be able to use the YANG tools generated artifacts together with our existing NETCONF sub-controller to produce driver implementations for several packet and optical devices. For this reason, I would like to request that this work be prioritized over anything else with respect to other YANG-related work. In order for that to happen, I think a number of other important questions will have to be answered and accounted for in the overall design of the YANG utilities:
| High | reviewing |
Ali Al-Shabibi | JSON or JSON-Schema Intermediary Representation. It would be nice if we could go from YANG to JSON or JSON-Schema because from this IR format we can easily go to XML or JSON or some other format that another protocol may want to use. As you probably know, Netconf is only one of the southbound to deliver payloads other ones such as gRPC or REST can be used. | medium | |
Marc De Leenheer | Support for OpenROADM YANG models. The specification contains two parts, a service-level model (NB) and a device-level model (SB). The first phase has already started, we want to integrate the device model into ONOS by early Q3 2016. In Q4 we will do the service level models. This is high priority work in collaboration with AT&T. | high | |
Aihua Guo | In order to support the use of standard IETF YANG models as an NBI for hierarchical SDN control, it is expected that the following YANG data constructs be supported in the H releases: augment (partially supported in G release), identity, feature/if-feature, when, must, leafref, path, require-instance. These data constructs are defined by YANG 1.1, and most of the IETF YANG models contain those constructs written in YANG 1.1. | high |
Overview
YANG is a data modeling language used to model configuration & state data. Modeling languages such as SMI (SNMP), UML, XML Schema, and others already existed. However, none of these languages were specifically targeted to the needs of configuration management. They lacked critical capabilities like being easily read and understood by human implementers, and fell short in providing mechanisms to validate models of configuration data for semantics and syntax.
YANG Utils are the basic building block to achieve the final goal of abstracting the language based Syntax/Semantics processing by APPs.
The YANG modeled interfaces need to be implemented by corresponding application component. There are 2 parts in implementing the interface:
- Syntax/semantics processing of the request/response being exchanged.
- Business logic to compute the request.
We intend to abstract the applications from syntactic processing of information encoding with external world.We intend to provide a framework in which the applications only need to implement the business logic and seamlessly support any interface language like REST, NETCONF etc.
Steps to use YANG utils
Step1 : Create a test app and add YANG utils maven plugin to pom file’s build section
<build> <plugins> <plugin> <groupId>org.onosproject</groupId> <artifactId>onos-yang-maven-plugin</artifactId> <version>1.9</version> <executions> <execution> <configuration> <classFileDir>src/main/java</classFileDir> </configuration> <goals> <goal>yang2java</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
Step 2 : Add dependency to pom file’s dependency section only if your yang file contains notification in it. You need to add dependencies for "onos-api".
Step 3 : Plugin configuration supported in YANG utils
Create a folder structure as “src/main/yang” in the test app folder and place your YANG files in it. In case user want to give desired path for source YANG files and generated java files, the following configuration can be appended to the above pom.xml file.
<configuration> <yangFilesDir>DesiredYangFilesPath</yangFilesDir> <classFileDir>DesiredGeneratedJavaFilesPath</classFileDir> </configuration>
Step 4 : Execution of application
Build using mvn clean install/ mvn install. Generated java code will be placed in default directory or in desired destination folder configured by user.
Code generated is as per ONOS coding guidelines.
Note:
- If user does not provide any configurations for code generation , code will be generated in "target/generated-sources" folder. This folder conatains majorly,
i) Service interface for module.
ii) Module interface and its param class.
iii) Interfaces of child constructs of module and their default implementation class. - If a yang file contains only typedef/grouping nodes, there will not be any generation of service class only one interface will be generated.
YANG utils constructs support/plan
YANG Construct | Supported/Planned version |
---|---|
anyxml | Not planned |
argument | Hummingbird(partial support) |
augment | Goldeneye |
uses-augment | Not planned |
base | Hummingbird |
belongs-to | Goldeneye |
bit | Hummingbird |
case | Goldeneye |
choice | Goldeneye |
config | Falcon |
contact | Goldeneye Enhancement in Hummingbird |
container | Falcon |
default | Goldeneye Enhancement in Humminbird |
description | Goldeneye Enhancement in Hummingbird |
deviate | Not planned |
deviation | Not planned |
enum | Goldeneye |
error-app-tag | Hummingbird |
error-message | Hummingbird |
extension | Hummingbird(partial support) |
feature | Hummingbird |
fraction-digits | Hummingbird |
grouping | Goldeneye |
identity | Hummingbird |
if-feature | Hummingbird |
import | Goldeneye Enhancement in Hummingbird |
include | Goldeneye Enhancement in Hummingbird |
input | Goldeneye |
key | Goldeneye |
leaf | Falcon |
leaf-list | Falcon |
length | Goldeneye |
list | Falcon |
mandatory | Falcon |
max-elements | Goldeneye |
min-elements | Goldeneye |
module | Falcon |
must | Hummingbird |
namespace | Goldeneye |
notification | Goldeneye |
ordered-by | Not planned |
organization | Goldeneye Enhancement in Hummingbird |
output | Goldeneye |
path | Hummingbird |
pattern | Goldeneye |
position | Goldeneye |
prefix | Goldeneye |
presence | Goldeneye |
range | Goldeneye |
reference | Goldeneye Enhancement in Hummingbird |
refine | Not planned |
require-instance | Hummingbird |
revision | Goldeneye Enhancement in Hummingbird |
revision-date | Goldeneye |
rpc | Goldeneye |
status | Goldeneye Enhancement in Hummingbird |
submodule | Goldeneye |
type | Goldeneye |
typedef | Goldeneye |
unique | Not Planned |
units | Goldeneye |
uses | Goldeneye Enhancement in Hummingbird |
value | Goldeneye |
when | Hummingbird |
yang-version | Goldeneye |
yin-element | Not Planned |
Built-in YANG data types support/plan
Binary | Goldeneye Enhancement in Hummingbird |
Bits | Goldeneye Enhancement in Hummingbird |
boolean | Goldeneye |
decimal64 | Goldeneye Enhancement in Hummingbird |
empty | Goldeneye |
enumeration | Goldeneye |
identityref | Hummingbird |
instance-identifier | Hummingbird |
int8 | Goldeneye |
int16 | Goldeneye |
int32 | Goldeneye |
int64 | Goldeneye |
leafref | Hummingbird |
string | Falcon |
uint8 | Goldeneye |
uint16 | Goldeneye |
uint32 | Goldeneye |
uint64 | Goldeneye |
union | Goldeneye |
Generated JAVA Details
Common behavior
Identifier
The identifier name of YANG constructs are taken, and are used in java by converting it to lower camel case. Identifier names are allowed to have three special characters such as “-”, ”_”, “.”. Whereas, in java, we cannot use these special characters. These characters will be removed during conversion. Conversion takes place by following the below rules of lower camel case.
The first letter of the identifier will be a small letter. If the three special characters occur alone or in group, they will be removed and the consecutive letter will be capitalized.
name-conversion will be mapped as nameConversion
yang-._constuct-generation will be mapped as yangConstuctGeneration
When identifier name has a special character followed by a number, the following letter from the digits will be capitalized.
yang_123construct will be mapped to yang123Construct
In java file, class name or attribute name cannot have java keyword or start with digits. During the conversion into java, we add prefix to the identifier “yangAutoPrefix”, by default.
_123date will be mapped to yangAutoPrefix123Date
const will be mapped to yangAutoPrefixConst
As per camelcase conversion rules, no two consecutive letters will have capitalization and the last letter will also not be capitalized.
- ca-l.e_nder will be mapped to caLeNder
- tric-._k will be mapped to trick
If users input has capital case, the following will be the conversion methods.
TESTNAME will be mapped to testname
TEST-NAME will be mapped to testName
TestName will be mapped to testName
TEST3NAME will be mapped to test3Name
When the identifier has to be used as java class name, after the above conversion, the first letter will be capitalized and if consecutive capital letters are present, it will be corrected and assigned as java class name.
If an identifier for a construct contains java keywords, then it name will be prefixed with "yangAutoPrefix" in generated code.
Namespace
The namespace is a mandatory statement in the module. We define namespace for URL/URI and for folder structure of generated java code. Here in ONOS YANG plugin, namespace forms a folder structure which in turn will be the package name in java.
The package will have “org.onosproject.yang.gen.v1.” by default in it. The namespace will be added to the above and the folder structure will also be formed respectively. This becomes the parent package. The conversion from YANG namespace to the java package will take place as below.
The complete namespace will be changed to lowercase letters. When special characters or a group of special characters are found, it replaces those characters by dot.
"http://acme.example.com/system" will be mapped as org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20160427
In java the package cannot have folder name which begins with digits or java keyword. Incase if found in YANG file these will be converted by adding prefix “yangautoprefix”.
http://acme.123example.com/try" will be mapped as org.onosproject.yang.gen.v1.http.acme.yangautoprefix123example.com.yangautoprefixtry.rev20160427
- At the end of the package the revision in module will be added by the string rev<yyyymmdd>.If the revision does not exist in the YANG file current date will be appended to the package.
When a node appears, with child node in it, a new package will be generated under the parent package, for that node. The new package is, parent package appended with the node name. The class for that node will be placed under this newly created package.
Example
File : acme-system.yang module acme-system { namespace "http://acme.example.com/system"; prefix "acme"; organization "ACME Inc."; contact "joe@acme.example.com"; description "The module for entities implementing the ACME system."; revision 2007-06-09 { description "Initial revision."; } container system { container login { leaf message { type string; description "Message given at start of login session"; } } } . . . }
File : System.java package org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem; . . . public interface System { . . . } File : Login.java package org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem.system; . . . public interface Login { . . . }
Javadocs
Currently Java doc will be generated as per ONOS javadoc guidelines.
YANG statements
Module
Overview
The primary unit of YANG is module. The module statement groups all the statements that belong to module together. The module statement argument is name of the module followed by sub-statements.
JAVA mapping
Module statement is mapped to
- Service interface
It includes:
a) java methods corresponding to the YANG RPC (Refer RPC section for more details)
b) If module contains notification, generated service interface will extend listener service (refer notification for more details).The name of service interface is <module_name>Service.java .
c) If module contains augment the get and setter for augmented module will be generated. - Interface and implementation class (Note: for module implementation class will have name xxxxOpParam.java)
Example
File : network.yang module network { yang-version 1; namespace "urn:TBD:params:xml:ns:yang:nodes"; prefix nd; organization "TBD"; contact "WILL-BE-DEFINED-LATER"; description "This module defines a common base model for a collection of nodes in a network. Node definitions s are further used in network topologies and inventories."; revision 2014-03-09 { description "Initial revision."; reference "draft-clemm-i2rs-yang-network-topo-04"; } list networklist { key "network-id"; leaf network-id { type string; } leaf server-provided { type boolean; config false; } } …. }
File : NetworkService.java package org.onosproject.yang.gen.v1.urn.tbd.params.xml.ns.yang.nodes.rev20140309; public interface NetworkService { Network getNetwork(); void setNetwork(Network network); } File : Network.java package org.onosproject.yang.gen.v1.urn.tbd.params.xml.ns.yang.nodes.rev20140309; import org.onosproject.yang.gen.v1.urn.tbd.params.xml.ns.yang.nodes.rev20140309.network.Networklist; import java.util.List; public interface Network { public static enum OnosYangOpType { MERGE, REPLACE, CREATE, DELETE, REMOVE, NONE } OnosYangOpType yangNetworkOpType(); List<Networklist> networklist(); interface NetworkBuilder { NetworkBuilder addToNetworklist(Networklist addTo); OnosYangOpType yangNetworkOpType(); List<Networklist> networklist(); NetworkBuilder yangNetworkOpType(OnosYangOpType yangNetworkOpType); NetworkBuilder networklist(List<Networklist> networklist); Network build(); } } File: NetworkOpParam.java package org.onosproject.yang.gen.v1.urn.tbd.params.xml.ns.yang.nodes.rev20140309; import com.google.common.base.MoreObjects; import java.util.ArrayList; import java.util.BitSet; import java.util.List; import java.util.Objects; import org.onosproject.yang.gen.v1.urn.tbd.params.xml.ns.yang.nodes.rev20140309.network.DefaultNetworklist; import org.onosproject.yang.gen.v1.urn.tbd.params.xml.ns.yang.nodes.rev20140309.network.Networklist; public class NetworkOpParam implements Network { protected OnosYangOpType yangNetworkOpType; protected boolean isSubTreeFiltered; protected List<Networklist> networklist; @Override public OnosYangOpType yangNetworkOpType() { return yangNetworkOpType; } public boolean isSubTreeFiltered() { return isSubTreeFiltered; } @Override public List<Networklist> networklist() { return networklist; } @Override public int hashCode() { return Objects.hash(yangNetworkOpType, isSubTreeFiltered, networklist); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof NetworkOpParam) { NetworkOpParam other = (NetworkOpParam) obj; return Objects.equals(yangNetworkOpType, other.yangNetworkOpType) && Objects.equals(isSubTreeFiltered, other.isSubTreeFiltered) && Objects.equals(networklist, other.networklist); } return false; } @Override public String toString() { return MoreObjects.toStringHelper(getClass()) .omitNullValues() .add("yangNetworkOpType", yangNetworkOpType) .add("isSubTreeFiltered", isSubTreeFiltered) .add("networklist", networklist) .toString(); } protected NetworkOpParam(NetworkBuilder builderObject) { yangNetworkOpType = builderObject.yangNetworkOpType(); isSubTreeFiltered = builderObject.isSubTreeFiltered(); networklist = builderObject.networklist(); } public NetworkOpParam processSubtreeFiltering(Network appInstance, boolean isSelectAllSchemaChild) { NetworkBuilder subTreeFilteringResultBuilder = new NetworkBuilder(); BitSet isAnySelectOrContainmentNode = new BitSet(); if (!processChildNodesSubTreeFiltering(appInstance, subTreeFilteringResultBuilder, isAnySelectOrContainmentNode, isSelectAllSchemaChild)) { return null; } if (!isSelectAllSchemaChild && !isAnySelectOrContainmentNode.get(0)) { return processSubtreeFiltering(appInstance, true); } return (NetworkOpParam) subTreeFilteringResultBuilder.buildForFilter(); } private boolean processChildNodesSubTreeFiltering(Network appInstance, NetworkBuilder subTreeFilteringResultBuilder, BitSet isAnySelectOrContainmentNode, boolean isSelectAllSchemaChild) { if (isSelectAllSchemaChild) { if (appInstance.networklist() != null) { for (Networklist networklist : appInstance.networklist()) { Networklist result; result = ((DefaultNetworklist) DefaultNetworklist.builder() .buildForFilter()).processSubtreeFiltering(networklist, true); subTreeFilteringResultBuilder.addToNetworklist(result); } } else { if (isSubTreeFiltered && networklist() != null) { subTreeFilteringResultBuilder.networklist(networklist); } } } else if (networklist() != null) { isAnySelectOrContainmentNode.set(0); if (!networklist().isEmpty()) { if (appInstance.networklist() != null && !appInstance.networklist().isEmpty()) { for (Networklist networklist : networklist()) { for (Networklist networklist2 : appInstance.networklist()) { Networklist result = ((DefaultNetworklist) networklist) .processSubtreeFiltering(networklist2, false); if (result != null) { subTreeFilteringResultBuilder.addToNetworklist(result); } } } } else { if (isSubTreeFiltered && networklist() != null) { subTreeFilteringResultBuilder.networklist(networklist); } } } else { if (appInstance.networklist() != null && !appInstance.networklist().isEmpty()) { for (Networklist networklist : appInstance.networklist()) { subTreeFilteringResultBuilder.addToNetworklist(networklist); } } } } return true; } protected NetworkOpParam() { } public static NetworkBuilder builder() { return new NetworkBuilder(); } public static class NetworkBuilder implements Network.NetworkBuilder { protected OnosYangOpType yangNetworkOpType; protected boolean isSubTreeFiltered; protected List<Networklist> networklist; @Override public OnosYangOpType yangNetworkOpType() { return yangNetworkOpType; } public boolean isSubTreeFiltered() { return isSubTreeFiltered; } @Override public List<Networklist> networklist() { return networklist; } @Override public NetworkBuilder yangNetworkOpType(OnosYangOpType yangNetworkOpType) { this.yangNetworkOpType = yangNetworkOpType; return this; } public NetworkBuilder isSubTreeFiltered(boolean isSubTreeFiltered) { this.isSubTreeFiltered = isSubTreeFiltered; return this; } @Override public NetworkBuilder networklist(List<Networklist> networklist) { this.networklist = networklist; return this; } @Override public NetworkBuilder addToNetworklist(Networklist addTo) { if (networklist == null) { networklist = new ArrayList<>(); } networklist.add(addTo); return this; } @Override public Network build() { return new NetworkOpParam(this); } public Network buildForFilter() { isSubTreeFiltered = true; return new NetworkOpParam(this); } public NetworkBuilder() { } } }
File : network.yang with an augment node. module network { yang-version 1; namespace "urn:TBD:params:xml:ns:yang:nodes"; prefix nd; organization "TBD"; contact "WILL-BE-DEFINED-LATER"; description "This module defines a common base model for a collection of nodes in a network. Node definitions s are further used in network topologies and inventories."; revision 2014-03-09 { description "Initial revision."; reference "draft-clemm-i2rs-yang-network-topo-04"; } list networklist { key "network-id"; leaf network-id { type string; } leaf server-provided { type boolean; config false; } } augment /networklist { leaf network-ip { type int32; } } .... }
File : NetworkService.java package org.onosproject.yang.gen.v1.urn.tbd.params.xml.ns.yang.nodes.rev20140309; public interface NetworkService { Network getNetwork(); void setNetwork(Network network); Network getAugmentedNetworkNetworklist(); void setAugmentedNetworkNetworklist(Network augmentedNetworkNetworklist); } Note: Other classes will remain same.
Sub Module
Overview
The “submodule” groups all the statements that belongs to the submodule together. The "submodule" statement's argument is the name of the submodule, followed by a block of sub statements.
JAVA mapping
Submodule mapping to java is same as module and files with be generated in module’s namespace.
Example
File : acme-system.yang module acme-system { namespace "http://yang-central.org/ns/example/acme"; prefix acme; include "acme-types"; container access { leaf id { type uint32; } } } File : acme-types.yang submodule acme-types { yang-version 1; belongs-to "acme-system" { prefix "acme"; } container access { leaf access-timeout { type uint32; } leaf retries { type uint8; } } }
File : AcmeSystemService.java package org.onosproject.yang.gen.v1.http.yang.central.org.ns.example.acme.rev20160720; public interface AcmeSystemService { AcmeSystem getAcmeSystem(); void setAcmeSystem(AcmeSystem acmeSystem); } File : AcmeTypesService.java package org.onosproject.yang.gen.v1.http.yang.central.org.ns.example.acme.rev20160720; public interface AcmeTypesService { AcmeTypes getAcmeTypes(); void setAcmeTypes(AcmeTypes acmeTypes); } Note: code generation will be same as module.
Prefix
Overview
Prefix is used to define prefix associated with module. It is used as a hint to other module developers when they import our module.
JAVA mapping
There is no java mapping for prefix statement.
Example
module dhcp { namespace "http://yang-central.org/ns/example/dhcp"; prefix dhcp; import ietf-yang-types { prefix yang; } import ietf-inet-types { prefix inet; } }
Note the prefixes above. In order to refer to the yang-module from now on, we use the prefix, e.g. the statement:
type yang:date-and-time;
refers to the date-and-time type defined in the yang-types module.
We use the prefix defined in the module itself, e.g. in the yang-types module, the prefix is defined as yang. You can use which prefix you want in your import, as long as it is unique within the module, but by using the prefix from the module, your module will be easier to read for others.
Import
Overview
A module can import definitions from other module or submodule by using import statement. It takes an argument, the name of the module or submodule followed by sub statements prefix and revision statement. Multiple import statements may be specified to import from different modules. Prefix statement inside import is mandatory and its scope is within the imported module or sub-module.
JAVA mapping
When imported YANG file is used in any of the nodes in current YANG file, then Java code will genereted for imported YANG file. If it is imported YANG file is not used in any of the node in current YANG file then Java code for imported file will not be genereted.
Example
File : flow-classifier.yang module flow-classifier { yang-version 1; namespace "sfc.flowclassifier"; prefix "flow-classifier"; import "ietf-yang-types" { prefix "yang"; } organization "ON-LAB"; description "This submodule defines for flow classifier."; revision "2016-05-24" { description "Initial revision."; } leaf id { type yang:uuid; } } File : ietf-yang-types.yang module ietf-yang-types { namespace "urn:ietf:params:xml:ns:yang:ietf-yang-types"; prefix "yang"; organization "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; contact "WG Web: <http://tools.ietf.org/wg/netmod/> WG List: <mailto:netmod@ietf.org> WG Chair: David Kessens <mailto:david.kessens@nsn.com> WG Chair: Juergen Schoenwaelder <mailto:j.schoenwaelder@jacobs-university.de> Editor: Juergen Schoenwaelder <mailto:j.schoenwaelder@jacobs-university.de>"; description "This module contains a collection of generally useful derived YANG data types. Copyright (c) 2013 IETF Trust and the persons identified as authors of the code. All rights reserved. Redistribution and use in source and binary forms, with or without modification, is permitted pursuant to, and subject to the license terms contained in, the Simplified BSD License set forth in Section 4.c of the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info). This version of this YANG module is part of RFC 6991; see the RFC itself for full legal notices."; revision 2013-07-15 { description "This revision adds the following new data types: - yang-identifier - hex-string - uuid - dotted-quad"; reference "RFC 6991: Common YANG Data Types"; } revision 2010-09-24 { description "Initial revision."; reference "RFC 6021: Common YANG Data Types"; } typedef uuid { type string { pattern '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-' + '[0-9a-fA-F]{4}-[0-9a-fA-F]{12}'; } description "A Universally Unique IDentifier in the string representation defined in RFC 4122. The canonical representation uses lowercase characters. The following is an example of a UUID in string representation: f81d4fae-7dec-11d0-a765-00a0c91e6bf6 "; reference "RFC 4122: A Universally Unique IDentifier (UUID) URN Namespace"; } }
File : FlowClassifierService package org.onosproject.yang.gen.v1.sfc.flowclassifier.rev20160524; public interface FlowClassifierService { FlowClassifier getFlowClassifier(); void setFlowClassifier(FlowClassifier flowClassifier); } File : IetfYangTypesService.java package org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev20130715; public interface IetfYangTypesService { IetfYangTypes getIetfYangTypes(); void setIetfYangTypes(IetfYangTypes ietfYangTypes); } File : Uuid.java package org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev20100924.ietfyangtypes; import java.util.Objects; import com.google.common.base.MoreObjects; public final class Uuid { private String string; private Uuid() { } public Uuid(String value) { this.string = value; } public static Uuid of(String value) { return new Uuid(value); } public String string() { return string; } @Override public int hashCode() { return Objects.hash(string); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof Uuid) { Uuid other = (Uuid) obj; return Objects.equals(string, other.string); } return false; } @Override public String toString() { return MoreObjects.toStringHelper(getClass()) .add("string", string) .toString(); } public static Uuid fromString(String valInString) { try { String tmpVal = (valInString); return of(tmpVal); } catch (Exception e) { } return null; } }
Include
Overview
A module uses a include statement to include sub-module that belongs to module. The argument is the name of sub-module. Modules are only allowed to include sub-module that belongs to module, as defined by belongs-to statement. When a module includes a submodule, it incorporates the contents of the submodule into the node hierarchy of the module.
JAVA mapping
There is no java mapping for include statement.
Example
Please refer submodule example
Organization
Overview
The "organization" statement defines the party responsible for this module. The argument is a string that is used to specify a textual description of the organization(s) under whose auspices this module was developed.
JAVA mapping
Organization will be used as javadoc in generated java code in Hummingbird release version. Currently it is not used in generated java code.
Example
Please refer module example section
Contact
Overview
The "contact" statement provides contact information for the module. The argument is a string that is used to specify contact information for the person or persons to whom technical queries concerning this module should be sent, such as their name, postal address, telephone number, and electronic mail address.
JAVA mapping
Contact information will be used as javadoc in generated java code in Hummingbird release version. Currently it is not used in generated java code.
Example
Please refer module example section
Belongs to
Overview
The "belongs-to" statement specifies the module to which the submodule belongs. The argument is an identifier that is the name of the module. A submodule must only be included by the module to which it belongs, or by another submodule that belongs to that module.
JAVA mapping
No java mapping for belongs to statement in generated code.
Example
Please refer submodule example section.
Leaf
Overview
A leaf is an atomic element in YANG. It has value, but does not have child. It is used for defining the scalar variable of a built-in type or a derived type.
Java mapping
In java leaf is converted to define variable with its respective java built-in type or derived type.
Example
File : acme-system.yang module acme-system { namespace "http://acme.example.com/system"; prefix "acme"; organization "ACME Inc."; contact "joe@acme.example.com"; description "The module for entities implementing the ACME system."; revision 2007-06-09 { description "Initial revision."; } container system { leaf host-name { type string; description "Hostname for this system"; } } . . . }
File: System.java package org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem; import java.util.BitSet; import java.util.Map; import org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.AcmeSystem.OnosYangOpType; public interface System { public enum LeafIdentifier { HOSTNAME(1); private int leafIndex; public int getLeafIndex() { return leafIndex; } LeafIdentifier(int value) { this.leafIndex = value; } } String hostName(); BitSet valueLeafFlags(); OnosYangOpType yangSystemOpType(); BitSet selectLeafFlags(); Map<Class<?>, Object> yangAugmentedInfoMap(); Object yangAugmentedInfo(Class classObject); boolean isLeafValueSet(LeafIdentifier leaf); boolean isSelectLeaf(LeafIdentifier leaf); interface SystemBuilder { String hostName(); BitSet valueLeafFlags(); OnosYangOpType yangSystemOpType(); BitSet selectLeafFlags(); Map<Class<?>, Object> yangAugmentedInfoMap(); SystemBuilder hostName(String hostName); SystemBuilder yangSystemOpType(OnosYangOpType yangSystemOpType); SystemBuilder addYangAugmentedInfo(Object value, Class classObject); Object yangAugmentedInfo(Class classObject); SystemBuilder selectLeaf(LeafIdentifier leaf); System build(); } } File : DefaultSystem.java package org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem; import com.google.common.base.MoreObjects; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.BitSet; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Objects; import java.util.Set; import org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.AcmeSystem.OnosYangOpType; public class DefaultSystem implements System { protected String hostName; protected BitSet valueLeafFlags = new BitSet(); protected OnosYangOpType yangSystemOpType; protected boolean isSubTreeFiltered; protected BitSet selectLeafFlags = new BitSet(); protected Map<Class<?>, Object> yangAugmentedInfoMap = new HashMap<>(); @Override public String hostName() { return hostName; } @Override public BitSet valueLeafFlags() { return valueLeafFlags; } @Override public OnosYangOpType yangSystemOpType() { return yangSystemOpType; } public boolean isSubTreeFiltered() { return isSubTreeFiltered; } @Override public BitSet selectLeafFlags() { return selectLeafFlags; } @Override public Map<Class<?>, Object> yangAugmentedInfoMap() { return yangAugmentedInfoMap; } @Override public int hashCode() { return Objects.hash(hostName, valueLeafFlags, yangSystemOpType, isSubTreeFiltered, selectLeafFlags, yangAugmentedInfoMap); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof DefaultSystem) { DefaultSystem other = (DefaultSystem) obj; return Objects.equals(hostName, other.hostName) && Objects.equals(valueLeafFlags, other.valueLeafFlags) && Objects.equals(yangSystemOpType, other.yangSystemOpType) && Objects.equals(isSubTreeFiltered, other.isSubTreeFiltered) && Objects.equals(selectLeafFlags, other.selectLeafFlags) && Objects.equals(yangAugmentedInfoMap, other.yangAugmentedInfoMap); } return false; } @Override public String toString() { return MoreObjects.toStringHelper(getClass()) .omitNullValues() .add("hostName", hostName) .add("valueLeafFlags", valueLeafFlags) .add("yangSystemOpType", yangSystemOpType) .add("isSubTreeFiltered", isSubTreeFiltered) .add("selectLeafFlags", selectLeafFlags) .add("yangAugmentedInfoMap", yangAugmentedInfoMap) .toString(); } @Override public Object yangAugmentedInfo(Class classObject) { return yangAugmentedInfoMap.get(classObject); } protected DefaultSystem(SystemBuilder builderObject) { hostName = builderObject.hostName(); valueLeafFlags = builderObject.valueLeafFlags(); yangSystemOpType = builderObject.yangSystemOpType(); isSubTreeFiltered = builderObject.isSubTreeFiltered(); selectLeafFlags = builderObject.selectLeafFlags(); yangAugmentedInfoMap = builderObject.yangAugmentedInfoMap(); } public DefaultSystem processSubtreeFiltering(System appInstance, boolean isSelectAllSchemaChild) { SystemBuilder subTreeFilteringResultBuilder = new SystemBuilder(); BitSet isAnySelectOrContainmentNode = new BitSet(); if (!processLeafSubtreeFiltering(appInstance, subTreeFilteringResultBuilder, isAnySelectOrContainmentNode, isSelectAllSchemaChild)) { return null; } if (yangAugmentedInfoMap.isEmpty()) { Set<Map.Entry<Class<?>, Object>> augment = appInstance.yangAugmentedInfoMap().entrySet(); if (augment != null && !augment.isEmpty()) { Iterator<Map.Entry<Class<?>, Object>> augItr = augment.iterator(); while (augItr.hasNext()) { Map.Entry<Class<?>, Object> aug = augItr.next(); Class<?> augClass = aug.getKey(); String augClassName = augClass.getName(); int index = augClassName.lastIndexOf('.'); String classPackage = augClassName.substring(0, index) + "." + "Default" + augClass.getSimpleName() + "$" + augClass.getSimpleName() + "Builder"; ClassLoader classLoader = augClass.getClassLoader(); try { Class<?> builderClass; builderClass = classLoader.loadClass(classPackage); Object builderObj = builderClass.newInstance(); Method method = builderClass.getMethod("build"); Object defaultObj = method.invoke(builderObj); Class<?> defaultClass = defaultObj.getClass(); method = defaultClass.getMethod ("processSubtreeFiltering", augClass, boolean.class); Object result = method.invoke(defaultObj, aug.getValue(), true); subTreeFilteringResultBuilder .addYangAugmentedInfo(result, augClass); } catch (ClassNotFoundException | InstantiationException | NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { e.printStackTrace(); } } } } else { Set<Map.Entry<Class<?>, Object>> augment = yangAugmentedInfoMap .entrySet(); Iterator<Map.Entry<Class<?>, Object>> augItr = augment.iterator(); while (augItr.hasNext()) { Map.Entry<Class<?>, Object> aug = augItr.next(); Class<?> augClass = aug.getKey(); Object appInstanceInfo = appInstance.yangAugmentedInfo(augClass); if (appInstanceInfo == null) { subTreeFilteringResultBuilder.addYangAugmentedInfo (aug.getValue(), aug.getKey()); } else { Object processSubtreeFiltering; try { processSubtreeFiltering = aug.getValue().getClass() .getMethod("processSubtreeFiltering", aug.getKey(), boolean.class) .invoke(aug.getValue(), appInstanceInfo, true); if (processSubtreeFiltering != null) { subTreeFilteringResultBuilder .addYangAugmentedInfo(processSubtreeFiltering, aug.getKey()); } } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { e.printStackTrace(); } } } } if (!isSelectAllSchemaChild && !isAnySelectOrContainmentNode.get(0)) { return processSubtreeFiltering(appInstance, true); } return (DefaultSystem) subTreeFilteringResultBuilder.buildForFilter(); } private boolean processLeafSubtreeFiltering(System appInstance, SystemBuilder subTreeFilteringResultBuilder, BitSet isAnySelectOrContainmentNode, boolean isSelectAllSchemaChild) { if (valueLeafFlags.get(LeafIdentifier.HOSTNAME.getLeafIndex())) { if (appInstance.hostName() == null || !(hostName().equals(appInstance.hostName()))) { if (isSubTreeFiltered && !appInstance.isLeafValueSet(LeafIdentifier.HOSTNAME)) { subTreeFilteringResultBuilder.hostName(hostName()); } else { return false; } } else { subTreeFilteringResultBuilder.hostName(appInstance.hostName()); } } else if (selectLeafFlags.get(LeafIdentifier.HOSTNAME.getLeafIndex()) || isSelectAllSchemaChild) { isAnySelectOrContainmentNode.set(0); subTreeFilteringResultBuilder.hostName(appInstance.hostName()); } return true; } protected DefaultSystem() { } public static SystemBuilder builder() { return new SystemBuilder(); } @Override public boolean isLeafValueSet(LeafIdentifier leaf) { return valueLeafFlags.get(leaf.getLeafIndex()); } @Override public boolean isSelectLeaf(LeafIdentifier leaf) { return selectLeafFlags.get(leaf.getLeafIndex()); } public static class SystemBuilder implements System.SystemBuilder { protected String hostName; protected BitSet valueLeafFlags = new BitSet(); protected OnosYangOpType yangSystemOpType; protected boolean isSubTreeFiltered; protected BitSet selectLeafFlags = new BitSet(); protected Map<Class<?>, Object> yangAugmentedInfoMap = new HashMap<>(); @Override public String hostName() { return hostName; } @Override public BitSet valueLeafFlags() { return valueLeafFlags; } @Override public OnosYangOpType yangSystemOpType() { return yangSystemOpType; } public boolean isSubTreeFiltered() { return isSubTreeFiltered; } @Override public BitSet selectLeafFlags() { return selectLeafFlags; } @Override public Map<Class<?>, Object> yangAugmentedInfoMap() { return yangAugmentedInfoMap; } @Override public SystemBuilder hostName(String hostName) { valueLeafFlags.set(LeafIdentifier.HOSTNAME.getLeafIndex()); this.hostName = hostName; return this; } @Override public SystemBuilder yangSystemOpType(OnosYangOpType yangSystemOpType) { this.yangSystemOpType = yangSystemOpType; return this; } public SystemBuilder isSubTreeFiltered(boolean isSubTreeFiltered) { this.isSubTreeFiltered = isSubTreeFiltered; return this; } @Override public SystemBuilder selectLeaf(LeafIdentifier leaf) { selectLeafFlags.set(leaf.getLeafIndex()); return this; } @Override public SystemBuilder addYangAugmentedInfo(Object value, Class classObject) { yangAugmentedInfoMap.put(classObject, value); return this; } @Override public Object yangAugmentedInfo(Class classObject) { return yangAugmentedInfoMap.get(classObject); } @Override public System build() { return new DefaultSystem(this); } public System buildForFilter() { isSubTreeFiltered = true; return new DefaultSystem(this); } public SystemBuilder() { } } }
Leaf-list
Overview
A leaf-list is also used for defining scalar variable, like leaf, but in an array of a particular type. The type of the variable can be either built-in type or a derived type.
Java mapping
In java leaf-list is stored in List, with respect to, java built-in type or derived type.
Example
File : acme-system.yang module acme-system { namespace "http://acme.example.com/system"; prefix "acme"; organization "ACME Inc."; contact "joe@acme.example.com"; description "The module for entities implementing the ACME system."; revision 2007-06-09 { description "Initial revision."; } container system { leaf-list domain-search { type string; description "List of domain names to search"; } } . . . }
File : System.java package org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem; import java.util.List; import java.util.Map; import org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.AcmeSystem.OnosYangOpType; public interface System { List<String> domainSearch(); OnosYangOpType yangSystemOpType(); Map<Class<?>, Object> yangAugmentedInfoMap(); Object yangAugmentedInfo(Class classObject); interface SystemBuilder { SystemBuilder addToDomainSearch(String addTo); List<String> domainSearch(); OnosYangOpType yangSystemOpType(); Map<Class<?>, Object> yangAugmentedInfoMap(); SystemBuilder domainSearch(List<String> domainSearch); SystemBuilder yangSystemOpType(OnosYangOpType yangSystemOpType); SystemBuilder addYangAugmentedInfo(Object value, Class classObject); Object yangAugmentedInfo(Class classObject); System build(); } } File : DefaultSystem.java package org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem; import com.google.common.base.MoreObjects; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.BitSet; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.AcmeSystem.OnosYangOpType; public class DefaultSystem implements System { protected List<String> domainSearch; protected OnosYangOpType yangSystemOpType; protected boolean isSubTreeFiltered; protected Map<Class<?>, Object> yangAugmentedInfoMap = new HashMap<>(); @Override public List<String> domainSearch() { return domainSearch; } @Override public OnosYangOpType yangSystemOpType() { return yangSystemOpType; } public boolean isSubTreeFiltered() { return isSubTreeFiltered; } @Override public Map<Class<?>, Object> yangAugmentedInfoMap() { return yangAugmentedInfoMap; } @Override public int hashCode() { return Objects.hash(domainSearch, yangSystemOpType, isSubTreeFiltered, yangAugmentedInfoMap); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof DefaultSystem) { DefaultSystem other = (DefaultSystem) obj; return Objects.equals(domainSearch, other.domainSearch) && Objects.equals(yangSystemOpType, other.yangSystemOpType) && Objects.equals(isSubTreeFiltered, other.isSubTreeFiltered) && Objects.equals(yangAugmentedInfoMap, other.yangAugmentedInfoMap); } return false; } @Override public String toString() { return MoreObjects.toStringHelper(getClass()) .omitNullValues() .add("domainSearch", domainSearch) .add("yangSystemOpType", yangSystemOpType) .add("isSubTreeFiltered", isSubTreeFiltered) .add("yangAugmentedInfoMap", yangAugmentedInfoMap) .toString(); } @Override public Object yangAugmentedInfo(Class classObject) { return yangAugmentedInfoMap.get(classObject); } protected DefaultSystem(SystemBuilder builderObject) { domainSearch = builderObject.domainSearch(); yangSystemOpType = builderObject.yangSystemOpType(); isSubTreeFiltered = builderObject.isSubTreeFiltered(); yangAugmentedInfoMap = builderObject.yangAugmentedInfoMap(); } public DefaultSystem processSubtreeFiltering(System appInstance, boolean isSelectAllSchemaChild) { SystemBuilder subTreeFilteringResultBuilder = new SystemBuilder(); BitSet isAnySelectOrContainmentNode = new BitSet(); if (!processLeafListSubTreeFiltering(appInstance, subTreeFilteringResultBuilder, isAnySelectOrContainmentNode, isSelectAllSchemaChild)) { return null; } if (yangAugmentedInfoMap.isEmpty()) { Set<Map.Entry<Class<?>, Object>> augment = appInstance.yangAugmentedInfoMap().entrySet(); if (augment != null && !augment.isEmpty()) { Iterator<Map.Entry<Class<?>, Object>> augItr = augment.iterator(); while (augItr.hasNext()) { Map.Entry<Class<?>, Object> aug = augItr.next(); Class<?> augClass = aug.getKey(); String augClassName = augClass.getName(); int index = augClassName.lastIndexOf('.'); String classPackage = augClassName.substring(0, index) + "." + "Default" + augClass.getSimpleName() + "$" + augClass.getSimpleName() + "Builder"; ClassLoader classLoader = augClass.getClassLoader(); try { Class<?> builderClass; builderClass = classLoader.loadClass(classPackage); Object builderObj = builderClass.newInstance(); Method method = builderClass.getMethod("build"); Object defaultObj = method.invoke(builderObj); Class<?> defaultClass = defaultObj.getClass(); method = defaultClass.getMethod ("processSubtreeFiltering", augClass, boolean.class); Object result = method.invoke(defaultObj, aug.getValue(), true); subTreeFilteringResultBuilder .addYangAugmentedInfo(result, augClass); } catch (ClassNotFoundException | InstantiationException | NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { e.printStackTrace(); } } } } else { Set<Map.Entry<Class<?>, Object>> augment = yangAugmentedInfoMap .entrySet(); Iterator<Map.Entry<Class<?>, Object>> augItr = augment.iterator(); while (augItr.hasNext()) { Map.Entry<Class<?>, Object> aug = augItr.next(); Class<?> augClass = aug.getKey(); Object appInstanceInfo = appInstance.yangAugmentedInfo(augClass); if (appInstanceInfo == null) { subTreeFilteringResultBuilder.addYangAugmentedInfo (aug.getValue(), aug.getKey()); } else { Object processSubtreeFiltering; try { processSubtreeFiltering = aug.getValue().getClass() .getMethod("processSubtreeFiltering", aug.getKey(), boolean.class) .invoke(aug.getValue(), appInstanceInfo, true); if (processSubtreeFiltering != null) { subTreeFilteringResultBuilder .addYangAugmentedInfo(processSubtreeFiltering, aug.getKey()); } } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { e.printStackTrace(); } } } } if (!isSelectAllSchemaChild && !isAnySelectOrContainmentNode.get(0)) { return processSubtreeFiltering(appInstance, true); } return (DefaultSystem) subTreeFilteringResultBuilder.buildForFilter(); } private boolean processLeafListSubTreeFiltering(System appInstance, SystemBuilder subTreeFilteringResultBuilder, BitSet isAnySelectOrContainmentNode, boolean isSelectAllSchemaChild) { if (isSelectAllSchemaChild) { if (appInstance.domainSearch() != null) { for (String domainSearch : appInstance.domainSearch()) { subTreeFilteringResultBuilder.addToDomainSearch(domainSearch); } } else { if (isSubTreeFiltered && domainSearch() != null) { subTreeFilteringResultBuilder.domainSearch(domainSearch); } } } else if (domainSearch() != null) { if (!domainSearch().isEmpty()) { if (appInstance.domainSearch() == null || appInstance.domainSearch().isEmpty()) { return false; } for (String domainSearch : domainSearch()) { boolean flag = false; for (String domainSearch2 : appInstance.domainSearch()) { if (domainSearch.equals(domainSearch2)) { flag = true; subTreeFilteringResultBuilder.addToDomainSearch(domainSearch2); break; } } if (!flag) { return false; } } } else { isAnySelectOrContainmentNode.set(0); if (appInstance.domainSearch() != null && !appInstance.domainSearch().isEmpty()) { for (String domainSearch : appInstance.domainSearch()) { subTreeFilteringResultBuilder.addToDomainSearch(domainSearch); } } } } return true; } protected DefaultSystem() { } public static SystemBuilder builder() { return new SystemBuilder(); } public static class SystemBuilder implements System.SystemBuilder { protected List<String> domainSearch; protected OnosYangOpType yangSystemOpType; protected boolean isSubTreeFiltered; protected Map<Class<?>, Object> yangAugmentedInfoMap = new HashMap<>(); @Override public List<String> domainSearch() { return domainSearch; } @Override public OnosYangOpType yangSystemOpType() { return yangSystemOpType; } public boolean isSubTreeFiltered() { return isSubTreeFiltered; } @Override public Map<Class<?>, Object> yangAugmentedInfoMap() { return yangAugmentedInfoMap; } @Override public SystemBuilder domainSearch(List<String> domainSearch) { this.domainSearch = domainSearch; return this; } @Override public SystemBuilder yangSystemOpType(OnosYangOpType yangSystemOpType) { this.yangSystemOpType = yangSystemOpType; return this; } public SystemBuilder isSubTreeFiltered(boolean isSubTreeFiltered) { this.isSubTreeFiltered = isSubTreeFiltered; return this; } @Override public SystemBuilder addToDomainSearch(String addTo) { if (domainSearch == null) { domainSearch = new ArrayList<>(); } domainSearch.add(addTo); return this; } @Override public SystemBuilder addYangAugmentedInfo(Object value, Class classObject) { yangAugmentedInfoMap.put(classObject, value); return this; } @Override public Object yangAugmentedInfo(Class classObject) { return yangAugmentedInfoMap.get(classObject); } @Override public System build() { return new DefaultSystem(this); } public System buildForFilter() { isSubTreeFiltered = true; return new DefaultSystem(this); } public SystemBuilder() { } } }
Container
Overview
Container is a holder that can hold many nodes within it. It is used for logically grouping certain set of nodes.
Java mapping
In java, container acts as a class which can hold information contained within. A class of the container is formed only when container has nodes in it. In addition to that, container's parent holder will have container class’s information.
Container statement is mapped to java as
- Interface File
It includes:
a) Getters for the attributes.
b) Builder interface which contains getters/setters and build method.
c) If container contains a leaf then one LeafIdentifier enum will be generated in interface. - Default implementation Class File
It includes:
a) Builder class which is the implementation of builder interface defined in interface file.
b) Impl class which is the implementation of interface file.
c) hashCode(), equals(), toString() methods overridden in it.
Example
File : acme-system.yang File : acme-system.yang module acme-system { namespace "http://acme.example.com/system"; prefix "acme"; organization "ACME Inc."; contact "joe@acme.example.com"; description "The module for entities implementing the ACME system."; revision 2007-06-09 { description "Initial revision."; } container system { leaf host-name { type string; description "Hostname for this system"; } } . . . }
File: System.java package org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem; import java.util.BitSet; import java.util.Map; import org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.AcmeSystem.OnosYangOpType; public interface System { public enum LeafIdentifier { HOSTNAME(1); private int leafIndex; public int getLeafIndex() { return leafIndex; } LeafIdentifier(int value) { this.leafIndex = value; } } String hostName(); BitSet valueLeafFlags(); OnosYangOpType yangSystemOpType(); BitSet selectLeafFlags(); Map<Class<?>, Object> yangAugmentedInfoMap(); Object yangAugmentedInfo(Class classObject); boolean isLeafValueSet(LeafIdentifier leaf); boolean isSelectLeaf(LeafIdentifier leaf); interface SystemBuilder { String hostName(); BitSet valueLeafFlags(); OnosYangOpType yangSystemOpType(); BitSet selectLeafFlags(); Map<Class<?>, Object> yangAugmentedInfoMap(); SystemBuilder hostName(String hostName); SystemBuilder yangSystemOpType(OnosYangOpType yangSystemOpType); SystemBuilder addYangAugmentedInfo(Object value, Class classObject); Object yangAugmentedInfo(Class classObject); SystemBuilder selectLeaf(LeafIdentifier leaf); System build(); } } File : DefaultSystem.java package org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem; import com.google.common.base.MoreObjects; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.BitSet; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Objects; import java.util.Set; import org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.AcmeSystem.OnosYangOpType; public class DefaultSystem implements System { protected String hostName; protected BitSet valueLeafFlags = new BitSet(); protected OnosYangOpType yangSystemOpType; protected boolean isSubTreeFiltered; protected BitSet selectLeafFlags = new BitSet(); protected Map<Class<?>, Object> yangAugmentedInfoMap = new HashMap<>(); @Override public String hostName() { return hostName; } @Override public BitSet valueLeafFlags() { return valueLeafFlags; } @Override public OnosYangOpType yangSystemOpType() { return yangSystemOpType; } public boolean isSubTreeFiltered() { return isSubTreeFiltered; } @Override public BitSet selectLeafFlags() { return selectLeafFlags; } @Override public Map<Class<?>, Object> yangAugmentedInfoMap() { return yangAugmentedInfoMap; } @Override public int hashCode() { return Objects.hash(hostName, valueLeafFlags, yangSystemOpType, isSubTreeFiltered, selectLeafFlags, yangAugmentedInfoMap); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof DefaultSystem) { DefaultSystem other = (DefaultSystem) obj; return Objects.equals(hostName, other.hostName) && Objects.equals(valueLeafFlags, other.valueLeafFlags) && Objects.equals(yangSystemOpType, other.yangSystemOpType) && Objects.equals(isSubTreeFiltered, other.isSubTreeFiltered) && Objects.equals(selectLeafFlags, other.selectLeafFlags) && Objects.equals(yangAugmentedInfoMap, other.yangAugmentedInfoMap); } return false; } @Override public String toString() { return MoreObjects.toStringHelper(getClass()) .omitNullValues() .add("hostName", hostName) .add("valueLeafFlags", valueLeafFlags) .add("yangSystemOpType", yangSystemOpType) .add("isSubTreeFiltered", isSubTreeFiltered) .add("selectLeafFlags", selectLeafFlags) .add("yangAugmentedInfoMap", yangAugmentedInfoMap) .toString(); } @Override public Object yangAugmentedInfo(Class classObject) { return yangAugmentedInfoMap.get(classObject); } protected DefaultSystem(SystemBuilder builderObject) { hostName = builderObject.hostName(); valueLeafFlags = builderObject.valueLeafFlags(); yangSystemOpType = builderObject.yangSystemOpType(); isSubTreeFiltered = builderObject.isSubTreeFiltered(); selectLeafFlags = builderObject.selectLeafFlags(); yangAugmentedInfoMap = builderObject.yangAugmentedInfoMap(); } public DefaultSystem processSubtreeFiltering(System appInstance, boolean isSelectAllSchemaChild) { SystemBuilder subTreeFilteringResultBuilder = new SystemBuilder(); BitSet isAnySelectOrContainmentNode = new BitSet(); if (!processLeafSubtreeFiltering(appInstance, subTreeFilteringResultBuilder, isAnySelectOrContainmentNode, isSelectAllSchemaChild)) { return null; } if (yangAugmentedInfoMap.isEmpty()) { Set<Map.Entry<Class<?>, Object>> augment = appInstance.yangAugmentedInfoMap().entrySet(); if (augment != null && !augment.isEmpty()) { Iterator<Map.Entry<Class<?>, Object>> augItr = augment.iterator(); while (augItr.hasNext()) { Map.Entry<Class<?>, Object> aug = augItr.next(); Class<?> augClass = aug.getKey(); String augClassName = augClass.getName(); int index = augClassName.lastIndexOf('.'); String classPackage = augClassName.substring(0, index) + "." + "Default" + augClass.getSimpleName() + "$" + augClass.getSimpleName() + "Builder"; ClassLoader classLoader = augClass.getClassLoader(); try { Class<?> builderClass; builderClass = classLoader.loadClass(classPackage); Object builderObj = builderClass.newInstance(); Method method = builderClass.getMethod("build"); Object defaultObj = method.invoke(builderObj); Class<?> defaultClass = defaultObj.getClass(); method = defaultClass.getMethod ("processSubtreeFiltering", augClass, boolean.class); Object result = method.invoke(defaultObj, aug.getValue(), true); subTreeFilteringResultBuilder .addYangAugmentedInfo(result, augClass); } catch (ClassNotFoundException | InstantiationException | NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { e.printStackTrace(); } } } } else { Set<Map.Entry<Class<?>, Object>> augment = yangAugmentedInfoMap .entrySet(); Iterator<Map.Entry<Class<?>, Object>> augItr = augment.iterator(); while (augItr.hasNext()) { Map.Entry<Class<?>, Object> aug = augItr.next(); Class<?> augClass = aug.getKey(); Object appInstanceInfo = appInstance.yangAugmentedInfo(augClass); if (appInstanceInfo == null) { subTreeFilteringResultBuilder.addYangAugmentedInfo (aug.getValue(), aug.getKey()); } else { Object processSubtreeFiltering; try { processSubtreeFiltering = aug.getValue().getClass() .getMethod("processSubtreeFiltering", aug.getKey(), boolean.class) .invoke(aug.getValue(), appInstanceInfo, true); if (processSubtreeFiltering != null) { subTreeFilteringResultBuilder .addYangAugmentedInfo(processSubtreeFiltering, aug.getKey()); } } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { e.printStackTrace(); } } } } if (!isSelectAllSchemaChild && !isAnySelectOrContainmentNode.get(0)) { return processSubtreeFiltering(appInstance, true); } return (DefaultSystem) subTreeFilteringResultBuilder.buildForFilter(); } private boolean processLeafSubtreeFiltering(System appInstance, SystemBuilder subTreeFilteringResultBuilder, BitSet isAnySelectOrContainmentNode, boolean isSelectAllSchemaChild) { if (valueLeafFlags.get(LeafIdentifier.HOSTNAME.getLeafIndex())) { if (appInstance.hostName() == null || !(hostName().equals(appInstance.hostName()))) { if (isSubTreeFiltered && !appInstance.isLeafValueSet(LeafIdentifier.HOSTNAME)) { subTreeFilteringResultBuilder.hostName(hostName()); } else { return false; } } else { subTreeFilteringResultBuilder.hostName(appInstance.hostName()); } } else if (selectLeafFlags.get(LeafIdentifier.HOSTNAME.getLeafIndex()) || isSelectAllSchemaChild) { isAnySelectOrContainmentNode.set(0); subTreeFilteringResultBuilder.hostName(appInstance.hostName()); } return true; } protected DefaultSystem() { } public static SystemBuilder builder() { return new SystemBuilder(); } @Override public boolean isLeafValueSet(LeafIdentifier leaf) { return valueLeafFlags.get(leaf.getLeafIndex()); } @Override public boolean isSelectLeaf(LeafIdentifier leaf) { return selectLeafFlags.get(leaf.getLeafIndex()); } public static class SystemBuilder implements System.SystemBuilder { protected String hostName; protected BitSet valueLeafFlags = new BitSet(); protected OnosYangOpType yangSystemOpType; protected boolean isSubTreeFiltered; protected BitSet selectLeafFlags = new BitSet(); protected Map<Class<?>, Object> yangAugmentedInfoMap = new HashMap<>(); @Override public String hostName() { return hostName; } @Override public BitSet valueLeafFlags() { return valueLeafFlags; } @Override public OnosYangOpType yangSystemOpType() { return yangSystemOpType; } public boolean isSubTreeFiltered() { return isSubTreeFiltered; } @Override public BitSet selectLeafFlags() { return selectLeafFlags; } @Override public Map<Class<?>, Object> yangAugmentedInfoMap() { return yangAugmentedInfoMap; } @Override public SystemBuilder hostName(String hostName) { valueLeafFlags.set(LeafIdentifier.HOSTNAME.getLeafIndex()); this.hostName = hostName; return this; } @Override public SystemBuilder yangSystemOpType(OnosYangOpType yangSystemOpType) { this.yangSystemOpType = yangSystemOpType; return this; } public SystemBuilder isSubTreeFiltered(boolean isSubTreeFiltered) { this.isSubTreeFiltered = isSubTreeFiltered; return this; } @Override public SystemBuilder selectLeaf(LeafIdentifier leaf) { selectLeafFlags.set(leaf.getLeafIndex()); return this; } @Override public SystemBuilder addYangAugmentedInfo(Object value, Class classObject) { yangAugmentedInfoMap.put(classObject, value); return this; } @Override public Object yangAugmentedInfo(Class classObject) { return yangAugmentedInfoMap.get(classObject); } @Override public System build() { return new DefaultSystem(this); } public System buildForFilter() { isSubTreeFiltered = true; return new DefaultSystem(this); } public SystemBuilder() { } } }
List
Overview
List is also like container that can hold many nodes by logically grouping. The only difference is, list can have multiple instances whereas container has only one instance.
Java mapping
In java, list acts as a class which can hold information contained within. A class of the list is formed only when list has nodes in it. In addition to that, list's parent holder will have list information by creating the list information in java List so that many instances of the class can be stored in it.
The list statement mapping in java is as same as container for the generation of java (refer container to know what files are generated).
In the below example the list holder is also a list with the same name. In such cases the complete path is defined for attribute in parent, in order to make sure that they are not referring to themselves. This case is same for any class generating YANG constructs.
Example
File : acme-system.yang module acme-system { namespace "http://acme.example.com/system"; prefix "acme"; organization "ACME Inc."; contact "joe@acme.example.com"; description "The module for entities implementing the ACME system."; revision 2007-06-09 { description "Initial revision."; } list login { key "name"; list login { key "name"; leaf name { type string; } leaf full-name { type string; } leaf class { type string; } } leaf name { type string; } } . . . }
Note: Qualified name is used for child node "login". File : Login.java package org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem; import java.util.BitSet; import java.util.List; import java.util.Map; import org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.AcmeSystem.OnosYangOpType; public interface Login { public enum LeafIdentifier { NAME(1); private int leafIndex; public int getLeafIndex() { return leafIndex; } LeafIdentifier(int value) { this.leafIndex = value; } } String name(); BitSet valueLeafFlags(); OnosYangOpType yangLoginOpType(); BitSet selectLeafFlags(); Map<Class<?>, Object> yangAugmentedInfoMap(); List<org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem.login.Login> login(); Object yangAugmentedInfo(Class classObject); boolean isLeafValueSet(LeafIdentifier leaf); boolean isSelectLeaf(LeafIdentifier leaf); interface LoginBuilder { LoginBuilder addToLogin(org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem .login.Login addTo); String name(); BitSet valueLeafFlags(); OnosYangOpType yangLoginOpType(); BitSet selectLeafFlags(); Map<Class<?>, Object> yangAugmentedInfoMap(); List<org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem.login.Login> login(); LoginBuilder name(String name); LoginBuilder yangLoginOpType(OnosYangOpType yangLoginOpType); LoginBuilder login(List<org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem.login .Login> login); LoginBuilder addYangAugmentedInfo(Object value, Class classObject); Object yangAugmentedInfo(Class classObject); LoginBuilder selectLeaf(LeafIdentifier leaf); Login build(); } } package org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem; import com.google.common.base.MoreObjects; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.BitSet; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.AcmeSystem.OnosYangOpType; public class DefaultLogin implements Login { protected String name; protected BitSet valueLeafFlags = new BitSet(); protected OnosYangOpType yangLoginOpType; protected boolean isSubTreeFiltered; protected BitSet selectLeafFlags = new BitSet(); protected Map<Class<?>, Object> yangAugmentedInfoMap = new HashMap<>(); protected List<org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem.login .Login> login; @Override public String name() { return name; } @Override public BitSet valueLeafFlags() { return valueLeafFlags; } @Override public OnosYangOpType yangLoginOpType() { return yangLoginOpType; } public boolean isSubTreeFiltered() { return isSubTreeFiltered; } @Override public BitSet selectLeafFlags() { return selectLeafFlags; } @Override public Map<Class<?>, Object> yangAugmentedInfoMap() { return yangAugmentedInfoMap; } @Override public List<org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem .login.Login> login() { return login; } @Override public int hashCode() { return Objects.hash(name, valueLeafFlags, yangLoginOpType, isSubTreeFiltered, selectLeafFlags, yangAugmentedInfoMap, login); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof DefaultLogin) { DefaultLogin other = (DefaultLogin) obj; return Objects.equals(name, other.name) && Objects.equals(valueLeafFlags, other.valueLeafFlags) && Objects.equals(yangLoginOpType, other.yangLoginOpType) && Objects.equals(isSubTreeFiltered, other.isSubTreeFiltered) && Objects.equals(selectLeafFlags, other.selectLeafFlags) && Objects.equals(yangAugmentedInfoMap, other.yangAugmentedInfoMap) && Objects.equals(login, other.login); } return false; } @Override public String toString() { return MoreObjects.toStringHelper(getClass()) .omitNullValues() .add("name", name) .add("valueLeafFlags", valueLeafFlags) .add("yangLoginOpType", yangLoginOpType) .add("isSubTreeFiltered", isSubTreeFiltered) .add("selectLeafFlags", selectLeafFlags) .add("yangAugmentedInfoMap", yangAugmentedInfoMap) .add("login", login) .toString(); } @Override public Object yangAugmentedInfo(Class classObject) { return yangAugmentedInfoMap.get(classObject); } protected DefaultLogin(LoginBuilder builderObject) { name = builderObject.name(); valueLeafFlags = builderObject.valueLeafFlags(); yangLoginOpType = builderObject.yangLoginOpType(); isSubTreeFiltered = builderObject.isSubTreeFiltered(); selectLeafFlags = builderObject.selectLeafFlags(); yangAugmentedInfoMap = builderObject.yangAugmentedInfoMap(); login = builderObject.login(); } public DefaultLogin processSubtreeFiltering(Login appInstance, boolean isSelectAllSchemaChild) { LoginBuilder subTreeFilteringResultBuilder = new LoginBuilder(); BitSet isAnySelectOrContainmentNode = new BitSet(); if (!processLeafSubtreeFiltering(appInstance, subTreeFilteringResultBuilder, isAnySelectOrContainmentNode, isSelectAllSchemaChild)) { return null; } if (!processChildNodesSubTreeFiltering(appInstance, subTreeFilteringResultBuilder, isAnySelectOrContainmentNode, isSelectAllSchemaChild)) { return null; } if (yangAugmentedInfoMap.isEmpty()) { Set<Map.Entry<Class<?>, Object>> augment = appInstance.yangAugmentedInfoMap().entrySet(); if (augment != null && !augment.isEmpty()) { Iterator<Map.Entry<Class<?>, Object>> augItr = augment.iterator(); while (augItr.hasNext()) { Map.Entry<Class<?>, Object> aug = augItr.next(); Class<?> augClass = aug.getKey(); String augClassName = augClass.getName(); int index = augClassName.lastIndexOf('.'); String classPackage = augClassName.substring(0, index) + "." + "Default" + augClass.getSimpleName() + "$" + augClass.getSimpleName() + "Builder"; ClassLoader classLoader = augClass.getClassLoader(); try { Class<?> builderClass; builderClass = classLoader.loadClass(classPackage); Object builderObj = builderClass.newInstance(); Method method = builderClass.getMethod("build"); Object defaultObj = method.invoke(builderObj); Class<?> defaultClass = defaultObj.getClass(); method = defaultClass.getMethod ("processSubtreeFiltering", augClass, boolean.class); Object result = method.invoke(defaultObj, aug.getValue(), true); subTreeFilteringResultBuilder .addYangAugmentedInfo(result, augClass); } catch (ClassNotFoundException | InstantiationException | NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { e.printStackTrace(); } } } } else { Set<Map.Entry<Class<?>, Object>> augment = yangAugmentedInfoMap .entrySet(); Iterator<Map.Entry<Class<?>, Object>> augItr = augment.iterator(); while (augItr.hasNext()) { Map.Entry<Class<?>, Object> aug = augItr.next(); Class<?> augClass = aug.getKey(); Object appInstanceInfo = appInstance.yangAugmentedInfo(augClass); if (appInstanceInfo == null) { subTreeFilteringResultBuilder.addYangAugmentedInfo (aug.getValue(), aug.getKey()); } else { Object processSubtreeFiltering; try { processSubtreeFiltering = aug.getValue().getClass() .getMethod("processSubtreeFiltering", aug.getKey(), boolean.class) .invoke(aug.getValue(), appInstanceInfo, true); if (processSubtreeFiltering != null) { subTreeFilteringResultBuilder .addYangAugmentedInfo(processSubtreeFiltering, aug.getKey()); } } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { e.printStackTrace(); } } } } if (!isSelectAllSchemaChild && !isAnySelectOrContainmentNode.get(0)) { return processSubtreeFiltering(appInstance, true); } return (DefaultLogin) subTreeFilteringResultBuilder.buildForFilter(); } private boolean processLeafSubtreeFiltering(Login appInstance, LoginBuilder subTreeFilteringResultBuilder, BitSet isAnySelectOrContainmentNode, boolean isSelectAllSchemaChild) { if (valueLeafFlags.get(LeafIdentifier.NAME.getLeafIndex())) { if (appInstance.name() == null || !(name().equals(appInstance.name()))) { if (isSubTreeFiltered && !appInstance.isLeafValueSet(LeafIdentifier.NAME)) { subTreeFilteringResultBuilder.name(name()); } else { return false; } } else { subTreeFilteringResultBuilder.name(appInstance.name()); } } else if (selectLeafFlags.get(LeafIdentifier.NAME.getLeafIndex()) || isSelectAllSchemaChild) { isAnySelectOrContainmentNode.set(0); subTreeFilteringResultBuilder.name(appInstance.name()); } return true; } private boolean processChildNodesSubTreeFiltering(Login appInstance, LoginBuilder subTreeFilteringResultBuilder, BitSet isAnySelectOrContainmentNode, boolean isSelectAllSchemaChild) { if (isSelectAllSchemaChild) { if (appInstance.login() != null) { for (org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem.login .Login login : appInstance.login()) { org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem.login .Login result; result = ((org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem.login .DefaultLogin) org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem.login .DefaultLogin.builder() .buildForFilter()).processSubtreeFiltering(login, true); subTreeFilteringResultBuilder.addToLogin(result); } } else { if (isSubTreeFiltered && login() != null) { subTreeFilteringResultBuilder.login(login); } } } else if (login() != null) { isAnySelectOrContainmentNode.set(0); if (!login().isEmpty()) { if (appInstance.login() != null && !appInstance.login().isEmpty()) { for (org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem .login.Login login : login()) { for (org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem.login .Login login2 : appInstance.login()) { org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem.login .Login result = ((org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem.login .DefaultLogin) login) .processSubtreeFiltering(login2, false); if (result != null) { subTreeFilteringResultBuilder.addToLogin(result); } } } } else { if (isSubTreeFiltered && login() != null) { subTreeFilteringResultBuilder.login(login); } } } else { if (appInstance.login() != null && !appInstance.login().isEmpty()) { for (org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem.login .Login login : appInstance.login()) { subTreeFilteringResultBuilder.addToLogin(login); } } } } return true; } protected DefaultLogin() { } public static LoginBuilder builder() { return new LoginBuilder(); } @Override public boolean isLeafValueSet(LeafIdentifier leaf) { return valueLeafFlags.get(leaf.getLeafIndex()); } @Override public boolean isSelectLeaf(LeafIdentifier leaf) { return selectLeafFlags.get(leaf.getLeafIndex()); } public static class LoginBuilder implements Login.LoginBuilder { protected String name; protected BitSet valueLeafFlags = new BitSet(); protected OnosYangOpType yangLoginOpType; protected boolean isSubTreeFiltered; protected BitSet selectLeafFlags = new BitSet(); protected Map<Class<?>, Object> yangAugmentedInfoMap = new HashMap<>(); protected List<org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem.login .Login> login; @Override public String name() { return name; } @Override public BitSet valueLeafFlags() { return valueLeafFlags; } @Override public OnosYangOpType yangLoginOpType() { return yangLoginOpType; } public boolean isSubTreeFiltered() { return isSubTreeFiltered; } @Override public BitSet selectLeafFlags() { return selectLeafFlags; } @Override public Map<Class<?>, Object> yangAugmentedInfoMap() { return yangAugmentedInfoMap; } @Override public List<org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem .login.Login> login() { return login; } @Override public LoginBuilder name(String name) { valueLeafFlags.set(LeafIdentifier.NAME.getLeafIndex()); this.name = name; return this; } @Override public LoginBuilder yangLoginOpType(OnosYangOpType yangLoginOpType) { this.yangLoginOpType = yangLoginOpType; return this; } public LoginBuilder isSubTreeFiltered(boolean isSubTreeFiltered) { this.isSubTreeFiltered = isSubTreeFiltered; return this; } @Override public LoginBuilder login(List<org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609 .acmesystem.login.Login> login) { this.login = login; return this; } @Override public LoginBuilder addToLogin(org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609 .acmesystem.login.Login addTo) { if (login == null) { login = new ArrayList<>(); } login.add(addTo); return this; } @Override public LoginBuilder selectLeaf(LeafIdentifier leaf) { selectLeafFlags.set(leaf.getLeafIndex()); return this; } @Override public LoginBuilder addYangAugmentedInfo(Object value, Class classObject) { yangAugmentedInfoMap.put(classObject, value); return this; } @Override public Object yangAugmentedInfo(Class classObject) { return yangAugmentedInfoMap.get(classObject); } @Override public Login build() { return new DefaultLogin(this); } public Login buildForFilter() { isSubTreeFiltered = true; return new DefaultLogin(this); } public LoginBuilder() { } } }
Grouping and uses
Overview
Grouping the nodes together, for reusing them at many places, can be done in YANG. Grouping the nodes is done by grouping statement and using those grouped nodes at different places is done by uses statement.
Java mapping
During YANG to java conversion, the contents of grouping is copied wherever uses statement is used and code will be generated for nodes inside grouping's generated package.
Note: if a yang file only contains grouping then for that module no service interface will be generated. one interface will be generated but there will not be any OpParam file for module. For other nodes code generation will be same.
Example
module Test { namespace "http://test.example.com/"; prefix "test"; organization "ACME Inc."; grouping endpoint { leaf address { type int32; } leaf port { type int8; } } container connection { container source { uses endpoint; } container destination { uses endpoint; } } . . . }
File : Connection.java package org.onosproject.yang.gen.v1.http.test.example.com.test; import java.util.Map; import org.onosproject.yang.gen.v1.http.test.example.com.Test.OnosYangOpType; import org.onosproject.yang.gen.v1.http.test.example.com.test.connection.Destination; import org.onosproject.yang.gen.v1.http.test.example.com.test.connection.Source; public interface Connection { OnosYangOpType yangConnectionOpType(); Map<Class<?>, Object> yangAugmentedInfoMap(); Source source(); Destination destination(); Object yangAugmentedInfo(Class classObject); interface ConnectionBuilder { OnosYangOpType yangConnectionOpType(); Map<Class<?>, Object> yangAugmentedInfoMap(); Source source(); Destination destination(); ConnectionBuilder yangConnectionOpType(OnosYangOpType yangConnectionOpType); ConnectionBuilder source(Source source); ConnectionBuilder destination(Destination destination); ConnectionBuilder addYangAugmentedInfo(Object value, Class classObject); Object yangAugmentedInfo(Class classObject); Connection build(); } }
Choice and case
Overview
The choice statement defines a set of alternatives, only one of which may exist at any one time. The argument is an identifier, followed by a block of sub-statements that holds detailed choice information.
A choice consists of a number of branches, defined with the “case” substatement. Each branch contains a number of child nodes. The nodes from at most one of the choice's branches exist at the same time.
The case statement is used to define branches of the choice. It takes identifier as an argument, followed by a block of sub-statements that holds detailed case information.
JAVA mapping
Choice is mapped to interface(marker interface).
Case statement are mapped to the JAVA interfaces
It includes
Interface file which extends choice marker interface
Builder class which implements the builder interface and impl class which implements the interface
- Impl class includes overridden methods, hashcode, equals, toString methods.
Example
File : link.yang module link { yang-version 1; namespace http://huawei.com; prefix Ant; container link { choice interfaceType { case ethernerType { leaf ethernet { type string; } } case p2pType { leaf p2p { type string; } } } } }
File : InterfaceType.java package org.onosproject.yang.gen.v1.http.huawei.com.link.link; public interface InterfaceType { default InterfaceType processSubtreeFiltering(InterfaceType appInstance, boolean isSelectAllSchemaChild) { return null; } } File : EthernerType.java package org.onosproject.yang.gen.v1.http.huawei.com.link.link.interfacetype; import java.util.BitSet; import java.util.Map; import org.onosproject.yang.gen.v1.http.huawei.com.Link.OnosYangOpType; import org.onosproject.yang.gen.v1.http.huawei.com.link.link.InterfaceType; public interface EthernerType extends InterfaceType { public enum LeafIdentifier { ETHERNET(1); private int leafIndex; public int getLeafIndex() { return leafIndex; } LeafIdentifier(int value) { this.leafIndex = value; } } String ethernet(); BitSet valueLeafFlags(); OnosYangOpType yangEthernerTypeOpType(); BitSet selectLeafFlags(); Map<Class<?>, Object> yangAugmentedInfoMap(); Object yangAugmentedInfo(Class classObject); boolean isLeafValueSet(LeafIdentifier leaf); boolean isSelectLeaf(LeafIdentifier leaf); interface EthernerTypeBuilder { String ethernet(); BitSet valueLeafFlags(); OnosYangOpType yangEthernerTypeOpType(); BitSet selectLeafFlags(); Map<Class<?>, Object> yangAugmentedInfoMap(); EthernerTypeBuilder ethernet(String ethernet); EthernerTypeBuilder yangEthernerTypeOpType(OnosYangOpType yangEthernerTypeOpType); EthernerTypeBuilder addYangAugmentedInfo(Object value, Class classObject); Object yangAugmentedInfo(Class classObject); EthernerTypeBuilder selectLeaf(LeafIdentifier leaf); EthernerType build(); } } File : DefaultEthernerType.java package org.onosproject.yang.gen.v1.http.huawei.com.link.link.interfacetype; import com.google.common.base.MoreObjects; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.BitSet; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Objects; import java.util.Set; import org.onosproject.yang.gen.v1.http.huawei.com.Link.OnosYangOpType; import org.onosproject.yang.gen.v1.http.huawei.com.link.link.InterfaceType; public class DefaultEthernerType implements EthernerType { protected String ethernet; protected BitSet valueLeafFlags = new BitSet(); protected OnosYangOpType yangEthernerTypeOpType; protected boolean isSubTreeFiltered; protected BitSet selectLeafFlags = new BitSet(); protected Map<Class<?>, Object> yangAugmentedInfoMap = new HashMap<>(); @Override public String ethernet() { return ethernet; } @Override public BitSet valueLeafFlags() { return valueLeafFlags; } @Override public OnosYangOpType yangEthernerTypeOpType() { return yangEthernerTypeOpType; } public boolean isSubTreeFiltered() { return isSubTreeFiltered; } @Override public BitSet selectLeafFlags() { return selectLeafFlags; } @Override public Map<Class<?>, Object> yangAugmentedInfoMap() { return yangAugmentedInfoMap; } @Override public int hashCode() { return Objects.hash(ethernet, valueLeafFlags, yangEthernerTypeOpType, isSubTreeFiltered, selectLeafFlags, yangAugmentedInfoMap); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof DefaultEthernerType) { DefaultEthernerType other = (DefaultEthernerType) obj; return Objects.equals(ethernet, other.ethernet) && Objects.equals(valueLeafFlags, other.valueLeafFlags) && Objects.equals(yangEthernerTypeOpType, other.yangEthernerTypeOpType) && Objects.equals(isSubTreeFiltered, other.isSubTreeFiltered) && Objects.equals(selectLeafFlags, other.selectLeafFlags) && Objects.equals(yangAugmentedInfoMap, other.yangAugmentedInfoMap); } return false; } @Override public String toString() { return MoreObjects.toStringHelper(getClass()) .omitNullValues() .add("ethernet", ethernet) .add("valueLeafFlags", valueLeafFlags) .add("yangEthernerTypeOpType", yangEthernerTypeOpType) .add("isSubTreeFiltered", isSubTreeFiltered) .add("selectLeafFlags", selectLeafFlags) .add("yangAugmentedInfoMap", yangAugmentedInfoMap) .toString(); } @Override public Object yangAugmentedInfo(Class classObject) { return yangAugmentedInfoMap.get(classObject); } protected DefaultEthernerType(EthernerTypeBuilder builderObject) { ethernet = builderObject.ethernet(); valueLeafFlags = builderObject.valueLeafFlags(); yangEthernerTypeOpType = builderObject.yangEthernerTypeOpType(); isSubTreeFiltered = builderObject.isSubTreeFiltered(); selectLeafFlags = builderObject.selectLeafFlags(); yangAugmentedInfoMap = builderObject.yangAugmentedInfoMap(); } public DefaultEthernerType processSubtreeFiltering(InterfaceType instance, boolean isSelectAllSchemaChild) { EthernerTypeBuilder subTreeFilteringResultBuilder = new EthernerTypeBuilder(); BitSet isAnySelectOrContainmentNode = new BitSet(); DefaultEthernerType appInstance = (DefaultEthernerType) instance; if (!processLeafSubtreeFiltering(appInstance, subTreeFilteringResultBuilder, isAnySelectOrContainmentNode, isSelectAllSchemaChild)) { return null; } if (yangAugmentedInfoMap.isEmpty()) { Set<Map.Entry<Class<?>, Object>> augment = appInstance.yangAugmentedInfoMap().entrySet(); if (augment != null && !augment.isEmpty()) { Iterator<Map.Entry<Class<?>, Object>> augItr = augment.iterator(); while (augItr.hasNext()) { Map.Entry<Class<?>, Object> aug = augItr.next(); Class<?> augClass = aug.getKey(); String augClassName = augClass.getName(); int index = augClassName.lastIndexOf('.'); String classPackage = augClassName.substring(0, index) + "." + "Default" + augClass.getSimpleName() + "$" + augClass.getSimpleName() + "Builder"; ClassLoader classLoader = augClass.getClassLoader(); try { Class<?> builderClass; builderClass = classLoader.loadClass(classPackage); Object builderObj = builderClass.newInstance(); Method method = builderClass.getMethod("build"); Object defaultObj = method.invoke(builderObj); Class<?> defaultClass = defaultObj.getClass(); method = defaultClass.getMethod ("processSubtreeFiltering", augClass, boolean.class); Object result = method.invoke(defaultObj, aug.getValue(), true); subTreeFilteringResultBuilder .addYangAugmentedInfo(result, augClass); } catch (ClassNotFoundException | InstantiationException | NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { e.printStackTrace(); } } } } else { Set<Map.Entry<Class<?>, Object>> augment = yangAugmentedInfoMap .entrySet(); Iterator<Map.Entry<Class<?>, Object>> augItr = augment.iterator(); while (augItr.hasNext()) { Map.Entry<Class<?>, Object> aug = augItr.next(); Class<?> augClass = aug.getKey(); Object appInstanceInfo = appInstance.yangAugmentedInfo(augClass); if (appInstanceInfo == null) { subTreeFilteringResultBuilder.addYangAugmentedInfo (aug.getValue(), aug.getKey()); } else { Object processSubtreeFiltering; try { processSubtreeFiltering = aug.getValue().getClass() .getMethod("processSubtreeFiltering", aug.getKey(), boolean.class) .invoke(aug.getValue(), appInstanceInfo, true); if (processSubtreeFiltering != null) { subTreeFilteringResultBuilder .addYangAugmentedInfo(processSubtreeFiltering, aug.getKey()); } } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { e.printStackTrace(); } } } } if (!isSelectAllSchemaChild && !isAnySelectOrContainmentNode.get(0)) { return processSubtreeFiltering(appInstance, true); } return (DefaultEthernerType) subTreeFilteringResultBuilder.buildForFilter(); } private boolean processLeafSubtreeFiltering(InterfaceType instance, EthernerTypeBuilder subTreeFilteringResultBuilder, BitSet isAnySelectOrContainmentNode, boolean isSelectAllSchemaChild) { DefaultEthernerType appInstance = (DefaultEthernerType) instance; if (valueLeafFlags.get(LeafIdentifier.ETHERNET.getLeafIndex())) { if (appInstance.ethernet() == null || !(ethernet().equals(appInstance.ethernet()))) { if (isSubTreeFiltered && !appInstance.isLeafValueSet(LeafIdentifier.ETHERNET)) { subTreeFilteringResultBuilder.ethernet(ethernet()); } else { return false; } } else { subTreeFilteringResultBuilder.ethernet(appInstance.ethernet()); } } else if (selectLeafFlags.get(LeafIdentifier.ETHERNET.getLeafIndex()) || isSelectAllSchemaChild) { isAnySelectOrContainmentNode.set(0); subTreeFilteringResultBuilder.ethernet(appInstance.ethernet()); } return true; } protected DefaultEthernerType() { } public static EthernerTypeBuilder builder() { return new EthernerTypeBuilder(); } @Override public boolean isLeafValueSet(LeafIdentifier leaf) { return valueLeafFlags.get(leaf.getLeafIndex()); } @Override public boolean isSelectLeaf(LeafIdentifier leaf) { return selectLeafFlags.get(leaf.getLeafIndex()); } public static class EthernerTypeBuilder implements EthernerType.EthernerTypeBuilder { protected String ethernet; protected BitSet valueLeafFlags = new BitSet(); protected OnosYangOpType yangEthernerTypeOpType; protected boolean isSubTreeFiltered; protected BitSet selectLeafFlags = new BitSet(); protected Map<Class<?>, Object> yangAugmentedInfoMap = new HashMap<>(); @Override public String ethernet() { return ethernet; } @Override public BitSet valueLeafFlags() { return valueLeafFlags; } @Override public OnosYangOpType yangEthernerTypeOpType() { return yangEthernerTypeOpType; } public boolean isSubTreeFiltered() { return isSubTreeFiltered; } @Override public BitSet selectLeafFlags() { return selectLeafFlags; } @Override public Map<Class<?>, Object> yangAugmentedInfoMap() { return yangAugmentedInfoMap; } @Override public EthernerTypeBuilder ethernet(String ethernet) { valueLeafFlags.set(LeafIdentifier.ETHERNET.getLeafIndex()); this.ethernet = ethernet; return this; } @Override public EthernerTypeBuilder yangEthernerTypeOpType(OnosYangOpType yangEthernerTypeOpType) { this.yangEthernerTypeOpType = yangEthernerTypeOpType; return this; } public EthernerTypeBuilder isSubTreeFiltered(boolean isSubTreeFiltered) { this.isSubTreeFiltered = isSubTreeFiltered; return this; } @Override public EthernerTypeBuilder selectLeaf(LeafIdentifier leaf) { selectLeafFlags.set(leaf.getLeafIndex()); return this; } @Override public EthernerTypeBuilder addYangAugmentedInfo(Object value, Class classObject) { yangAugmentedInfoMap.put(classObject, value); return this; } @Override public Object yangAugmentedInfo(Class classObject) { return yangAugmentedInfoMap.get(classObject); } @Override public EthernerType build() { return new DefaultEthernerType(this); } public EthernerType buildForFilter() { isSubTreeFiltered = true; return new DefaultEthernerType(this); } public EthernerTypeBuilder() { } } }
RPC
Overview
RPCs are modeled with RPC statement. The input statement is used to define input parameters to the RPC and output statement is used to define output parameters to the RPC.
JAVA mapping
Rpc statement is mapped to a method in module manager class and service interface.
The generated method will depends on the sub statements input and output. Input and Output will have there own java classes and RPC method will contain Output class's object as return type and Input class's object will be input for the method. If no output node is present , return type will be "void". Same way if no input is present , there will be no input parameter for the method.
Rpc node is an non operation type node so all the nodes under it will not contain operationType, processSubTreeFiltereing, select leaf flags in their generated code.
Example
File: sfc.yang module Sfc { yang-version 1; namespace http://huawei.com; prefix Ant; rpc SFP { input { leaf port { type string; } } output { leaf path { type string; } } } }
File : SfcService.java package org.onosproject.yang.gen.v1.http.huawei.com; import org.onosproject.yang.gen.v1.http.huawei.com.sfc.sfp.SfpInput; import org.onosproject.yang.gen.v1.http.huawei.com.sfc.sfp.SfpOutput; public interface SfcService { Sfc getSfc(SfcOpParam sfc); void setSfc(SfcOpParam sfc); SfpOutput sfp(SfpInput inputVar); } File : SfpInput.java package org.onosproject.yang.gen.v1.http.huawei.com.sfc.sfp; import java.util.BitSet; import java.util.Map; public interface SfpInput { public enum LeafIdentifier { PORT(1); private int leafIndex; public int getLeafIndex() { return leafIndex; } LeafIdentifier(int value) { this.leafIndex = value; } } String port(); BitSet valueLeafFlags(); Map<Class<?>, Object> yangAugmentedInfoMap(); Object yangAugmentedInfo(Class classObject); boolean isLeafValueSet(LeafIdentifier leaf); interface SfpInputBuilder { String port(); BitSet valueLeafFlags(); Map<Class<?>, Object> yangAugmentedInfoMap(); SfpInputBuilder port(String port); SfpInputBuilder addYangAugmentedInfo(Object value, Class classObject); Object yangAugmentedInfo(Class classObject); SfpInput build(); } } File : DefaultSfpInput.java package org.onosproject.yang.gen.v1.http.huawei.com.sfc.sfp; import com.google.common.base.MoreObjects; import java.util.BitSet; import java.util.HashMap; import java.util.Map; import java.util.Objects; public class DefaultSfpInput implements SfpInput { protected String port; protected BitSet valueLeafFlags = new BitSet(); protected Map<Class<?>, Object> yangAugmentedInfoMap = new HashMap<>(); @Override public String port() { return port; } @Override public BitSet valueLeafFlags() { return valueLeafFlags; } @Override public Map<Class<?>, Object> yangAugmentedInfoMap() { return yangAugmentedInfoMap; } @Override public int hashCode() { return Objects.hash(port, valueLeafFlags, yangAugmentedInfoMap); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof DefaultSfpInput) { DefaultSfpInput other = (DefaultSfpInput) obj; return Objects.equals(port, other.port) && Objects.equals(valueLeafFlags, other.valueLeafFlags) && Objects.equals(yangAugmentedInfoMap, other.yangAugmentedInfoMap); } return false; } @Override public String toString() { return MoreObjects.toStringHelper(getClass()) .omitNullValues() .add("port", port) .add("valueLeafFlags", valueLeafFlags) .add("yangAugmentedInfoMap", yangAugmentedInfoMap) .toString(); } @Override public Object yangAugmentedInfo(Class classObject) { return yangAugmentedInfoMap.get(classObject); } protected DefaultSfpInput(SfpInputBuilder builderObject) { port = builderObject.port(); valueLeafFlags = builderObject.valueLeafFlags(); yangAugmentedInfoMap = builderObject.yangAugmentedInfoMap(); } protected DefaultSfpInput() { } public static SfpInputBuilder builder() { return new SfpInputBuilder(); } @Override public boolean isLeafValueSet(LeafIdentifier leaf) { return valueLeafFlags.get(leaf.getLeafIndex()); } public static class SfpInputBuilder implements SfpInput.SfpInputBuilder { protected String port; protected BitSet valueLeafFlags = new BitSet(); protected Map<Class<?>, Object> yangAugmentedInfoMap = new HashMap<>(); @Override public String port() { return port; } @Override public BitSet valueLeafFlags() { return valueLeafFlags; } @Override public Map<Class<?>, Object> yangAugmentedInfoMap() { return yangAugmentedInfoMap; } @Override public SfpInputBuilder port(String port) { valueLeafFlags.set(LeafIdentifier.PORT.getLeafIndex()); this.port = port; return this; } @Override public SfpInputBuilder addYangAugmentedInfo(Object value, Class classObject) { yangAugmentedInfoMap.put(classObject, value); return this; } @Override public Object yangAugmentedInfo(Class classObject) { return yangAugmentedInfoMap.get(classObject); } @Override public SfpInput build() { return new DefaultSfpInput(this); } public SfpInputBuilder() { } } } File : Sfpoutput.java package org.onosproject.yang.gen.v1.http.huawei.com.sfc.sfp; import java.util.BitSet; import java.util.Map; public interface SfpOutput { public enum LeafIdentifier { PATH(1); private int leafIndex; public int getLeafIndex() { return leafIndex; } LeafIdentifier(int value) { this.leafIndex = value; } } String path(); BitSet valueLeafFlags(); Map<Class<?>, Object> yangAugmentedInfoMap(); Object yangAugmentedInfo(Class classObject); boolean isLeafValueSet(LeafIdentifier leaf); interface SfpOutputBuilder { String path(); BitSet valueLeafFlags(); Map<Class<?>, Object> yangAugmentedInfoMap(); SfpOutputBuilder path(String path); SfpOutputBuilder addYangAugmentedInfo(Object value, Class classObject); Object yangAugmentedInfo(Class classObject); SfpOutput build(); } } File : DefaultSfpOutput.java ppackage org.onosproject.yang.gen.v1.http.huawei.com.sfc.sfp; import com.google.common.base.MoreObjects; import java.util.BitSet; import java.util.HashMap; import java.util.Map; import java.util.Objects; public class DefaultSfpOutput implements SfpOutput { protected String path; protected BitSet valueLeafFlags = new BitSet(); protected Map<Class<?>, Object> yangAugmentedInfoMap = new HashMap<>(); @Override public String path() { return path; } @Override public BitSet valueLeafFlags() { return valueLeafFlags; } @Override public Map<Class<?>, Object> yangAugmentedInfoMap() { return yangAugmentedInfoMap; } @Override public int hashCode() { return Objects.hash(path, valueLeafFlags, yangAugmentedInfoMap); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof DefaultSfpOutput) { DefaultSfpOutput other = (DefaultSfpOutput) obj; return Objects.equals(path, other.path) && Objects.equals(valueLeafFlags, other.valueLeafFlags) && Objects.equals(yangAugmentedInfoMap, other.yangAugmentedInfoMap); } return false; } @Override public String toString() { return MoreObjects.toStringHelper(getClass()) .omitNullValues() .add("path", path) .add("valueLeafFlags", valueLeafFlags) .add("yangAugmentedInfoMap", yangAugmentedInfoMap) .toString(); } @Override public Object yangAugmentedInfo(Class classObject) { return yangAugmentedInfoMap.get(classObject); } protected DefaultSfpOutput(SfpOutputBuilder builderObject) { path = builderObject.path(); valueLeafFlags = builderObject.valueLeafFlags(); yangAugmentedInfoMap = builderObject.yangAugmentedInfoMap(); } protected DefaultSfpOutput() { } public static SfpOutputBuilder builder() { return new SfpOutputBuilder(); } @Override public boolean isLeafValueSet(LeafIdentifier leaf) { return valueLeafFlags.get(leaf.getLeafIndex()); } public static class SfpOutputBuilder implements SfpOutput.SfpOutputBuilder { protected String path; protected BitSet valueLeafFlags = new BitSet(); protected Map<Class<?>, Object> yangAugmentedInfoMap = new HashMap<>(); @Override public String path() { return path; } @Override public BitSet valueLeafFlags() { return valueLeafFlags; } @Override public Map<Class<?>, Object> yangAugmentedInfoMap() { return yangAugmentedInfoMap; } @Override public SfpOutputBuilder path(String path) { valueLeafFlags.set(LeafIdentifier.PATH.getLeafIndex()); this.path = path; return this; } @Override public SfpOutputBuilder addYangAugmentedInfo(Object value, Class classObject) { yangAugmentedInfoMap.put(classObject, value); return this; } @Override public Object yangAugmentedInfo(Class classObject) { return yangAugmentedInfoMap.get(classObject); } @Override public SfpOutput build() { return new DefaultSfpOutput(this); } public SfpOutputBuilder() { } } }
Notification
Overview
The "notification" statement is used to define a notification. It takes one argument, which is an identifier, followed by a block of substatements that holds detailed notification information.
JAVA mapping
Notification is mapped to events and event listeners in ONOS. Events are used by Managers to notify its listeners about changes in the network or topology etc, and by Stores to notify their peers of events in a distributed setting. An Event is comprised of a event type and a subject built of model objects.
When notification statement is present in YANG, an event class , event subject class, event listener interface and notification interface and builder will be generated.
When multiple notifications are present event class include the an enum with types of events for all notification like DEVICE_ADDED, DEVICE_REMOVED and it extends AbstractEvent with event type and event subject class. It is used to notify EventListeners about the event.
xxxEvent Subject class will have all the objects of events for multiple notifications and getters and setters for the events.
xxxEvent Listener is interface which extends EventListener.
Notification is an non operation type node so all the nodes under it will not contains operation type, process sub tree filtering and select leaf flag in generated code.
Example
File : ospf.yang module ospf { namespace "http://example.com/ospf"; prefix "ospf"; notification test { leaf event-class { type string; } leaf severity { type string; } } }
File : OspfService.java package org.onosproject.yang.gen.v1.http.example.com.ospf; import org.onosproject.event.ListenerService; import org.onosproject.yang.gen.v1.http.example.com.ospf.ospf.OspfEvent; import org.onosproject.yang.gen.v1.http.example.com.ospf.ospf.OspfEventListener; public interface OspfService extends ListenerService<OspfEvent, OspfEventListener> { Ospf getOspf(OspfOpParam ospf); void setOspf(OspfOpParam ospf); } File : OspfEvent.java package org.onosproject.yang.gen.v1.http.example.com.ospf.ospf; import org.onosproject.event.AbstractEvent; public class OspfEvent extends AbstractEvent<OspfEvent.Type, OspfEventSubject> { public enum Type { TEST } public OspfEvent(Type type, OspfEventSubject subject) { super(type, subject); } public OspfEvent(Type type, OspfEventSubject subject, long time) { super(type, subject, time); } } File : OspfEventSubject.java package org.onosproject.yang.gen.v1.http.example.com.ospf.ospf; public class OspfEventSubject { protected Test test; public Test test() { return test; } public void test(Test test) { this.test = test; } } File : OspfEventListener.java package org.onosproject.yang.gen.v1.http.example.com.ospf.ospf; import org.onosproject.event.EventListener; public interface OspfEventListener extends EventListener<OspfEvent> { } File : Test.java package org.onosproject.yang.gen.v1.http.example.com.ospf.ospf; import java.util.BitSet; import java.util.Map; public interface Test { public enum LeafIdentifier { EVENTCLASS(1), SEVERITY(2); private int leafIndex; public int getLeafIndex() { return leafIndex; } LeafIdentifier(int value) { this.leafIndex = value; } } String eventClass(); String severity(); BitSet valueLeafFlags(); Map<Class<?>, Object> yangAugmentedInfoMap(); Object yangAugmentedInfo(Class classObject); boolean isLeafValueSet(LeafIdentifier leaf); interface TestBuilder { String eventClass(); String severity(); BitSet valueLeafFlags(); Map<Class<?>, Object> yangAugmentedInfoMap(); TestBuilder eventClass(String eventClass); TestBuilder severity(String severity); TestBuilder addYangAugmentedInfo(Object value, Class classObject); Object yangAugmentedInfo(Class classObject); Test build(); } } File : DefaultTest.java package org.onosproject.yang.gen.v1.http.example.com.ospf.ospf; import com.google.common.base.MoreObjects; import java.util.BitSet; import java.util.HashMap; import java.util.Map; import java.util.Objects; public class DefaultTest implements Test { protected String eventClass; protected String severity; protected BitSet valueLeafFlags = new BitSet(); protected Map<Class<?>, Object> yangAugmentedInfoMap = new HashMap<>(); @Override public String eventClass() { return eventClass; } @Override public String severity() { return severity; } @Override public BitSet valueLeafFlags() { return valueLeafFlags; } @Override public Map<Class<?>, Object> yangAugmentedInfoMap() { return yangAugmentedInfoMap; } @Override public int hashCode() { return Objects.hash(eventClass, severity, valueLeafFlags, yangAugmentedInfoMap); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof DefaultTest) { DefaultTest other = (DefaultTest) obj; return Objects.equals(eventClass, other.eventClass) && Objects.equals(severity, other.severity) && Objects.equals(valueLeafFlags, other.valueLeafFlags) && Objects.equals(yangAugmentedInfoMap, other.yangAugmentedInfoMap); } return false; } @Override public String toString() { return MoreObjects.toStringHelper(getClass()) .omitNullValues() .add("eventClass", eventClass) .add("severity", severity) .add("valueLeafFlags", valueLeafFlags) .add("yangAugmentedInfoMap", yangAugmentedInfoMap) .toString(); } @Override public Object yangAugmentedInfo(Class classObject) { return yangAugmentedInfoMap.get(classObject); } protected DefaultTest(TestBuilder builderObject) { eventClass = builderObject.eventClass(); severity = builderObject.severity(); valueLeafFlags = builderObject.valueLeafFlags(); yangAugmentedInfoMap = builderObject.yangAugmentedInfoMap(); } protected DefaultTest() { } public static TestBuilder builder() { return new TestBuilder(); } @Override public boolean isLeafValueSet(LeafIdentifier leaf) { return valueLeafFlags.get(leaf.getLeafIndex()); } public static class TestBuilder implements Test.TestBuilder { protected String eventClass; protected String severity; protected BitSet valueLeafFlags = new BitSet(); protected Map<Class<?>, Object> yangAugmentedInfoMap = new HashMap<>(); @Override public String eventClass() { return eventClass; } @Override public String severity() { return severity; } @Override public BitSet valueLeafFlags() { return valueLeafFlags; } @Override public Map<Class<?>, Object> yangAugmentedInfoMap() { return yangAugmentedInfoMap; } @Override public TestBuilder eventClass(String eventClass) { valueLeafFlags.set(LeafIdentifier.EVENTCLASS.getLeafIndex()); this.eventClass = eventClass; return this; } @Override public TestBuilder severity(String severity) { valueLeafFlags.set(LeafIdentifier.SEVERITY.getLeafIndex()); this.severity = severity; return this; } @Override public TestBuilder addYangAugmentedInfo(Object value, Class classObject) { yangAugmentedInfoMap.put(classObject, value); return this; } @Override public Object yangAugmentedInfo(Class classObject) { return yangAugmentedInfoMap.get(classObject); } @Override public Test build() { return new DefaultTest(this); } public TestBuilder() { } } }
Augment
Overview
Augment means “make (something) greater by adding to it; increase.” in YANG augment adds some information in target node. Here in YANG, container, list, choice, case, input, output, or notification node can come as a target node.
As the child node of augment node only "container", "leaf", "list", "leaf-list", "uses", and "choice" can come. If augment comes under a module or submodule.
If a target node is a choice node the "case" statement, or a case shorthand statement can be come as a child node of augment node.
If a target node is from some other YANG file than a mandatory node which is is one of:
A leaf, choice, or anyxml node with a "mandatory" statement with the value "true".
A list or leaf-list node with a "min-elements" statement with a value greater than zero.
A container node without a "presence" statement, which has at least one mandatory node as a child.
should not come as a child node of augment node.
A augment node can't add the same augmented info to an augmented node multiple times.
Java mapping
For a given augment node in the YANG file one interface file and one builder class file will be generated. Generated files will be having attributes, getters and setters for augment node's child nodes and leaf or leaf-list.
For augment we have given one interface named as "YangAugmentedInfo” as part of YANG utils plugin.
File generated for augment node will be implementing AugmentedInfo class.
Node in data model tree which can be augmented as per the YANG rules for them we have given 3 methods , which are :
public void addAugmentedInfo(YangAugmentedInfo value, Class classObject) { yangAugmentedInfoMap.put(classObject, value); } public YangAugmentedInfo getAugmentedInfo(Class classObject) { return yangAugmentedInfoMap.get(classObject); } public Map<Class<?>, YangAugmentedInfo> getYangAugmentedInfoMap() { return yangAugmentedInfoMap; }
these methods will be providing augmentation functionalities for augmentable nodes. These class will be storing augmentedInfo , which is nothing but a augment node which are augmenting this node. Also we have provides one code snippet in OpParam file which checks if augmented info is set or not in IsFilterMatchMethod().
OpParam file will extend "YangAugmentedOpParamInfo" interface provides by YangUtils.
Example
File : Test.yang module Test { yang-version 1; namespace "http://huawei.com"; prefix Ant; description "Interval before a route is declared invalid"; container interface { leaf ifType { type string; } } augment "/interface" { leaf ds0ChannelNumber { type int16; } } }
File: TestService.java package org.onosproject.yang.gen.v1.http.huawei.com; public interface TestService { Test getTest(TestOpParam test); void setTest(TestOpParam test); Test getAugmentedTestYangAutoPrefixInterface(TestOpParam test); void setAugmentedTestYangAutoPrefixInterface(TestOpParam augmentedTestYangAutoPrefixInterface); } File : AugmentedInterface.java package org.onosproject.yang.gen.v1.http.huawei.com.test.yangautoprefixinterface; import java.util.BitSet; import org.onosproject.yang.gen.v1.http.huawei.com.Test.OnosYangOpType; public interface AugmentedInterface { public enum LeafIdentifier { DS0CHANNELNUMBER(1); private int leafIndex; public int getLeafIndex() { return leafIndex; } LeafIdentifier(int value) { this.leafIndex = value; } } short ds0ChannelNumber(); BitSet valueLeafFlags(); OnosYangOpType yangAugmentedInterfaceOpType(); BitSet selectLeafFlags(); boolean isLeafValueSet(LeafIdentifier leaf); boolean isSelectLeaf(LeafIdentifier leaf); interface AugmentedInterfaceBuilder { short ds0ChannelNumber(); BitSet valueLeafFlags(); OnosYangOpType yangAugmentedInterfaceOpType(); BitSet selectLeafFlags(); AugmentedInterfaceBuilder ds0ChannelNumber(short ds0ChannelNumber); AugmentedInterfaceBuilder yangAugmentedInterfaceOpType(OnosYangOpType yangAugmentedInterfaceOpType); AugmentedInterfaceBuilder selectLeaf(LeafIdentifier leaf); AugmentedInterface build(); } } File : DefaultAugmentedInterface.java package org.onosproject.yang.gen.v1.http.huawei.com.test.yangautoprefixinterface; import com.google.common.base.MoreObjects; import java.util.BitSet; import java.util.Objects; import org.onosproject.yang.gen.v1.http.huawei.com.Test.OnosYangOpType; public class DefaultAugmentedInterface implements AugmentedInterface { protected short ds0ChannelNumber; protected BitSet valueLeafFlags = new BitSet(); protected OnosYangOpType yangAugmentedInterfaceOpType; protected boolean isSubTreeFiltered; protected BitSet selectLeafFlags = new BitSet(); @Override public short ds0ChannelNumber() { return ds0ChannelNumber; } @Override public BitSet valueLeafFlags() { return valueLeafFlags; } @Override public OnosYangOpType yangAugmentedInterfaceOpType() { return yangAugmentedInterfaceOpType; } public boolean isSubTreeFiltered() { return isSubTreeFiltered; } @Override public BitSet selectLeafFlags() { return selectLeafFlags; } @Override public int hashCode() { return Objects.hash(ds0ChannelNumber, valueLeafFlags, yangAugmentedInterfaceOpType, isSubTreeFiltered, selectLeafFlags); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof DefaultAugmentedInterface) { DefaultAugmentedInterface other = (DefaultAugmentedInterface) obj; return Objects.equals(ds0ChannelNumber, other.ds0ChannelNumber) && Objects.equals(valueLeafFlags, other.valueLeafFlags) && Objects.equals(yangAugmentedInterfaceOpType, other.yangAugmentedInterfaceOpType) && Objects.equals(isSubTreeFiltered, other.isSubTreeFiltered) && Objects.equals(selectLeafFlags, other.selectLeafFlags); } return false; } @Override public String toString() { return MoreObjects.toStringHelper(getClass()) .omitNullValues() .add("ds0ChannelNumber", ds0ChannelNumber) .add("valueLeafFlags", valueLeafFlags) .add("yangAugmentedInterfaceOpType", yangAugmentedInterfaceOpType) .add("isSubTreeFiltered", isSubTreeFiltered) .add("selectLeafFlags", selectLeafFlags) .toString(); } protected DefaultAugmentedInterface(AugmentedInterfaceBuilder builderObject) { ds0ChannelNumber = builderObject.ds0ChannelNumber(); valueLeafFlags = builderObject.valueLeafFlags(); yangAugmentedInterfaceOpType = builderObject.yangAugmentedInterfaceOpType(); isSubTreeFiltered = builderObject.isSubTreeFiltered(); selectLeafFlags = builderObject.selectLeafFlags(); } public DefaultAugmentedInterface processSubtreeFiltering(AugmentedInterface appInstance, boolean isSelectAllSchemaChild) { AugmentedInterfaceBuilder subTreeFilteringResultBuilder = new AugmentedInterfaceBuilder(); BitSet isAnySelectOrContainmentNode = new BitSet(); if (!processLeafSubtreeFiltering(appInstance, subTreeFilteringResultBuilder, isAnySelectOrContainmentNode, isSelectAllSchemaChild)) { return null; } if (!isSelectAllSchemaChild && !isAnySelectOrContainmentNode.get(0)) { return processSubtreeFiltering(appInstance, true); } return (DefaultAugmentedInterface) subTreeFilteringResultBuilder.buildForFilter(); } private boolean processLeafSubtreeFiltering(AugmentedInterface appInstance, AugmentedInterfaceBuilder subTreeFilteringResultBuilder, BitSet isAnySelectOrContainmentNode, boolean isSelectAllSchemaChild) { if (valueLeafFlags.get(LeafIdentifier.DS0CHANNELNUMBER.getLeafIndex())) { if (appInstance.ds0ChannelNumber() != ds0ChannelNumber()) { if (isSubTreeFiltered && !appInstance.isLeafValueSet(LeafIdentifier.DS0CHANNELNUMBER)) { subTreeFilteringResultBuilder.ds0ChannelNumber(ds0ChannelNumber()); } else { return false; } } else { subTreeFilteringResultBuilder.ds0ChannelNumber(appInstance.ds0ChannelNumber()); } } else if (selectLeafFlags.get(LeafIdentifier.DS0CHANNELNUMBER.getLeafIndex()) || isSelectAllSchemaChild) { isAnySelectOrContainmentNode.set(0); subTreeFilteringResultBuilder.ds0ChannelNumber(appInstance.ds0ChannelNumber()); } return true; } protected DefaultAugmentedInterface() { } public static AugmentedInterfaceBuilder builder() { return new AugmentedInterfaceBuilder(); } @Override public boolean isLeafValueSet(LeafIdentifier leaf) { return valueLeafFlags.get(leaf.getLeafIndex()); } @Override public boolean isSelectLeaf(LeafIdentifier leaf) { return selectLeafFlags.get(leaf.getLeafIndex()); } public static class AugmentedInterfaceBuilder implements AugmentedInterface.AugmentedInterfaceBuilder { protected short ds0ChannelNumber; protected BitSet valueLeafFlags = new BitSet(); protected OnosYangOpType yangAugmentedInterfaceOpType; protected boolean isSubTreeFiltered; protected BitSet selectLeafFlags = new BitSet(); @Override public short ds0ChannelNumber() { return ds0ChannelNumber; } @Override public BitSet valueLeafFlags() { return valueLeafFlags; } @Override public OnosYangOpType yangAugmentedInterfaceOpType() { return yangAugmentedInterfaceOpType; } public boolean isSubTreeFiltered() { return isSubTreeFiltered; } @Override public BitSet selectLeafFlags() { return selectLeafFlags; } @Override public AugmentedInterfaceBuilder ds0ChannelNumber(short ds0ChannelNumber) { valueLeafFlags.set(LeafIdentifier.DS0CHANNELNUMBER.getLeafIndex()); this.ds0ChannelNumber = ds0ChannelNumber; return this; } @Override public AugmentedInterfaceBuilder yangAugmentedInterfaceOpType(OnosYangOpType yangAugmentedInterfaceOpType) { this.yangAugmentedInterfaceOpType = yangAugmentedInterfaceOpType; return this; } public AugmentedInterfaceBuilder isSubTreeFiltered(boolean isSubTreeFiltered) { this.isSubTreeFiltered = isSubTreeFiltered; return this; } @Override public AugmentedInterfaceBuilder selectLeaf(LeafIdentifier leaf) { selectLeafFlags.set(leaf.getLeafIndex()); return this; } @Override public AugmentedInterface build() { return new DefaultAugmentedInterface(this); } public AugmentedInterface buildForFilter() { isSubTreeFiltered = true; return new DefaultAugmentedInterface(this); } public AugmentedInterfaceBuilder() { } } }
Type
Overview
The "type" statement takes as an argument a string that is the name of a YANG built-in type or a derived type, followed by an optional block of sub statements that are used to put further restrictions on the type.
Java mapping
YANG | Description | JAVA |
---|---|---|
binary | Any binary data | byte[] |
bits | A set of bits or flags | BitSet in container class (A enum class for bits leaf) |
boolean | "True" or "false" | boolean |
decimal64 | 64-bit signed decimal number | BigDecimal |
empty | A leaf that does not have any value | boolean |
enumeration | Enumerated strings | Enum class will be generated |
identityref | A reference to an abstract identity | To be implemented |
instance-identifier | References a data tree node | String |
int8 | 8-bit signed integer | byte |
int16 | 16-bit signed integer | short |
int32 | 32-bit signed integer | int |
int64 | 64-bit signed integer | long |
leafref | A reference to a leaf instance | The type of referenced leaf/leaf-list will be used |
string | Human-readable string | String |
uint8 | 8-bit unsigned integer | short |
uint16 | 16-bit unsigned integer | int |
uint32 | 32-bit unsigned integer | long |
uint64 | 64-bit unsigned integer | BigInteger |
union | Choice of member types | Union class will be generated |
Example
leaf one { type string; } leaf two { type int32; } leaf-list three { type boolean; } leaf-list four { type int16; } leaf mybits { type bits { bit disable-nagle { position 0; } bit auto-sense-speed { position 1; } bit Mb-only { position 2; } } default "auto-sense-speed"; }
private String one; private int two; private List<Boolean> three; private List<Short> four; private BitSet mybits();
Typedef
Overview
Typedef is user defined type for his implementation. It has the base type which is must for typedef. To give more information about the typedef there should be sub statements to describe it. Unit statement is optional for typedef which give info about the unit of the type. Default is like a value which will be assigned to the typedef if no value is given.default value should follow all restriction defined for the base-type.
Java mapping
For a given typedef node one class file will be generated which will have an attribute with the base type of typedef. There will be a constructor and a getter method, of method and implementation of hashcode, equals and toString methods.
Example
File : test.yang module test { yang-version 1; namespace "http://huawei.com"; prefix "test"; typedef percent { type uint8; description "Percentage"; } leaf completed { type percent; } }
File : Percent.java package org.onosproject.yang.gen.v1.http.huawei.com.rev20160526.test; import java.util.Objects; import com.google.common.base.MoreObjects; public final class Percent { private short uint8; private Percent() { } public Percent(short value) { this.uint8 = value; } public static Percent of(short value) { return new Percent(value); } public short uint8() { return uint8; } @Override public int hashCode() { return Objects.hash(uint8); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof Percent) { Percent other = (Percent) obj; return Objects.equals(uint8, other.uint8); } return false; } @Override public String toString() { return MoreObjects.toStringHelper(getClass()) .add("uint8", uint8) .toString(); } public static Percent fromString(String valInString) { try { short tmpVal = Short.parseShort(valInString); return of(tmpVal); } catch (Exception e) { } return null; } }
Enumeration
Overview
Enum statement only can come when a leaf is of type enumeration. Each enum has one string then should be unique . The string must not be empty string and must not have white spaces. Enum can have sub statements, value statement will give the info about its value. If the enum statement in enumeration has no value statement then its value is considered as zero and subsequently incremented by one for next values.
Java mapping
For a given enumeration node one enum file will be generated which will have all the enum as its attributes. There will be a constructor and a getter method for the values.
Example
File: test.yang module Test { yang-version 1; namespace "http://huawei.com"; prefix Ant; description "Interval before a route is declared invalid"; leaf packetType { type enumeration { enum "unbounded"; enum ZERO; enum two; enum four; } } }
File : PacketTypeEnum.java package org.onosproject.yang.gen.v1.http.huawei.com.test; public enum PacketTypeEnum { UNBOUNDED(0, "unbounded"), ZERO(1, "ZERO"), TWO(2, "two"), FOUR(3, "four"); private int packetTypeEnum; private String schemaName; PacketTypeEnum(int packetTypeEnum, String schemaName) { this.packetTypeEnum = packetTypeEnum; this.schemaName = schemaName; } public static PacketTypeEnum of(int value) { switch (value) { case 0: return PacketTypeEnum.UNBOUNDED; case 1: return PacketTypeEnum.ZERO; case 2: return PacketTypeEnum.TWO; case 3: return PacketTypeEnum.FOUR; default : return null; } } public static PacketTypeEnum of(String value) { switch (value) { case "unbounded": return PacketTypeEnum.UNBOUNDED; case "ZERO": return PacketTypeEnum.ZERO; case "two": return PacketTypeEnum.TWO; case "four": return PacketTypeEnum.FOUR; default : return null; } } public int packetTypeEnum() { return packetTypeEnum; } @Override public String toString() { return schemaName; } }
Union
Overview
Union is a built in type which represents its member types. Union can have multiple member types. To use union there must be a type statement. Except empty and leafref all types can come under union.
When a value comes for union , which can match to multiple member types of union, then in that case to whichever type value matches from the member types defined in union value, will be taken from union as the values type.
Java mapping
For a given union node one class file will be generated which will have all the an attribute with the type union is having. There will be a constructor , getter method, of method, fromString, HashCode, equals and ToString methods for the values.
Example
File : test.yang module test { yang-version 1; namespace "http://huawei.com"; prefix "test"; typedef ip-address { type union { type int32; type uint32; } } }
File : IpAddressUnion.java package org.onosproject.yang.gen.v1.http.huawei.com.rev20160526.test.ipaddress; import java.util.Objects; import com.google.common.base.MoreObjects; public final class IpAddressUnion { private int int32; private long uint32; private IpAddressUnion() { } public IpAddressUnion(int value) { this.int32 = value; } public IpAddressUnion(long value) { this.uint32 = value; } public static IpAddressUnion of(int value) { return new IpAddressUnion(value); } public static IpAddressUnion of(long value) { return new IpAddressUnion(value); } public int int32() { return int32; } public long uint32() { return uint32; } @Override public int hashCode() { return Objects.hash(int32, uint32); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof IpAddressUnion) { IpAddressUnion other = (IpAddressUnion) obj; return Objects.equals(int32, other.int32) && Objects.equals(uint32, other.uint32); } return false; } @Override public String toString() { return MoreObjects.toStringHelper(getClass()) .omitNullValues() .add("int32", int32) .add("uint32", uint32) .toString(); } public static IpAddressUnion fromString(String valInString) { try { int tmpVal = Integer.parseInt(valInString); return of(tmpVal); } catch (Exception e) { } try { long tmpVal = Long.parseLong(valInString); return of(tmpVal); } catch (Exception e) { } return null; } }
When there are two types with same java mapping. for resolving this conflict we will be checking the range of the value and then we will assign it to the right attribute. Order will be taken care of while code generation and conflict range validation . for example : if union have type int32 followed by uint16, then range validation will be done on basis of int32 , in other case range will be validated on basis of uint16.
File : test.yang module test { yang-version 1; namespace "http://huawei.com"; prefix "test"; typedef ip-address { type union { type int32; type uint16; type int64; type uint32; type string; } } }
File : IpAddressUnion.java package org.onosproject.yang.gen.v1.http.huawei.com.rev20160721.test.ipaddress; import com.google.common.base.MoreObjects; import java.math.BigInteger; import java.util.Objects; public final class IpAddressUnion { private static final int INT32_MIN_RANGE = -2147483648; private static final int INT32_MAX_RANGE = 2147483647; private static final BigInteger INT64_MIN_RANGE = new BigInteger("-9223372036854775808"); private static final BigInteger INT64_MAX_RANGE = new BigInteger("9223372036854775807"); private int int32; private int uint16; private long int64; private long uint32; private String string; private IpAddressUnion() { } public IpAddressUnion(String value) { this.string = value; } public IpAddressUnion(int value) { if (validateRange(INT32_MIN_RANGE, INT32_MAX_RANGE, value)) { this.int32 = value; } else { this.uint16 = value; } } public IpAddressUnion(long value) { if (validateRange(INT64_MIN_RANGE, INT64_MAX_RANGE, value)) { this.int64 = value; } else { this.uint32 = value; } } public static IpAddressUnion of(String value) { return new IpAddressUnion(value); } public static IpAddressUnion of(int value) { return new IpAddressUnion(value); } public static IpAddressUnion of(long value) { return new IpAddressUnion(value); } public String string() { return string; } public int int32() { return int32; } public long int64() { return int64; } @Override public int hashCode() { return Objects.hash(int32, uint16, int64, uint32, string); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof IpAddressUnion) { IpAddressUnion other = (IpAddressUnion) obj; return Objects.equals(int32, other.int32) && Objects.equals(uint16, other.uint16) && Objects.equals(int64, other.int64) && Objects.equals(uint32, other.uint32) && Objects.equals(string, other.string); } return false; } @Override public String toString() { return MoreObjects.toStringHelper(getClass()) .omitNullValues() .add("int32", int32) .add("uint16", uint16) .add("int64", int64) .add("uint32", uint32) .add("string", string) .toString(); } public static IpAddressUnion fromString(String valInString) { try { String tmpVal = (valInString); return of(tmpVal); } catch (Exception e) { } try { int tmpVal = Integer.parseInt(valInString); return of(tmpVal); } catch (Exception e) { } try { long tmpVal = Long.parseLong(valInString); return of(tmpVal); } catch (Exception e) { } return null; } private boolean validateRange(int minRange, int maxRange, int value) { return value >= minRange && value<= maxRange; } private boolean validateRange(BigInteger minRange, BigInteger maxRange, long value) { BigInteger bigInteger = new BigInteger(" " + value); return bigInteger.compareTo(minRange) == 1 && bigInteger.compareTo(maxRange) == 1; } }
Leafref
Overview
The leafref type is used to reference a particular leaf instance in the data tree. Path statement must be present for leafref type. The path under leafref must refer to existing leaf or leaf-list. The leaf or leaf-list with leafref will use the instance of the referred leaf or leaf-list.
If leafref comes under grouping and typedef, it will be resolved where it is used. It will not be resolved where it is defined.
Java mapping
The leaf or leaf-list with type leafref, will copy the type of referred leaf or leaf-list, during java file generation. If leaf-ref is directly inside grouping then the generated return type of that leaf will be Object.
Example
File : ietf-network.yang module ietf-network { yang-version 1; namespace "urn:ietf:params:xml:ns:yang:ietf-network"; prefix nd; container networks { description "Serves as top-level container for a list of networks."; leaf id { type uint8; description "Identifies a network."; } container network { leaf network-id { type leafref { path "/nd:networks/nd:id"; } } } uses network-id; } grouping network-id { description "Serves as top-level container for a list of networks."; leaf network-id { type leafref { path "/nd:networks/nd:id"; } } } }
File : Networks.java package org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.ietfnetwork; import java.util.BitSet; import java.util.Map; import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.IetfNetwork.OnosYangOpType; import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.ietfnetwork.networks.Network; public interface Networks { public enum LeafIdentifier { ID(1), NETWORKID(2); private int leafIndex; public int getLeafIndex() { return leafIndex; } LeafIdentifier(int value) { this.leafIndex = value; } } short id(); Object networkId(); BitSet valueLeafFlags(); OnosYangOpType yangNetworksOpType(); BitSet selectLeafFlags(); Map<Class<?>, Object> yangAugmentedInfoMap(); Network network(); Object yangAugmentedInfo(Class classObject); boolean isLeafValueSet(LeafIdentifier leaf); boolean isSelectLeaf(LeafIdentifier leaf); interface NetworksBuilder { short id(); Object networkId(); BitSet valueLeafFlags(); OnosYangOpType yangNetworksOpType(); BitSet selectLeafFlags(); Map<Class<?>, Object> yangAugmentedInfoMap(); Network network(); NetworksBuilder id(short id); NetworksBuilder networkId(Object networkId); NetworksBuilder yangNetworksOpType(OnosYangOpType yangNetworksOpType); NetworksBuilder network(Network network); NetworksBuilder addYangAugmentedInfo(Object value, Class classObject); Object yangAugmentedInfo(Class classObject); NetworksBuilder selectLeaf(LeafIdentifier leaf); Networks build(); } } File : Networks.java package org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.ietfnetwork.networks; import java.util.BitSet; import java.util.Map; import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.IetfNetwork.OnosYangOpType; public interface Network { public enum LeafIdentifier { NETWORKID(1); private int leafIndex; public int getLeafIndex() { return leafIndex; } LeafIdentifier(int value) { this.leafIndex = value; } } short networkId(); BitSet valueLeafFlags(); OnosYangOpType yangNetworkOpType(); BitSet selectLeafFlags(); Map<Class<?>, Object> yangAugmentedInfoMap(); Object yangAugmentedInfo(Class classObject); boolean isLeafValueSet(LeafIdentifier leaf); boolean isSelectLeaf(LeafIdentifier leaf); interface NetworkBuilder { short networkId(); BitSet valueLeafFlags(); OnosYangOpType yangNetworkOpType(); BitSet selectLeafFlags(); Map<Class<?>, Object> yangAugmentedInfoMap(); NetworkBuilder networkId(short networkId); NetworkBuilder yangNetworkOpType(OnosYangOpType yangNetworkOpType); NetworkBuilder addYangAugmentedInfo(Object value, Class classObject); Object yangAugmentedInfo(Class classObject); NetworkBuilder selectLeaf(LeafIdentifier leaf); Network build(); } }
Identity
Overview
The identity is used to define a new globally unique, abstract, and untyped identity. Its only purpose is to denote its name, semantics, and existence. An identity can iether be defined from scratch or derived from a base identity. The base statement, which is optional, takes as an argument a string that is the name of an existing identity, from which the new identity is derived.
Java mapping
For a given identity one abstract class file will be generated.
Example
File : ietf-network.yang module ietf-network { yang-version 1; namespace "urn:ietf:params:xml:ns:yang:ietf-network"; prefix nd; identity tunnel-type { description "Base identity from which specific tunnel types are derived."; } }
File : TunnelType.java package org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.ietfnetwork; public abstract class TunnelType { public static String tunnelTypeToString() { return "tunnel-type"; } public static Class fromString(String valInString) { if (valInString.equals("tunnel-type")) { return TunnelType.class; } throw new IllegalArgumentException("not a valid input element"); } }
Identityref
Overview
The identityref type is used to reference an existing identity. Base statement, which is a substatement to the type statement, must be present if the type is identityref. The base under identityref must refer to existing identity.
If identityref comes under grouping and typedef, it will be resolved where it is used. It will not be resolved where it is defined.
Java mapping
The leaf or leaf-list with type identityref, will referred to identity, during java file generation.
Example
File : ietf-network.yang module ietf-network { yang-version 1; namespace "urn:ietf:params:xml:ns:yang:ietf-network"; prefix nd; identity tunnel-type { description "Base identity from which specific tunnel types are derived."; } container network-id { description "Serves as top-level container for a list of networks."; leaf leaf-network-id { type identityref { base tunnel-type; } } } }
File : TunnelType.java package org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.ietfnetwork; public abstract class TunnelType { public static String tunnelTypeToString() { return "tunnel-type"; } public static Class fromString(String valInString) { if (valInString.equals("tunnel-type")) { return TunnelType.class; } throw new IllegalArgumentException("not a valid input element"); } } File : NetworkId.java package org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.ietfnetwork; import java.util.BitSet; import java.util.Map; import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.IetfNetwork.OnosYangOpType; public interface NetworkId { public enum LeafIdentifier { LEAFNETWORKID(1); private int leafIndex; public int getLeafIndex() { return leafIndex; } LeafIdentifier(int value) { this.leafIndex = value; } } Class<? extends TunnelType> leafNetworkId(); BitSet valueLeafFlags(); OnosYangOpType yangNetworkIdOpType(); BitSet selectLeafFlags(); Map<Class<?>, Object> yangAugmentedInfoMap(); Object yangAugmentedInfo(Class classObject); boolean isLeafValueSet(LeafIdentifier leaf); boolean isSelectLeaf(LeafIdentifier leaf); interface NetworkIdBuilder { Class<? extends TunnelType> leafNetworkId(); BitSet valueLeafFlags(); OnosYangOpType yangNetworkIdOpType(); BitSet selectLeafFlags(); Map<Class<?>, Object> yangAugmentedInfoMap(); NetworkIdBuilder leafNetworkId(Class<? extends TunnelType> leafNetworkId); NetworkIdBuilder yangNetworkIdOpType(OnosYangOpType yangNetworkIdOpType); NetworkIdBuilder addYangAugmentedInfo(Object value, Class classObject); Object yangAugmentedInfo(Class classObject); NetworkIdBuilder selectLeaf(LeafIdentifier leaf); NetworkId build(); } }
Bits
Overview
The bits built-in type represents a bit set. That is, a bits value is a set of flags identified by small integer position numbers starting at 0.
The "bit" statement, which is a substatement to the "type" statement, MUST be present if the type is "bits". It is repeatedly used to specify each assigned named bit of a bits type. It takes as an argument a string that is the assigned name of the bit. All assigned names in a bits type MUST be unique.
The "position" statement, which is optional, takes as an argument a non-negative integer value that specifies the bit's position.
Java mapping
Container BitSet is used to store bits during code generation.
Example
File : test.yang module Test { yang-version 1; namespace http://huawei.com; prefix Ant; typedef MyBits { type bits { bit disable-nagle { position 0; } bit auto-sense-speed { position 1; } bit Mb-only { position 2; } } } }
package org.onosproject.yang.gen.v1.http.huawei.com.test.mybits; import java.util.BitSet; import java.util.regex.Pattern; public enum Bits { DISABLE_NAGLE(0, "disable-nagle"), AUTO_SENSE_SPEED(1, "auto-sense-speed"), MB_ONLY(2, "Mb-only"); private int bits; private String schemaName; Bits(int bits, String schemaName) { this.bits = bits; this.schemaName = schemaName; } public static Bits of(int value) { switch (value) { case 0: return Bits.DISABLE_NAGLE; case 1: return Bits.AUTO_SENSE_SPEED; case 2: return Bits.MB_ONLY; default : return null; } } public static Bits of(String value) { switch (value) { case "disable-nagle": return Bits.DISABLE_NAGLE; case "auto-sense-speed": return Bits.AUTO_SENSE_SPEED; case "Mb-only": return Bits.MB_ONLY; default : return null; } } public int bits() { return bits; } public static BitSet fromString(String valInString) { BitSet tmpVal = new BitSet(); String[] bitNames = valInString.trim().split(Pattern.quote(" ")); for (String bitName : bitNames) { Bits bits = of(bitName); if (bits != null) { tmpVal.set(bits.bits()); } } if (tmpVal.isEmpty()) { throw new IllegalArgumentException("no such element found in bits"); } return tmpVal; } public static String toString(BitSet bits) { StringBuilder sBuild = new StringBuilder(""); if (bits.get(Bits.DISABLE_NAGLE.bits())) { sBuild.append("disable-nagle"); sBuild.append(" "); } if (bits.get(Bits.AUTO_SENSE_SPEED.bits())) { sBuild.append("auto-sense-speed"); sBuild.append(" "); } if (bits.get(Bits.MB_ONLY.bits())) { sBuild.append("Mb-only"); sBuild.append(" "); } return sBuild.toString(); } }
File: MyBits.java package org.onosproject.yang.gen.v1.http.huawei.com.test; import java.util.BitSet; import org.onosproject.yang.gen.v1.http.huawei.com.test.mybits.Bits; import java.util.Objects; public final class MyBits { private BitSet bits; private MyBits() { } public MyBits(BitSet bits) { this.bits = bits; } public static MyBits of(BitSet value) { return new MyBits(value); } public BitSet bits() { return bits; } @Override public int hashCode() { return Objects.hash(bits); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof MyBits) { MyBits other = (MyBits) obj; return Objects.equals(bits, other.bits); } return false; } @Override public String toString() { return Bits.toString(bits); } public static MyBits fromString(String valInString) { try { BitSet tmpVal = Bits.fromString(valInString); return of(tmpVal); } catch (Exception e) { } return null; } }
Binary
Overview
The binary built-in type represents any binary data, i.e., a sequence of octets.
A binary can be restricted with the "length" statement. The length of a binary value is the number of octets it contains.
Binary values are encoded with the base64 encoding scheme.
Java mapping
Byte array is used to store decoded binary during code generation.
Example
File : test.yang module Test { yang-version 1; namespace http://huawei.com; prefix Ant; typedef MyBinary { type binary { length "4"; } } }
File: MyBinary.java package org.onosproject.yang.gen.v1.http.huawei.com.rev20160718.test; import java.util.Objects; import com.google.common.base.MoreObjects; import java.util.Base64; public final class MyBinary { private byte[] binary; private MyBinary() { } public MyBinary(byte[] value) { this.binary = value; } public static MyBinary of(byte[] value) { return new MyBinary(value); } public byte[] binary() { return binary; } @Override public int hashCode() { return Objects.hash(binary); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof MyBinary) { MyBinary other = (MyBinary) obj; return Objects.equals(binary, other.binary); } return false; } @Override public String toString() { return Base64.getEncoder().encodeToString(binary); } public static MyBinary fromString(String valInString) { try { byte[] tmpVal = Base64.getDecoder().decode(valInString); return of(tmpVal); } catch (Exception e) { } return null; } }
Decimal64
Overview
The decimal64 type represents a subset of the real numbers, which can be represented by decimal numerals.
A decimal64 type can be restricted with the "range" statement.
The "fraction-digits" statement, which is a substatement to the "type" statement, MUST be present if the type is "decimal64". It takes as an argument an integer between 1 and 18, inclusively. It controls the size of the minimum difference between values of a decimal64 type.
The Minimum and Maximum decimal64 value table for each fraction-digit value.
fraction-digits | min | max |
---|---|---|
1 | -922337203685477580.8 | 922337203685477580.7 |
2 | -92233720368547758.08 | 92233720368547758.07 |
3 | -9223372036854775.808 | 9223372036854775.807 |
4 | -922337203685477.5808 | 922337203685477.5807 |
5 | -92233720368547.75808 | 92233720368547.75807 |
6 | -9223372036854.775808 | 9223372036854.775807 |
7 | -922337203685.4775808 | 922337203685.4775807 |
8 | -92233720368.54775808 | 92233720368.54775807 |
9 | -9223372036.854775808 | 9223372036.854775807 |
10 | -922337203.6854775808 | 922337203.6854775807 |
11 | -92233720.36854775808 | 92233720.36854775807 |
12 | -9223372.036854775808 | 9223372.036854775807 |
13 | -922337.2036854775808 | 922337.2036854775807 |
14 | -92233.72036854775808 | 92233.72036854775807 |
15 | -9223.372036854775808 | 9223.372036854775807 |
16 | -922.3372036854775808 | 922.3372036854775807 |
17 | -92.23372036854775808 | 92.23372036854775807 |
18 | -9.223372036854775808 | 9.223372036854775807 |
Java mapping
BigDecimal is used to store decimal64 value during code generation.
Example
File : test.yang module Test { yang-version 1; namespace http://huawei.com; prefix Ant; typedef MyDecimal { type decimal64 { fraction-digits 2; range "1 .. 3.14 | 10 | 20..max"; } } }
File: MyDecimal.java package org.onosproject.yang.gen.v1.http.huawei.com.rev20160718.test; import java.math.BigDecimal; import java.util.Objects; import com.google.common.base.MoreObjects; public final class MyDecimal { private BigDecimal decimal64; private MyDecimal() { } public MyDecimal(BigDecimal value) { this.decimal64 = value; } public static MyDecimal of(BigDecimal value) { return new MyDecimal(value); } public BigDecimal decimal64() { return decimal64; } @Override public int hashCode() { return Objects.hash(decimal64); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof MyDecimal) { MyDecimal other = (MyDecimal) obj; return Objects.equals(decimal64, other.decimal64); } return false; } @Override public String toString() { return MoreObjects.toStringHelper(getClass()) .add("decimal64", decimal64) .toString(); } public static MyDecimal fromString(String valInString) { try { BigDecimal tmpVal = new BigDecimal(valInString); return of(tmpVal); } catch (Exception e) { } return null; } }
Golden Eye Demo
Link: https://www.youtube.com/watch?v=ipbu0x0LcDk
Presentation: YANG Demo.pptx
References
RFC6020 - https://tools.ietf.org/html/rfc6020
Name | Organization | |
---|---|---|
Adarsh M | Huawei Technologies | adarsh.m@huawei.com |
Bharat Saraswal | Huawei Technologies | bharat.saraswal@huawei.com |