Jump to: navigation, search

YANG Tools:YANG to Java Mapping

YANG to JAVA mapping

Package name

The package name consists from following parts:

  • opendaylight prefix - every package name starts with prefix org.opendaylight.yang.gen.v1 which is hardcoded in BindingGeneratorUtil.moduleNamespaceToPackageName().
  • YANG version - is specified through module substatement yang-version
  • namespace - equals to value of module subelement namespace argument value. The namespace characters : / : - @ $ # ' * + , ; = and character group:/) are replaced with periods (.).
  • revision - concatenation of word rev and value of module subelement revision argument value without leading zeros before month and day (e.g. rev201379)

After the package name is generated then it is checked if it contains any JAVA key words or digits. If it is so then before this tokens is adden underscore (_). List of key words which are prefixed with underscore:

abstract, assert, boolean, break, byte, case, catch, char, class, const, continue, default, double, do, else, enum, extends, false, final, finally, float, for, goto, if, implements, import, instanceof, int, interface, long, native, new, null, package, private, protected, public, return, short, static, strictfp, super, switch, synchronized, this, throw, throws, transient, true, try, void, volatile, while

As an example suppose following yang model:

module module {
 
    namespace <font color="blue">"urn:2:case#module"</font color>
    prefix "sbd";
 
    organization "OPEN DAYLIGHT";
    contact "http://www.whatever.com/";
 
    revision <font color="violet">2013-07-09</font color> {        
    }
}

Package name will be org.opendaylight.yang.gen.v1.urn:2:case#module.rev201379
and after replacing digits and JAVA keywords
org.opendaylight.yang.gen.v1.urn._2._case.module.rev201379

Other package names

In some cases there are generated also additional packages. It happens in cases where the superior YANG elements contain specific subordinate YANG elements (see table below).

Superior element Subordinate element
list list, container, choice
container list, container, choice
choice leaf, list, leaf-list, container, case
case list, container, choice
rpc.input

rpc.output

list, container, (choice isn't supported)
notification list, container, (choice isn't supported)
augment list, container, choice, case

In this case the subordinate elements aren't mapped only to JAVA getter methods in the interface of superior element but there are also generated packages which names consist of superior element package name + superior element name.
In example YANG model suppose that container element cont is direct subelement of module

container cont {
  container cont-inner {
  }
  list outter-list {
    list list-in-list {
    }
  }
}
Container cont is the superior element for the subordinate elements cont-inner and outter-list.

JAVA code will be generated in following structure:

  • org.opendaylight.yang.gen.v1.urn.module.rev201379 - package contains element which are subordinate of module
    • Cont.java
  • org.opendaylight.yang.gen.v1.urn.module.rev201379.cont - package contains subordinate elements of cont container element
    • ContInner.java
    • OutterList.java


container cont {
  container cont-inner {
  }
  list outter-list {
    list list-in-list {
    }
  }
}

list outter-list is superior element for subordinate element list-in-list

JAVA code will be generated in following structure:

  • org.opendaylight.yang.gen.v1.urn.module.rev201379.cont.outter.list - package contains subordinate elements of outter-list list element
    • ListInList.java

Class and interface name

Some YANG elements are mapped to JAVA classes and interfaces. The name of YANG element may contain various characters which aren't permitted in JAVA class names. Firstly whitespaces are trimmed from YANG name. Next characters space, -, _ are deleted and subsequent letter is capitalized. At the end first letter is capitalized. Transformation example:
example-name without_capitalization
is mapped to
ExampleNameWithoutCapitalization

Getters and setters name

In some cases are YANG elements generated as getter or setter methods. This methods are created through class MethodSignatureBuilder
The process for getter is:

  • name of YANG element is converted to JAVA class name style
  • the word get is added as preffix
  • return type of the getter method is set to element's type substatement value


The process for setter is:

  • name of YANG element is converted to JAVA class name style
  • word set is added as preffix
  • input parameter name is set to element's name converted to JAVA parameter style
  • return parameter is set to void

Module

YANG module is converted to JAVA as two JAVA classes. Each of the class is in the separate JAVA file. The names of JAVA files are composed as follows:
<YANG_module_name><Sufix>.java where <sufix> can be Data or Service.

YANG JAVA
module module {
 
    namespace "urn:module";
    prefix "sbd";
 
    organization "OPEN DAYLIGHT";
    contact "http://www.whatever.com/";    
 
    revision 2013-07-09 {
    }
}

ModuleData.java

package org.opendaylight.yang.gen.v1.urn.module.rev201379;
public interface ModuleData {
}

ModuleService.java

package org.opendaylight.yang.gen.v1.urn.module.rev201379;
public interface ModuleService {
}

Data Interface

Data Interface has a mapping similar to container, but contains only top level nodes defined in module.

Service Interface

Service Interface serves to describe RPC contract defined in the module. This RPC contract is defined by rpc statements.

Typedef

YANG typedef statement is mapped to JAVA class. Typedef may contain following substatement:

Substatement How si argument mapped to JAVA
type is mapped as class attribute
descripton isn't mapped
units isn't mapped
default isn't mapped

Type's valid arguments

Simple values of type argument are mapped as follows:

Type's argument Mapped to JAVA
boolean Boolean
empty Boolean
int8 Byte
int16 Short
int32 Integer
int64 Long
string
decimal64 Double
uint8 Short
uint16 Integer
uint32 Long
uint64 BigInteger
binary byte[]


Complex values of type argument are mapped as follows:

Type's argument Mapped to JAVA
enumeration enum
bits class
leafref  ??
identityref  ??
union class
instance-identifier  ??


Enumeration's substatement enum

The YANG enumeration type has to contain some enum substatements. Enumeration is mapped as JAVA enum type (standalone class) and every YANG enum subelement is mapped to JAVA enum's predefined values.
Enum substatement can have following substatements:

Enum's substatement mapping to JAVA
description isn't mapped
value mapped as input parameter for every predefined value of enum

Example of maping of YANG enumeration to JAVA

YANG JAVA
typedef typedef-enumeration {
    type enumeration {
        enum enum1 {
            description "enum1 description";
            value 18;
        }
        enum enum2 {
            value 16;
        }
        enum enum3 {
        }    		
    }
}
public enum TypedefEnumeration {
    Enum1(18),
    Enum2(16),
    Enum3(19);
 
    int value;
 
    private TypedefEnumeration(int value) {
        this.value = value;
    }
}

Bits's substatement bit

The YANG bits type has to contain some bit substatements. YANG Bits is mapped to JAVA class (standalone class) and every YANG bits subelement is mapped to class boolean attributes. In addition are overriden Object methods hash, toString, equals.

YANG JAVA JAVA overriden Object methods
typedef typedef-bits {
  type bits {
    bit first-bit {
      description "first-bit description";
        position 15;
      }
    bit second-bit; 
  }
}
public class TypedefBits {
 
    private Boolean firstBit;
    private Boolean secondBit;
 
    public TypedefBits() {
        super();
    }
 
    public Boolean getFirstBit() {
        return firstBit;
    }
 
    public void setFirstBit(Boolean firstBit) {
        this.firstBit = firstBit;
    }
 
    public Boolean getSecondBit() {
        return secondBit;
    }
 
    public void setSecondBit(Boolean secondBit) {
        this.secondBit = secondBit;
    }
}
@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result +
     ((firstBit == null) ? 0 : firstBit.hashCode());
    result = prime * result +
     ((secondBit == null) ? 0 : secondBit.hashCode());
    return result;
}
 
@Override
public boolean equals(Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj == null) {
        return false;
    }
    if (getClass() != obj.getClass()) {
        return false;
    }
    TypedefBits other = (TypedefBits) obj;
    if (firstBit == null) {
        if (other.firstBit != null) {
            return false;
        }
    } else if(!firstBit.equals(other.firstBit)) {
        return false;
    }
    if (secondBit == null) {
        if (other.secondBit != null) {
            return false;
        }
    } else if(!secondBit.equals(other.secondBit)) {
        return false;
    }
    return true;
}
 
@Override
public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append("TypedefBits [firstBit=");
    builder.append(firstBit);
    builder.append(", secondBit=");
    builder.append(secondBit);
    builder.append("]");
    return builder.toString();
}

Union's substatement type

If type of typedef is union it has to contain type substatements. Union typedef is mapped to class and its type subelements are mapped to private class attributes. For every YANG union subtype si generated own JAVA constructor with a parameter which represent just one attribute.
Example to union mapping:

YANG JAVA JAVA overriden Object methods
typedef typedef-union {
    type union {
        type int32;
        type string;
    }
}
public class TypedefUnion {
 
 
 
    private Integer int32;
    private String string;
 
    public TypedefUnion(Integer int32) {
        super();
        this.int32 = int32;
    }
 
    public TypedefUnion(String string) {
        super();
        this.string = string;
    }
 
    public Integer getInt32() {
        return int32;
    }
 
    public String getString() {
        return string;
    }
}
@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((int32 == null) ? 0 : int32.hashCode());
    result = prime * result + ((string == null) ? 0 : string.hashCode());
    return result;
}
 
@Override
public boolean equals(Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj == null) {
        return false;
    }
    if (getClass() != obj.getClass()) {
        return false;
    }
    TypedefUnion other = (TypedefUnion) obj;
    if (int32 == null) {
        if (other.int32 != null) {
            return false;
        }
    } else if(!int32.equals(other.int32)) {
        return false;
    }
    if (string == null) {
        if (other.string != null) {
            return false;
        }
    } else if(!string.equals(other.string)) {
        return false;
    }
    return true;
}
 
@Override
public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append("TypedefUnion [int32=");
    builder.append(int32);
    builder.append(", string=");
    builder.append(string);
    builder.append("]");
    return builder.toString();
}

String mapping

YANG String can be detailed specified through type's subelements length and pattern which are mapped as follows:

Type's subelement Mapping to JAVA
length isn't mapped
pattern
  • list of string constants = list of patterns
  • list of Pattern objects
  • static initialization block where list of Patterns is initialized from list of string of constants

Example of YANG string mapping

YANG JAVA JAVA overriden Object methods
typedef typedef-string {
    type string {
        length 44;
        pattern "[a][.]*"
    }
}
public class TypedefString {
 
    private static final List<Pattern> patterns = new ArrayList<Pattern>();
    public static final List<String> PATTERN_CONSTANTS = Arrays.asList("[a][.]*");
 
    static {
        for (String regEx : PATTERN_CONSTANTS) {
            patterns.add(Pattern.compile(regEx));
        }
    }
 
    private String typedefString;
 
    public TypedefString(String typedefString) {
        super();
        this.typedefString = typedefString;
    }
 
    public String getTypedefString() {
        return typedefString;
    }
}
 
@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((typedefString == null) ? 0 : typedefString.hashCode());
    return result;
}
 
@Override
public boolean equals(Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj == null) {
        return false;
    }
    if (getClass() != obj.getClass()) {
        return false;
    }
    TypedefString other = (TypedefString) obj;
    if (typedefString == null) {
        if (other.typedefString != null) {
            return false;
        }
    } else if(!typedefString.equals(other.typedefString)) {
        return false;
    }
    return true;
}
 
@Override
public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append("TypedefString [typedefString=");
    builder.append(typedefString);
    builder.append("]");
    return builder.toString();
}


Container

YANG Container is mapped to JAVA interface which extends interfaces DataObject, Augmentable<container_interface>, where container_interface is name of mapped interface.
Example of mapping:

YANG JAVA
container cont {
}
public interface Cont extends DataObject, Augmentable<Cont> {
}

Leaf

Each leaf has to contain at least one type substatement. The leaf is mapped to getter method of superior element with return type equal to type substatement value.
Example of leaf mapping at model level:

YANG JAVA
module module {
 
    namespace "urn:module";
    prefix "sbd";
 
    organization "OPEN DAYLIGHT";
    contact "http://www.whatever.com/";    
 
    revision 2013-07-09 {
 
    }
    leaf lf {
        type string;				
    }     
}
package org.opendaylight.yang.gen.v1.urn.module.rev201379;
public interface ModuleData {
    String getLf();
}

Example of leaf mapping at container level:

YANG JAVA
container cont {
  leaf lf {
    type string;				
  }
}
public interface Cont extends DataObject, Augmentable<Cont> {
    String getLf();
}

Leaf-list

Each leaf-list has to contain one type substatement. The leaf-list is mapped to getter method of superior element with return type equal to List of type substatement value.
Example of mapping of leaf-list.

YANG JAVA
container cont {
    leaf-list lf-lst {
        type typedef-union;
    }
}
public interface Cont extends DataObject, Augmentable<Cont> {
    List<TypedefUnion> getLfLst();
}

YANG typedef-union and JAVA TypedefUnion are the same as in union type.

List

YANG list element is mapped to JAVA interface. In superior element is generated as getter method with return type List of generated interfaces.
Mapping of list substatement to JAVA:

Substatement Mapping to JAVA
key class

Example of list mapping. outter-list is mapped to JAVA interface OutterList and in Cont interface (superior of OutterList) contains getter method with return type List<OutterList>

YANG JAVA JAVA overriden Object methods
container cont {
  list outter-list {
    leaf leaf-in-list {
      type uint64;                
    }
    leaf-list leaf-list-in-list {
      type string;                
    }
    list list-in-list {
      leaf-list inner-leaf-list {
        type int16;
      }
    }
  }
}

ListInList.java

package org.opendaylight.yang.gen.v1.urn.module.rev201379.cont.outter.list;
 
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.Augmentable;
import java.util.List;
 
public interface ListInList extends DataObject, Augmentable<ListInList> {
 
    List<Short> getInnerLeafList();
}

OutterListKey.java

package org.opendaylight.yang.gen.v1.urn.module.rev201379.cont;
 
import org.opendaylight.yang.gen.v1.urn.module.rev201379.cont.OutterListKey;
import java.math.BigInteger;
 
public class OutterListKey {
 
    private BigInteger LeafInList;
 
    public OutterListKey(BigInteger LeafInList) {
        super();
        this.LeafInList = LeafInList;
    }
 
    public BigInteger getLeafInList() {
        return LeafInList;
    }
}

OutterList.java

package org.opendaylight.yang.gen.v1.urn.module.rev201379.cont;
 
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.Augmentable;
import java.util.List;
import org.opendaylight.yang.gen.v1.urn.module.rev201379.cont.outter.list.ListInList;
 
public interface OutterList extends DataObject, Augmentable<OutterList> {
 
    List<String> getLeafListInList();
 
    List<ListInList> getListInList();
 
    /*
    Returns Primary Key of Yang List Type
    */
    OutterListKey getOutterListKey();
 
}

Cont.java

package org.opendaylight.yang.gen.v1.urn.module.rev201379;
 
 
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.Augmentable;
import java.util.List;
import org.opendaylight.yang.gen.v1.urn.module.rev201379.cont.OutterList;
 
public interface Cont extends DataObject, Augmentable<Cont> {
 
    List<OutterList> getOutterList();
 
}

for OutterListKey.java

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((LeafInList == null) ? 0 : LeafInList.hashCode());
    return result;
}
 
@Override
public boolean equals(Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj == null) {
        return false;
    }
    if (getClass() != obj.getClass()) {
        return false;
    }
    OutterListKey other = (OutterListKey) obj;
    if (LeafInList == null) {
        if (other.LeafInList != null) {
            return false;
        }
    } else if(!LeafInList.equals(other.LeafInList)) {
        return false;
    }
    return true;
}
 
@Override
public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append("OutterListKey [LeafInList=");
    builder.append(LeafInList);
    builder.append("]");
    return builder.toString();
}

Choice and case

Choice element is mapped similarly as list element. It means that is mapped to interface (marker interface) and in the superior element is created getter method with the return type List of this marker interfaces.
Case substatements are mapped to the JAVA interfaces which extend mentioned marker interface.
Example of choice mapping:

YANG JAVA
container cont {
    choice choice-test {
        case case1 {
        }
        case case2 {
        }
    }
}

Case1.java

package org.opendaylight.yang.gen.v1.urn.module.rev201379.cont.choice.test;
 
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.Augmentable;
import org.opendaylight.yang.gen.v1.urn.module.rev201379.cont.ChoiceTest;
 
public interface Case1 extends DataObject, Augmentable<Case1>, ChoiceTest {
}

Case2.java

package org.opendaylight.yang.gen.v1.urn.module.rev201379.cont.choice.test;
 
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.Augmentable;
import org.opendaylight.yang.gen.v1.urn.module.rev201379.cont.ChoiceTest;
 
public interface Case2 extends DataObject, Augmentable<Case2>, ChoiceTest {
}

ChoiceTest.java

package org.opendaylight.yang.gen.v1.urn.module.rev201379.cont;
 
import org.opendaylight.yangtools.yang.binding.DataObject;
 
public interface ChoiceTest extends DataObject {
}

Cont.java

package org.opendaylight.yang.gen.v1.urn.module.rev201379;
 
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.Augmentable;
import org.opendaylight.yang.gen.v1.urn.module.rev201379.cont.ChoiceTest;
 
public interface Cont extends DataObject, Augmentable<Cont> {
 
    ChoiceTest getChoiceTest();
 
}


Grouping and uses

Grouping is mapped to JAVA interface. Uses used in some element (using of concrete grouping) are mapped as extension of interface for this element with the interface which represents grouping.
Example of grouping and uses mapping.

YANG JAVA
grouping grp {
 
}
 
container cont {
    uses grp;
}

Cont.java

package org.opendaylight.yang.gen.v1.urn.module.rev201379;
 
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.Augmentable;
 
public interface Cont extends DataObject, Augmentable<Cont>, Grp {
}

Grp.java

package org.opendaylight.yang.gen.v1.urn.module.rev201379;
 
import org.opendaylight.yangtools.yang.binding.DataObject;
 
public interface Grp extends DataObject {
}

Rpc

Rpc is mapped to JAVA as method of class ModuleService.java.
Rpc's substatement are mapped as follows:

Rpc substatement mapped to JAVA
input interface
output interface

Example of rpc mapping:

YANG JAVA
rpc rpc-test1 {
    output {
        leaf lf-output {
            type string;
        }
    }
    input {
        leaf lf-input {
            type string;
        }        
    }
}

ModuleService.java

package org.opendaylight.yang.gen.v1.urn.module.rev201379;
 
import java.util.concurrent.Future;
import org.opendaylight.yangtools.yang.common.RpcResult;
 
public interface ModuleService {
 
    Future<RpcResult<RpcTest1Output>> rpcTest1(RpcTest1Input input);
 
}

RpcTest1Input.java

package org.opendaylight.yang.gen.v1.urn.module.rev201379;
 
public interface RpcTest1Input {
 
    String getLfInput();
 
}

RpcTest1Output.java

package org.opendaylight.yang.gen.v1.urn.module.rev201379;
 
public interface RpcTest1Output {
 
    String getLfOutput();
 
}

Notification

Notification is mapped to the JAVA interface which extends Notification interface.
Example of notification mapping:

YANG JAVA
	notification notif {
	}
package org.opendaylight.yang.gen.v1.urn.module.rev201379;
 
 
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.Augmentable;
import org.opendaylight.yangtools.yang.binding.Notification;
 
public interface Notif extends DataObject, Augmentable<Notif>, Notification {
}

Augment

Augment is mapped to the JAVA interface. The interface starts with the same name as the name of augmented interface. The suffix is order number of augmenting interface. The augmenting interface also extends Augmentation<> with actual type parameter equal to augmented interface.
Example of augment mapping. In this example is augmented interface Cont so whole parametrized type is Augmentation<Cont>.

YANG JAVA
container cont {
}         
 
augment "/cont" {
}

Cont.java

package org.opendaylight.yang.gen.v1.urn.module.rev201379;
 
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.Augmentable;
 
public interface Cont extends DataObject, Augmentable<Cont> {
 
}

Cont1.java

package org.opendaylight.yang.gen.v1.urn.module.rev201379;
 
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.Augmentation;
 
public interface Cont1 extends DataObject, Augmentation<Cont> {
 
}

Identity

The purpose of the identity statement is “to define a new globally unique, abstract, and untyped identity “. YANG substatement base „takes as an argument a string that is the name of existing identity, from which the new identity is derived.1“ Therefore the identity statement is mapped to JAVA abstract class and base substatement is mapped as extends JAVA keyword. The identity name is translated to class name.

YANG JAVA
identity toast-type {  
}

ToastType.java

public abstract class ToastType extends BaseIdentity {
    protected ToastType() {
        super();
    }
}
identity white-bread {
  base toast-type;
}

WhiteBread.java

public abstract class WhiteBread extends ToastType {
    protected WhiteBread() {
        super();
    }
}