Have questions? Stuck? Please check our FAQ for some common questions and answers.

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 24 Next »

Team

NameOrganizationEmail
Adarsh MHuawei Technologiesadarsh.m@huawei.com
Bharat SaraswalHuawei Technologiesbharat.saraswal@huawei.com
Gaurav Agrawal Huawei Technologiesgaurav.agrawal@huawei.com
Janani BHuawei Technologiesjanani.b@huawei.com
Sathish Kumar MHuawei Technologiessathishkumar.m@huawei.com
Suchitra H NHuawei Technologiessuchitra.hn@huawei.com
Vidyashree RamaHuawei Technologiesvidyashree.rama@huawei.com
Vinod Kumar SHuawei Technologiesvinods.kumar@huawei.com

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:

  1. syntax/semantics processing of the request/response being exchanged.
     
  2. 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>yangutils-maven-plugin</artifactId>
      <version>1.0.0-SNAPSHOT</version>
      <executions>
        <execution>
          <configuration>
          </configuration>
          <goals>
            <goal>yang2java</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

Step 2 : Add dependency to pom file’s dependency section

<dependencies>
    <dependency>
        <groupId>org.onosproject</groupId>
        <artifactId>yangutils-maven-plugin</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.onosproject</groupId>
        <artifactId>onos-api</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.felix</groupId>
        <artifactId>org.apache.felix.scr.annotations</artifactId>
    </dependency>
</dependencies>

Step 3 : Plugin configuration supported in YANG utils 

  1. Create a folder structure as “src/main/yang” in the test app folder and place your YANG files in it. If incase 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>/opt/src/yang/</yangFilesDir>
        <genFilesDir>/opt/src/java/</genFilesDir> 
    </configuration>

     

  2. In YANG, identifier has the support of having “.”, ”-”, “_”. But, in java, we cannot use these characters in class name or attribute name. Hence, by default, these characters will be removed and the successive character will be capitalized for making it camel case. Similarly, in YANG, we can have java keywords and starting with digits, in namespace and identifiers. But, in java, we cannot use it in class name or attribute name or package. Hence, by default, a prefix "yangAutoPrefix" will be added to the identifier name.Here users are given options to change this default behaviour.“.”, ”-”, “_” in identifier name can be replaced by the values given inside the configuration of pom.xml and will be used in java, respectively. Similarly, the prefix value can also be provided in configuration of pom.xml and that will be used as prefix for identifiers.(refer identifier for more details)

    <configuration>
        <replacementForPeriod>dot</replacementForPeriod>
        <replacementForHyphen>hyphen</replacementForHyphen>
        <replacementForUnderscore>underscore</replacementForUnderscore>
        <prefixForIdentifier>prefix</prefixForIdentifier>
    </configuration>
      1. yang-._constuct-generation will be mapped as yangHyphenDotUnderscoreConstuctHyphenGeneration 

      2. const will be mapped as prefixConst

  3.  Default package/folder structure for generated code will be constructed from the namespace of the YANG file and if user wants to generated code with specific folder structure/package he can configure it , using below configurations.

    <configuration>
        <defaultPackage>org.onosproject.sfc</defaultPackage>
    </configuration>

    In above example code will be generated in org.onosproject.sfc package.

  4. As Grouping construct being an special case in YANG. we are giving user a flexibility to choose whether to generate code for grouping node or not. So if user does not wants to generate code he should set the configurations  as false. By default code will be generated. 

    <configuration>
        <groupingCodeGenFlag>true</groupingCodeGenFlag>
    </configuration>

     

  5. In case of RPC construct we have given flexibility for controlling the generation of code for input and output sub statements in a special cases where Input or output contains only one leaf/leaf-list/Yang construct. In such case user can configure whether he wants to generate code for input or output. By default code will be generated and in case input or output contains multiple leaf/leaf-list/Yang constructs code will be generated even the configuration is false.

    <configuration>
        <rpcSubStatementCodeGenFlag>true</rpcSubStatementCodeGenFlag>
    </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.

Note : Code generated is as per ONOS coding guidelines.

YANG utils constructs support/plan

YANG ConstructSupported/Planned version
anyxmlNot planned
argumentNot planned
augmentGoldeneye
baseHummingbird
belongs-toGoldeneye
bitGoldeneye
caseGoldeneye
choiceGoldeneye
configFalcon
contact

Goldeneye

Enhancement in Hummingbird

containerFalcon
default

Goldeneye

Enhancement in Humminbird

description

Goldeneye

Enhancement in Hummingbird

deviateNot planned
deviationNot planned
enumGoldeneye
error-app-tagNot planned
error-messageNot planned
extensionNot planned
featureHummingbird
fraction-digitsGoldeneye
groupingGoldeneye
identityHummingbird
if-featureHummingbird
import

Goldeneye

Enhancement in Hummingbird

include

Goldeneye

Enhancement in Hummingbird

inputGoldeneye
keyGoldeneye
leafFalcon
leaf-listFalcon
lengthGoldeneye
listFalcon
mandatoryFalcon
max-elementsGoldeneye
min-elementsGoldeneye
moduleFalcon
mustHummingbird
namespaceGoldeneye
notificationGoldeneye
ordered-byNot planned
organization

Goldeneye

Enhancement in Hummingbird
outputGoldeneye
pathHummingbird
patternGoldeneye
positionGoldeneye
prefixGoldeneye
presenceGoldeneye
rangeGoldeneye
reference

Goldeneye

Enhancement in Hummingbird
refineNot planned
require-instanceNot planned
revision

Goldeneye

Enhancement in Hummingbird
revision-date

Goldeneye

rpcGoldeneye
status

Goldeneye

Enhancement in Hummingbird
submoduleGoldeneye
typeGoldeneye
typedefGoldeneye
uniqueNot Planned
units

Goldeneye

usesGoldeneye
valueGoldeneye
whenHummingbird
yang-versionGoldeneye
yin-elementNot Planned

Built-in YANG data types support/plan

Binary

Goldeneye

Enhancement in Hummingbird
Bits

Goldeneye

Enhancement in Hummingbird
booleanGoldeneye
decimal64

Goldeneye

Enhancement in Hummingbird
emptyGoldeneye
enumerationGoldeneye
identityrefHummingbird
instance-identifierHummingbird
int8Goldeneye
int16Goldeneye
int32Goldeneye
int64Goldeneye
leafrefHummingbird
stringFalcon
uint8Goldeneye
uint16Goldeneye
uint32Goldeneye
uint64Goldeneye
unionGoldeneye

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

Note :  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. 

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.

  • When a node occurs in yang, a new package will be generated under the parent package. The new package name is the node name and class for that node will be placed under this newly created package. The conversion from yang namespace to the java package will take place as below.

Javadocs

Currently Java doc will be generated as per ONOS javadoc guidelines.
Note: Here in wiki for the given examples for each YANG construct we have removed generated javadocs for documentation purpose. Code will contain all the default javadoc which we are providing in golden-eye release. Javadocs support will be enhanced in hummingbird release.

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

  1. 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)
  2. Manager class
    It includes:
    a ) Activate/Deactivate methods
    b) If module contains child data nodes, getters and setters for those nodes will be generated for app developers to implement.
    c)If module contains notification, generated manager class will extend ListenerRegistry(refer notification for more details) .
     
    The manager class implements the service interface. The name of service interface and manager class is <module_name>Service.java and <module_name>Manager.java.
Example
Input YANG file
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;
       }
     }
     ….
}
Generated Java files
File : NetworkService.java
package org.onosproject.yang.gen.v1.urn.tbd.params.xml.ns.yang.nodes.rev20140309;

import java.util.List;
import org.onosproject.yang.gen.v1.urn.tbd.params.xml.ns.yang.nodes.rev20140309.network.Networklist;

public interface NetworkService {

    List<Networklist> getNetworklist();

    void setNetworklist(List<Networklist> networklist);
}


File : NetworkManager.java
package org.onosproject.yang.gen.v1.urn.tbd.params.xml.ns.yang.nodes.rev20140309;

import java.util.List;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Service;
import org.onosproject.yang.gen.v1.urn.tbd.params.xml.ns.yang.nodes.rev20140309.network.Networklist;
import org.slf4j.Logger;
import static org.slf4j.LoggerFactory.getLogger;

@Component (immediate = true)
@Service
public class NetworkManager implements NetworkService {

    private final Logger log = getLogger(getClass());

    @Activate
    public void activate() {
        //TODO: YANG utils generated code
          log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        //TODO: YANG utils generated code
          log.info("Stopped");
    }

    @Override
    public List<Networklist> getNetworklist() {
        //TODO: YANG utils generated code
          return null;
    }

    @Override
    public void setNetworklist(List<Networklist> networklist) {
          //TODO: YANG utils generated code
    }
}

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
Input YANG files
File : acme-system.yang
module acme-system {
    namespace "http://yang-central.org/ns/example/acme";
    prefix acme;

    include "acme-types";
 
    leaf id {
        type string;
    }
}
File : acme-types.yang
submodule acme-types {
    yang-version 1;
    belongs-to "acme-system" {
        prefix "acme";
    }
    leaf access-timeout {
        type uint32;
    }
    leaf retries {
        type uint8;
    }
}
Generated Java files
File : AcmeSystemManager.java
package org.onosproject.yang.gen.v1.http.yang.central.org.ns.example.acme.rev20160526;

import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Service;
import org.slf4j.Logger;
import static org.slf4j.LoggerFactory.getLogger;

@Component (immediate = true)
@Service
public class AcmeSystemManager implements AcmeSystemService {

    private final Logger log = getLogger(getClass());

    @Activate
    public void activate() {
        //TODO: YANG utils generated code
          log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        //TODO: YANG utils generated code
          log.info("Stopped");
    }

    @Override
    public String getId() {
          //TODO: YANG utils generated code
          return null;
    }

    @Override
    public void setId(String id) {
        //TODO: YANG utils generated code
    }
}

File : AcmeSystemService.java
package org.onosproject.yang.gen.v1.http.yang.central.org.ns.example.acme.rev20160526;

public interface AcmeSystemService {

    String getId();

    void setId(String id);
}

File : AcmeTypesManager.java
package org.onosproject.yang.gen.v1.http.yang.central.org.ns.example.acme.rev20160526;

import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Service;
import org.slf4j.Logger;
import static org.slf4j.LoggerFactory.getLogger;

@Component (immediate = true)
@Service
public class AcmeTypesManager implements AcmeTypesService {

    private final Logger log = getLogger(getClass());

    @Activate
    public void activate() {
        //TODO: YANG utils generated code
          log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        //TODO: YANG utils generated code
          log.info("Stopped");
    }

    @Override
    public long getAccessTimeout() {
        //TODO: YANG utils generated code
          return 0;
    }

    @Override
    public short getRetries() {
          //TODO: YANG utils generated code
          return 0;
    }

    @Override
    public void setAccessTimeout(long accessTimeout) {
        //TODO: YANG utils generated code
    }

    @Override
    public void setRetries(short retries) {
          //TODO: YANG utils generated code
    }
}

File : AcmeTypesService.java
package org.onosproject.yang.gen.v1.http.yang.central.org.ns.example.acme.rev20160526;

public interface AcmeTypesService {
    long getAccessTimeout();

    short getRetries();

    void setAccessTimeout(long accessTimeout);

    void setRetries(short retries);
}

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
Input YANG files
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";
     }
}

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
Input YANG file
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";
           }
     }
    .
    .
    .
}

 

Generated Java files
File: System.java
public interface System extends AugmentationHolder  {
    String hostName();
    interface SystemBuilder {
        String hostName();
        SystemBuilder hostName(String hostName);
        System build();
    }
}

File : SystemBuilder.java
public class SystemBuilder implements System.SystemBuilder {
    private String hostName;

    @Override
    public String hostName() {
        return hostName;
    }
    @Override
    public SystemBuilder hostName(String hostName) {
        this.hostName = hostName;
        return this;
    }
    .
    .
    .
    public final class SystemImpl implements System {
        private String hostName;
        @Override
        public String hostName() {
            return hostName;
        }
    .
    .
    .
    }
}

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
Input YANG file
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";
             }
     }
    .
    .
    .
}

 

Generated Java files
File : System.java
public interface System extends AugmentationHolder  {
    String hostName();
    interface SystemBuilder {
        String hostName();
        SystemBuilder hostName(String hostName);
        System build();
    }
}

File : SystemBuilder.java
public class SystemBuilder implements System.SystemBuilder {
    private List<String> domainSearch;
    @Override
    public List<String> domainSearch() {
        return domainSearch;
    }
    @Override
    public SystemBuilder domainSearch(List<String> domainSearch) {
        this.domainSearch = domainSearch;
        return this;
    }
    .
    .
    .
    public final class SystemImpl implements System {
        private List<String> domainSearch;
        @Override
        public List<String> domainSearch() {
            return domainSearch;
        }
    .
    .
    .
        }
}

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                  

  1.  Interface
    It includes:
    a) The interface file has two interfaces defined. One interface which is for the impl class and one for the builder class. 
    b) The interface for builder class contains method for getter and setters of the attributes without get and set prefix respectively. And a method to create object of impl class. The interface for impl class contains only a getter of the attribute without get prefix
  2. Builder Class
    It includes:
    a) Builder class implements the builder interface.
    b) It has impl class inside which also implements impl interface. This also has hashCode(), equals(), toString() methods overridden in it. Further augmentation also is implemented here(refer augmentation for more details).
Example
Input YANG file
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";
             }
        }
    }
    .
    .
    .
}

 

Generated Java files
File : Login.java
public interface Login extends AugmentationHolder  {
    String message();
    interface LoginBuilder {
        String message();
        LoginBuilder message(String message);
        Login build();
    }
}

File : SystemBuilder.java
public class LoginBuilder implements Login.LoginBuilder {
    private String message;
    @Override
    public String message() {
        return message;
    }
    @Override
    public LoginBuilder message(String message) {
        this.message = message;
        return this;
    }
    @Override
    public Login build() {
        return new LoginImpl(this);
    }
    public LoginBuilder() {
    }
    public final class LoginImpl implements Login {
        private List<AugmentedInfo> augmentedInfoList = new ArrayList<>();
        private String message;
        @Override
        public String message() {
            return message;
        }
        @Override
        public int hashCode() {
            return Objects.hash(message);
        }
        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj instanceof LoginImpl) {
                LoginImpl other = (LoginImpl) obj;
                return
                     Objects.equals(message, other.message);
            }
            return false;
        }
        @Override
        public String toString() {
            return MoreObjects.toStringHelper(getClass())
                .add("message", message)
                .toString();
        }
        public LoginImpl(LoginBuilder builderObject) {
            this.message = builderObject.message();
        }
        @Override
        public void addAugmentation(AugmentedInfo value) {
            getAugmentedInfoList().add(value);
        }
        @Override
        public List<AugmentedInfo> getAugmentedInfoList() {
            return augmentedInfoList;
        }
        @Override
        public void removeAugmentation() {
            getAugmentedInfoList().clear();
        }
    }
}

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

Input YANG file
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;
        }
    }
    .
    .
    .
}
Generated Java files
File : Login.java
public interface Login extends AugmentationHolder  {
    String name();
    String fullName();
    String addThisBeforeClass();
    interface LoginBuilder {
        String name();
        String fullName();
        String addThisBeforeClass();
        LoginBuilder name(String name);
        LoginBuilder fullName(String fullName);
        LoginBuilder addThisBeforeClass(String addThisBeforeClass);
        Login build();
    }
}

File : LoginBuilder.java
public class LoginBuilder implements Login.LoginBuilder {
    private String name;
    private String fullName;
    private String addThisBeforeClass;
    @Override
    public String name() {
        return name;
    }
    @Override
    public String fullName() {
        return fullName;
    }
    @Override
    public String addThisBeforeClass() {
        return addThisBeforeClass;
    }
    @Override
    public LoginBuilder name(String name) {
        this.name = name;
        return this;
    }
    @Override
    public LoginBuilder fullName(String fullName) {
        this.fullName = fullName;
        return this;
    }
    @Override
    public LoginBuilder addThisBeforeClass(String addThisBeforeClass) {
        this.addThisBeforeClass = addThisBeforeClass;
        return this;
    }
    @Override
    public Login build() {
        return new LoginImpl(this);
    }
    public LoginBuilder() {
    }
    public final class LoginImpl implements Login {
        private List<AugmentedInfo> augmentedInfoList = new ArrayList<>();
        private String name;
        private String fullName;
        private String addThisBeforeClass;
        @Override
        public String name() {
            return name;
        }
        @Override
        public String fullName() {
            return fullName;
        }
        @Override
        public String addThisBeforeClass() {
            return addThisBeforeClass;
        }
        @Override
        public int hashCode() {
            return Objects.hash(name, fullName, addThisBeforeClass);
        }
        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj instanceof LoginImpl) {
                LoginImpl other = (LoginImpl) obj;
                return
                     Objects.equals(name, other.name) &&
                     Objects.equals(fullName, other.fullName) &&
                     Objects.equals(addThisBeforeClass, other.addThisBeforeClass);
            }
            return false;
        }
        @Override
        public String toString() {
            return MoreObjects.toStringHelper(getClass())
                .add("name", name)
                .add("fullName", fullName)
                .add("addThisBeforeClass", addThisBeforeClass)
                .toString();
        }
        public LoginImpl(LoginBuilder builderObject) {
            this.name = builderObject.name();
            this.fullName = builderObject.fullName();
            this.addThisBeforeClass = builderObject.addThisBeforeClass();
        }
        @Override
        public void addAugmentation(AugmentedInfo value) {
            getAugmentedInfoList().add(value);
        }
        @Override
        public List<AugmentedInfo> getAugmentedInfoList() {
            return augmentedInfoList;
        }
        @Override
        public void removeAugmentation() {
            getAugmentedInfoList().clear();
        }
    }
}

Generated java files for list's holder(another list):

File : Login.java
public interface Login extends AugmentationHolder  {
    String name();
List<org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem.login.Login> login();
    interface LoginBuilder {
        String name();
List<org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem.login.Login> login();
        LoginBuilder name(String name);
        LoginBuilder login(List<org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem
                .login
                .Login> login);
        Login build();
    }
}

File : LoginBuilder.java
public class LoginBuilder implements Login.LoginBuilder {
    private String name;
    private List<org.onosproject.yang.gen.v1.http.acme.example.com.system.rev20070609.acmesystem.login.Login> login;
    @Override
    public String name() {
        return name;
    }
    @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) {
        this.name = name;
        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;
    }
    .
    .
    .
    public final class LoginImpl implements Login {
    .
    .
    .
    }
}

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 nodes under grouping are completely copied, wherever uses is present. Later the java file generation takes place according to the new yang nodes added. Grouping and uses itself will not have any impact in java file generation.

Example
Input YANG file
File : Test.yang
module Test {
         .
         .
         .
    grouping Percentage {
    leaf mark{
            type String;
        }
    }
    container classroom {
        leaf student{
            type String;
        }
        uses Percentage;
    }
}

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

  1. Interface file which extends choice marker interface

  2. Builder class which implements the builder interface and impl class which implements the interface

  3. Impl class includes overridden methods, hashcode, equals, toString methods.
Example
Input YANG file
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; }
            }
        }
     }
}
Generated Java files
File : InterfaceType.java
package org.onosproject.yang.gen.v1.http.huawei.com.rev20160509.choicecasetest.link1;

import org.onosproject.yangutils.translator.tojava.AugmentationHolder;

public interface InterfaceType extends AugmentationHolder  {
}

File : EthernerType.java
package org.onosproject.yang.gen.v1.http.huawei.com.rev20160509.choicecasetest.link1.interfacetype;

import org.onosproject.yang.gen.v1.http.huawei.com.rev20160509.choicecasetest.link1.InterfaceType;
import org.onosproject.yangutils.translator.tojava.AugmentationHolder;

public interface EthernerType extends AugmentationHolder, InterfaceType  {

    String ethernet();

    interface EthernerTypeBuilder {

        String ethernet();

        EthernerTypeBuilder ethernet(String ethernet);

        EthernerType build();
    }
}

File : EthernerTypeBuilder.java
package org.onosproject.yang.gen.v1.http.huawei.com.rev20160509.choicecasetest.link1.interfacetype;

import com.google.common.base.MoreObjects;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.onosproject.yangutils.translator.tojava.AugmentedInfo;

public class EthernerTypeBuilder implements EthernerType.EthernerTypeBuilder {

    private String ethernet;

    @Override
    public String ethernet() {
        return ethernet;
    }

    @Override
    public EthernerTypeBuilder ethernet(String ethernet) {
        this.ethernet = ethernet;
        return this;
    }

   @Override
   public EthernerType build() {
       return new EthernerTypeImpl(this);
   }

   public EthernerTypeBuilder() {
   }

   public final class EthernerTypeImpl implements EthernerType {

        private String ethernet;

        @Override
        public String ethernet() {
            return ethernet;
        }

        public EthernerTypeImpl() {
        }

        public EthernerTypeImpl(EthernerTypeBuilder builderObject) {
                this.ethernet = builderObject.ethernet();
        }
    }
}

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. There can be following java mapping for different combinations of input output statement,

  1. When input is present and no output statement.
     

    1. When input has only one leaf/leaf-list. In this case method signature will have return type as “void” and member attribute with type of leaf.

    2. When input has only one YANG construct. In this case method signature will have return type as “void” and a class will be generated for construct which will be used as the type of method’s attribute..

    3. When input has multiple leaf/leaf-list/YANG construct, one class will be generated for input and that will be used as type of method’s attribute and return type will be void.

  2. When no input  and  output statement is present.
     

    1. When output has only one leaf/leaf-list. In this case method signature will have return type as type of leaf and no member attribute.

    2. When output has only one YANG construct. In this case method signature will have return type as class which is generated for construct and no method  attribute will be generated.

    3. When output has multiple leaf/leaf-list/YANG construct, one class will be generated for output and that will be used as type of method’s return type.
  3. When input is present and  output statement is present.
     
    1. When input has only one leaf/leaf-list and output has only leaf/leaf-list. In this case method signature will have return type as type of leaf/list of output and member attribute with type of leaf/leaf-lists type input.

    2. When input has only one YANG construct and output has one YANG construct. In this case method signature will have return type as generated class of outputs construct and a class will be generated for inputs construct which will be used as the type of method’s attribute.

    3. When input has multiple leaf/leaf-list/YANG construct, and output has leaf/leaf-list/YANG construct one class will be generated for input and that will be used as type of method’s attribute and class will be generated for output which will be used as return type of method.
Example
Input YANG file
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;
            }
          }
    }
}
Generated Java files
File : SfcService.java

package org.onosproject.yang.gen.v1.http.huawei.com.rev20160526;

import org.onosproject.yang.gen.v1.http.huawei.com.rev20160526.sfc.sfp.SfpInput;
import org.onosproject.yang.gen.v1.http.huawei.com.rev20160526.sfc.sfp.SfpOutput;

public interface SfcService {
    SfpOutput sfp(SfpInput inputVar);
}
File : SfcManager.java
package org.onosproject.yang.gen.v1.http.huawei.com.rev20160526;

import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Service;
import org.onosproject.yang.gen.v1.http.huawei.com.rev20160526.sfc.sfp.SfpInput;
import org.onosproject.yang.gen.v1.http.huawei.com.rev20160526.sfc.sfp.SfpOutput;
import org.slf4j.Logger;
import static org.slf4j.LoggerFactory.getLogger;

@Component (immediate = true)
@Service
public class SfcManager implements SfcService {

    private final Logger log = getLogger(getClass());

    @Activate
    public void activate() {
        //TODO: YANG utils generated code
        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        //TODO: YANG utils generated code
        log.info("Stopped");
     }

     @Override
     public SfpOutput sfp(SfpInput inputVar) {
        //TODO: YANG utils generated code
        return null;
     }
}

File : SfpInput.java
package org.onosproject.yang.gen.v1.http.huawei.com.rev20160526.sfc.sfp;

public interface SfpInput {

    String port();

    interface SfpInputBuilder {

        String port();

        SfpInputBuilder port(String port);

        SfpInput build();
    }
}
File : SfpinputBuilder.java
package org.onosproject.yang.gen.v1.http.huawei.com.rev20160526.sfc.sfp;

import com.google.common.base.MoreObjects;
import java.util.Objects;

public class SfpInputBuilder implements SfpInput.SfpInputBuilder {

     private String port;

    @Override
    public String port() {
        return port;
    }

    @Override
    public SfpInputBuilder port(String port) {
         this.port = port;
         return this;
    }

    @Override
    public SfpInput build() {
         return new SfpInputImpl(this);
    }

    public SfpInputBuilder() {
    }

    public final class SfpInputImpl implements SfpInput {

         private String port;

        @Override
        public String port() {
            return port;
        }

        @Override
        public int hashCode() {
            return Objects.hash(port);
        }

        @Override
        public boolean equals(Object obj) {
             if (this == obj) {
                 return true;
             }
            if (obj instanceof SfpInputImpl) {
                SfpInputImpl other = (SfpInputImpl) obj;
                return
                     Objects.equals(port, other.port);
            }
            return false;
         }

        @Override
        public String toString() {
                return MoreObjects.toStringHelper(getClass())
                   .add("port", port)
                   .toString();
        }

        public SfpInputImpl(SfpInputBuilder builderObject) {
                 this.port = builderObject.port();
        }
    }
}
File : Sfpoutput.java
package org.onosproject.yang.gen.v1.http.huawei.com.rev20160526.sfc.sfp;

public interface SfpOutput {

    String path();

    interface SfpOutputBuilder {

        String path();

        SfpOutputBuilder path(String path);

        SfpOutput build();
     }
}
File : SfpOutputBuilder.java

package org.onosproject.yang.gen.v1.http.huawei.com.rev20160526.sfc.sfp;

import com.google.common.base.MoreObjects;
import java.util.Objects;
public class SfpOutputBuilder implements SfpOutput.SfpOutputBuilder {

     private String path;

    @Override
    public String path() {
         return path;
    }

    @Override
    public SfpOutputBuilder path(String path) {
         this.path = path;
         return this;
    }

    @Override
    public SfpOutput build() {
         return new SfpOutputImpl(this);
    }

    public SfpOutputBuilder() {
    }

    public final class SfpOutputImpl implements SfpOutput {

         private String path;

         @Override
         public String path() {
            return path;
         }

         @Override
         public int hashCode() {
            return Objects.hash(path);
         }

         @Override
         public boolean equals(Object obj) {
            if (this == obj) {
                     return true;
            }
            if (obj instanceof SfpOutputImpl) {
                     SfpOutputImpl other = (SfpOutputImpl) obj;
                     return Objects.equals(path, other.path);
            }
            return false;
         }

          @Override
         public String toString() {
            return MoreObjects.toStringHelper(getClass())
                .add("path", path)
                .toString();
         }

         public SfpOutputImpl(SfpOutputBuilder builderObject) {
            this.path = builderObject.path();
         }
     }
}

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, 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.

Event Subject class will have all the objects of events for multiple notifications and getters and setters for the events.

Event Listener is interface which extends EventListener.

Manager Extends ListenerRegistry with event and eventListener.

Example
Input YANG files
File : ospf.yang
module ospf {
    namespace "http://example.com/ospf";
    prefix "ospf";

    notification test {
           leaf event-class {
              type string;
           }
           leaf severity {
              type string;
           }
    }
}
Generated Java files
File : OspfManager.java
package org.onosproject.yang.gen.v1.http.example.com.ospf.rev20160519;

import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Service;
import org.onosproject.event.ListenerRegistry;
import org.onosproject.yang.gen.v1.http.example.com.ospf.rev20160519.ospf.OspfEvent;
import org.onosproject.yang.gen.v1.http.example.com.ospf.rev20160519.ospf.OspfListener;
import org.slf4j.Logger;
import static org.slf4j.LoggerFactory.getLogger;

@Component (immediate = true)
@Service
public class OspfManager
        extends ListenerRegistry<OspfEvent, OspfListener>
        implements OspfService {

    private final Logger log = getLogger(getClass());

    @Activate
    public void activate() {
        //TODO: YANG utils generated code
        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        //TODO: YANG utils generated code
        log.info("Stopped");
    }
}

File : OspfService.java
package org.onosproject.yang.gen.v1.http.example.com.ospf.rev20160519;

import org.onosproject.event.ListenerService;
import org.onosproject.yang.gen.v1.http.example.com.ospf.rev20160519.ospf.OspfEvent;
import org.onosproject.yang.gen.v1.http.example.com.ospf.rev20160519.ospf.OspfListener;

public interface OspfService
        extends ListenerService<OspfEvent, OspfListener> {
}

File : OspfEvent.java
package org.onosproject.yang.gen.v1.http.example.com.ospf.rev20160527.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.rev20160519.ospf;

public class OspfEventSubject {

    private Test test;

    public Test test() {
        return test;
    }

    public void test(Test test) {
        this.test = test;
    }
}

File : OspfListener.java

package org.onosproject.yang.gen.v1.http.example.com.ospf.rev20160519.ospf;

import org.onosproject.event.EventListener;

public interface OspfListener extends EventListener<OspfEvent> {
}

File : Test.java

package org.onosproject.yang.gen.v1.http.example.com.ospf.rev20160519.ospf;

import org.onosproject.yangutils.translator.tojava.AugmentationHolder;

public interface Test extends AugmentationHolder  {

    String eventClass();

    String severity();

    interface TestBuilder {

         String eventClass();

         String severity();

         TestBuilder eventClass(String eventClass);

         TestBuilder severity(String severity);

         Test build();
    }
}

File : TestBuilder.java
package org.onosproject.yang.gen.v1.http.example.com.ospf.rev20160519.ospf;

import com.google.common.base.MoreObjects;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.onosproject.yangutils.translator.tojava.AugmentedInfo;

public class TestBuilder implements Test.TestBuilder {

    private String eventClass;
    private String severity;

    @Override
    public String eventClass() {
        return eventClass;
    }

    @Override
    public String severity() {
        return severity;
    }

    @Override
    public TestBuilder eventClass(String eventClass) {
        this.eventClass = eventClass;
        return this;
    }

    @Override
    public TestBuilder severity(String severity) {
        this.severity = severity;
        return this;
    }

    @Override
    public Test build() {
        return new TestImpl(this);
    }

    public TestBuilder() {
    }

    public final class TestImpl implements Test {

        private List<AugmentedInfo> augmentedInfoList = new ArrayList<>();
        private String eventClass;
        private String severity;

        @Override
        public String eventClass() {
            return eventClass;
        }

        @Override
        public String severity() {
            return severity;
        }

        @Override
        public int hashCode() {
            return Objects.hash(eventClass, severity);
        }

        @Override
        public boolean equals(Object obj) {
           if (this == obj) {
               return true;
            }
            if (obj instanceof TestImpl) {
                TestImpl other = (TestImpl) obj;
                return Objects.equals(eventClass, other.eventClass) &&
                       Objects.equals(severity, other.severity);
            }
            return false;
        }

        @Override
        public String toString() {
            return MoreObjects.toStringHelper(getClass())
                    .add("eventClass", eventClass)
                    .add("severity", severity)
                    .toString();
        }

        public TestImpl(TestBuilder builderObject) {
            this.eventClass = builderObject.eventClass();
            this.severity = builderObject.severity();
        }

        @Override
        public void addAugmentation(AugmentedInfo value) {
            getAugmentedInfoList().add(value);
        }

        @Override
        public List<AugmentedInfo> getAugmentedInfoList() {
            return augmentedInfoList;
        }

        @Override
        public void removeAugmentation() {
            getAugmentedInfoList().clear();
        }
    }
}

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.

Note : 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 two interface named as “AugmentationHolder” and “AugmentedInfo” as part of yangutils 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, will be implementing AugmentationHolder class. We have given 3 api in AugmentationHolder class, which are :

addAugmentation(AugmentedInfo augmentedInfo);

removeAugmentation();

getAugmentation();

these apis will be providing augmentation functionalities for augmented nodes. These class will be keeping a list of augmentedInfo , which is nothing but a list of augment nodes which are augmenting this node.

Example
Input YANG file
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 "/Test/interface" {
          leaf ds0ChannelNumber {
               type int16;
         }
    }
}
Generated Java files
File : AugmentedInterface.java


package org.onosproject.yang.gen.v1.http.huawei.com.rev20160428.test;
import org.onosproject.yangutils.utils.AugmentedInfo;

public interface AugmentedInterface extends AugmentedInfo  {
   
    short getDs0ChannelNumber();
   
    interface AugmentedInterfaceBuilder {
 
        short getDs0ChannelNumber();

        AgmentedInterfaceBuilder setDs0ChannelNumber(short ds0ChannelNumber);

       AugmentedInterface build();
    }
}

File : AugmentedInterfaceBuilder.java
package org.onosproject.yang.gen.v1.http.huawei.com.rev20160428.test;
import java.util.Objects;
import com.google.common.base.MoreObjects;
import org.onosproject.yang.gen.v1.http.huawei.com.rev20160428.test.InterfaceBuilder.InterfaceImpl;

public class AugmentedInterfaceBuilder implements AugmentedInterface.AugmentedInterfaceBuilder {
   private short ds0ChannelNumber;

   @Override
   public short getDs0ChannelNumber() {
       return ds0ChannelNumber;
   }

   @Override
   public AugmentedInterfaceBuilder setDs0ChannelNumber(short ds0ChannelNumber)  {
       this.ds0ChannelNumber = ds0ChannelNumber;
       return this;
   }

   @Override
   public AugmentedInterface build() {
       return new AugmentedInterfaceImpl(this);
   }

   public AugmentedInterfaceBuilder() {
   }

   public final class AugmentedInterfaceImpl implements AugmentedInterface {

       private short ds0ChannelNumber;

       @Override
       public short getDs0ChannelNumber() {
           return ds0ChannelNumber;
       }

       @Override
       Public int hashCode() {
           return Objects.hash(ds0ChannelNumber);
       }

       @Override
       public boolean equals(Object obj) {
           if (this == obj) {
               return true;
           }

           if (obj instanceof AugmentedInterfaceImpl) {
               AugmentedInterfaceImpl other = (AugmentedInterfaceImpl) obj;
               return
                      Objects.equals(ds0ChannelNumber, other.ds0ChannelNumber);
           }
           return false;
       }

       @Override
       public String toString() {
           return MoreObjects.toStringHelper(getClass())
               .add("ds0ChannelNumber", ds0ChannelNumber)
               .toString();
       }

       Public AugmentedInterfaceImpl(AugmentedInterfaceBuilder builderObject) {
           this.ds0ChannelNumber = builderObject.getDs0ChannelNumber();
          InterfaceImpl interfaceImpl = new InterfaceBuilder().new InterfaceImpl();
          interfaceImpl.addAugmentation(this);
       }
   }
}

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

To be implemented

bits

A set of bits or flags

To be implemented

boolean

"True" or "false"

boolean

decimal64

64-bit    signed decimal number

To be implemented

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

To be implemented

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

To be implemented

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
Input YANG file
leaf one {                         
    type string;
}

leaf two {                           
    type int32;
}

leaf-list three {
    type boolean;
}

leaf-list four {            
    type int16;
}
Generated Java file
private String one;

private int two;

private List<Boolean> three;

private List<Short> four;

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
Input YANG file
File : test.yang

module test {

    yang-version 1;
    namespace "http://huawei.com";
    prefix "test";

    typedef percent {
        type uint8;
           description "Percentage";
    }

    leaf completed {
        type percent;
    }
}
Generated Java file
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
Input YANG file
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;
         }         
       }
}
Generated Java files
File : PacketTypeEnum.java

package org.onosproject.yang.gen.v1.http.huawei.com.rev20160526.test;

public enum PacketTypeEnum {

    UNBOUNDED(0),

    ZERO(1),

    TWO(2),

    FOUR(3);

    private int packetTypeEnum;

    PacketTypeEnum(int value) {
        packetTypeEnum = value;
    }

    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 int packetTypeEnum() {
            return packetTypeEnum;
    }

    public static PacketTypeEnum fromString(String valInString) {
            try {
                int tmpVal = Integer.parseInt(valInString);
                return of(tmpVal);
            } catch (Exception e) {
        }
        return null;
    }
}

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
Input YANG file
File : test.yang
module test {
    yang-version 1;
    namespace "http://huawei.com";
    prefix "test";

    typedef ip-address {
        type union {
            type int32;
            type uint32;
        }
    }
}
Generated java files
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;
   }
}
Generated Java files
File : FlowClassifierService.java
package org.onosproject.yang.gen.v1.sfc.flowclassifier.rev20160524;

import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev20100924.ietfyangtypes.Uuid;

public interface FlowClassifierService {

    Uuid getId();

    void setId(Uuid id);
}

File : FlowClassifierManager.java
package org.onosproject.yang.gen.v1.sfc.flowclassifier.rev20160524;

import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Service;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev20100924.ietfyangtypes.Uuid;
import org.slf4j.Logger;
import static org.slf4j.LoggerFactory.getLogger;

@Component (immediate = true)
@Service
public class FlowClassifierManager implements FlowClassifierService {

    private final Logger log = getLogger(getClass());

    @Activate
    public void activate() {
        //TODO: YANG utils generated code
        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        //TODO: YANG utils generated code
        log.info("Stopped");
    }

    @Override
    public Uuid getId() {
        //TODO: YANG utils generated code
        return null;
    }

    @Override
    public void setId(Uuid id) {
        //TODO: YANG utils generated code
    }

}

File : IetfYangTypesService.java
package org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev20100924;

public interface IetfYangTypesService {
}

File : IetfYangTypesManager.java
package org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev20100924;

import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Service;
import org.slf4j.Logger;
import static org.slf4j.LoggerFactory.getLogger;

@Component (immediate = true)
@Service
public class IetfYangTypesManager implements IetfYangTypesService {

    private final Logger log = getLogger(getClass());

    @Activate
    public void activate() {
        //TODO: YANG utils generated code
        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        //TODO: YANG utils generated code
        log.info("Stopped");
    }
}

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;
    }
}
  • No labels