Revived yangtools developers guide. 69/23169/4
authorTony Tkacik <ttkacik@cisco.com>
Tue, 23 Jun 2015 13:55:33 +0000 (15:55 +0200)
committerColin Dixon <colin@colindixon.com>
Fri, 14 Aug 2015 16:48:47 +0000 (16:48 +0000)
Change-Id: I1cfeb34599bf5988f5d2fd94ada4d65fa39dbb87
Signed-off-by: Tony Tkacik <ttkacik@cisco.com>
manuals/developer-guide/src/main/asciidoc/bk-developers-guide.adoc
manuals/developer-guide/src/main/asciidoc/yangtools/yang-java-binding-explained.adoc [new file with mode: 0644]
manuals/developer-guide/src/main/asciidoc/yangtools/yangtools.adoc [new file with mode: 0644]

index d5f03be0407314582820a00d79ab7aa63f3e9167..69378afa84247a8def23922f1fe29e4b11b6cd34 100644 (file)
@@ -111,6 +111,8 @@ include::usc/odl-usc-channel-dev.adoc[]
 
 include::vtn/vtn-dev.adoc[]
 
+include::yangtools/yangtools.adoc[]
+
 :numbered!:
 
 ///////
diff --git a/manuals/developer-guide/src/main/asciidoc/yangtools/yang-java-binding-explained.adoc b/manuals/developer-guide/src/main/asciidoc/yangtools/yang-java-binding-explained.adoc
new file mode 100644 (file)
index 0000000..f61ba50
--- /dev/null
@@ -0,0 +1,1101 @@
+=== YANG Java Binding: Mapping rules\r
+This chapter covers the details of mapping YANG to Java.\r
+\r
+NOTE: The following source code examples does not show canonical generated\r
+code, but rather illustrative example. Generated classes and interfaces may\r
+differ from this examples, but APIs are preserved.\r
+\r
+==== General conversion rules\r
+\r
+===== Package names of YANG models\r
+\r
+The package name consists of the following parts: +\r
+\r
+* *Opendaylight prefix* - Specifies the opendaylight prefix. Every package name\r
+starts with the prefix `org.opendaylight.yang.gen.v`.\r
+* *Java Binding version* - Specifies the YANG Java Binding version.\r
+  Curent Binding version is `1`.\r
+* *Namespace* - Specified by the value of `namespace` substatement.\r
+   URI is converted to package name structure.\r
+* *Revision* - Specifies the concatenation of word `rev` and value of `module`\r
+  substatements `revision` argument value without leading zeros before month and day.\r
+  For example: `rev201379`\r
+\r
+After the package name is generated, we check if it contains any Java keywords\r
+or starts with a digit. If so, then we add an underscore before the offending\r
+token.\r
+\r
+The following is a list of keywords which are prefixed with underscore:\r
+\r
+abstract, assert, boolean, break, byte, case, catch, char, class, const,\r
+continue, default, double, do, else, enum, extends, false, final, finally,\r
+float, for, goto, if, implements, import, instanceof, int, interface, long,\r
+native, new, null, package, private, protected, public, return, short, static,\r
+strictfp, super, switch, synchronized, this, throw, throws, transient, true, try,\r
+void, volatile, while\r
+\r
+As an example suppose following yang model:\r
+\r
+[source, yang]\r
+----\r
+module module {\r
+    namespace "urn:2:case#module";\r
+    prefix "sbd";\r
+    organization "OPEN DAYLIGHT";\r
+    contact "http://www.example.com/";\r
+    revision 2013-07-09 {\r
+    }\r
+}\r
+----\r
+\r
+After applying rules (replacing digits and Java keywords) the resulting\r
+package name is `org.opendaylight.yang.gen.v1.urn._2._case.module.rev201379`\r
+\r
+===== Additional Packages\r
+\r
+In cases when YANG statement contain some of specific YANG\r
+statements additional packages are generated to designate this containment.\r
+Table below provides details of parent statement and nested statements, which\r
+yields additional package generation:\r
+\r
+[options="header"]\r
+|===\r
+|Parent statement  | Substatement\r
+|`list`  |list, container, choice\r
+|`container` | list, container, choice\r
+|`choice` | leaf, list, leaf-list, container, case\r
+|`case`  | list, container, choice\r
+|rpc `input` or `output` |  list, container, (choice isn't supported)\r
+|`notification` |  list, container, (choice isn't supported)\r
+|`augment`  | list, container, choice, case |\r
+|===\r
+\r
+Substatements are not only mapped to Java setter methods in the interface\r
+representing the parent statement, but they also generate packages with\r
+names consisting of the parent statement package name with the parent statement\r
+name appended.\r
+\r
+For example, this YANG model considers the container statement `cont` as the\r
+direct substatement of the module.\r
+\r
+[source, yang]\r
+----\r
+container cont {\r
+  container cont-inner {\r
+  }\r
+  list outter-list {\r
+    list list-in-list {\r
+    }\r
+  }\r
+}\r
+----\r
+\r
+Container `cont` is the parent statement for the substatements\r
+`cont-inner` and `outter-list`. `list outter-list` is the parent\r
+statement for substatement `list-in-list`.\r
+\r
+Java code is generated in the following structure: +\r
+\r
+* `org.opendaylight.yang.gen.v1.urn.module.rev201379` - package contains direct\r
+   substatements of module statement\r
+** `Cont.java`\r
+* `org.opendaylight.yang.gen.v1.urn.module.rev201379.cont` - package contains\r
+  substatements of `cont` container statement\r
+** `ContInner.java` - interface representing container `cont-inner`\r
+** `OutterList.java` - interface representing list `outer-list`\r
+* `org.opendaylight.yang.gen.v1.urn.module.rev201379.cont.outter.list` - package\r
+  contains substatements of outter-list list element\r
+  ** `ListInList.java`\r
+\r
+===== Class and interface names\r
+Some YANG statements are mapped to Java classes and interfaces. The name of YANG\r
+element may contain various characters which aren't permitted in Java class names.\r
+Firstly whitespaces are trimmed from YANG name. Next the characters space, -, `\r
+are deleted and the subsequent letter is capitalized. At the end, first letter is\r
+capitalized.\r
+\r
+For example, \r
+`example-name_ without_capitalization` would map to\r
+`ExampleNameWithoutCapitalization`.\r
+\r
+===== Getter and setter names\r
+In some cases, YANG statements are converted to getter and/or setter methods.\r
+The process for getter is:\r
+\r
+. the name of YANG statement is converted to Java class name style as \r
+  <<_class_and_interface_names,explained above>>.\r
+. the word `get` is added as prefix, if resulting type is `Boolean`, the name\r
+  is prefixed with `is` prefix instead of `get`.\r
+. the return type of the getter method is set to Java type representing substatement\r
+\r
+The process for setter is:\r
+\r
+. the name of YANG statement is converted to Java class name style as\r
+  <<_class_and_interface_names,explained above>>.\r
+. the word `set` is added as prefix\r
+. the input parameter name is set to element's name converted to Java parameter style\r
+. the return parameter is set to builder type\r
+\r
+==== Statement specific mapping\r
+\r
+===== module statement\r
+\r
+YANG `module` statement is converted to Java as two Java classes.\r
+Each of the classes is in the separate Java file. The names of Java files are\r
+composed as follows:\r
+`<module name><suffix>.java` where `<suffix>` is either data or service.\r
+\r
+====== Data Interface\r
+\r
+Data Interface has a mapping similar to container, but contains only top level\r
+nodes defined in module.\r
+\r
+Data interface serves only as marker interface for type-safe APIs of\r
+`InstanceIdentifier`.\r
+\r
+====== Service Interface\r
+\r
+Service Interface serves to describe RPC contract defined in the module.\r
+This RPC contract is defined by `rpc` statements.\r
+\r
+RPC implementation usually implement this interface and users of the RPCs\r
+use this interface to invoke RPCs.\r
+\r
+===== container statement\r
+YANG containers are mapped to Java interfaces which extend the Java DataObject and\r
+Augmentable<container-interface>, where container-interface is the name of the mapped\r
+interface.\r
+\r
+For example, the following YANG:\r
+\r
+.YANG model\r
+[source, yang]\r
+----\r
+container cont {\r
+\r
+}\r
+----\r
+\r
+is converted into this Java:\r
+\r
+.Cont.java\r
+[source, java]\r
+----\r
+public interface Cont extends ChildOf<...>, Augmentable<Cont> {\r
+}\r
+----\r
+\r
+===== Leaf statement\r
+Each leaf has to contain at least one type substatement. The leaf is mapped to\r
+getter method of parent statement with return type equal to type substatement\r
+value.\r
+\r
+For example, the following YANG:\r
+\r
+.YANG model\r
+[source, yang]\r
+----\r
+container cont {\r
+  leaf lf {\r
+    type string;\r
+  }\r
+}\r
+----\r
+\r
+is converted into this Java:\r
+\r
+.Cont.java\r
+[source, java]\r
+----\r
+public interface Cont extends DataObject, Augmentable<Cont> {\r
+    String getLf(); // <1>\r
+}\r
+----\r
+\r
+<1> Represents `leaf lf`\r
+\r
+===== leaf-list statement\r
+Each leaf-list has to contain one type substatement. The leaf-list is mapped\r
+to getter method of parent statement with return type equal to List of type\r
+substatement value.\r
+\r
+For example, the following YANG:\r
+\r
+.YANG model\r
+[source, yang]\r
+----\r
+container cont {\r
+    leaf-list lf-lst {\r
+        type string;\r
+    }\r
+}\r
+----\r
+\r
+is converted into this Java:\r
+\r
+.Cont.java\r
+[source, java]\r
+----\r
+public interface Cont extends DataObject, Augmentable<Cont> {\r
+    List<String> getLfLst();\r
+}\r
+----\r
+\r
+===== list statement\r
+\r
+`list` statements are mapped to Java interfaces and a getter method is\r
+generated in the interface associated with it's parent statement.\r
+The return type of getter the method is a Java List of objects implementing\r
+the interface generated corresponding to the `list statement.\r
+Mapping of `list` substatement to Java:\r
+\r
+//[options="header"]\r
+//|===\r
+//|Substatement|Mapping to Java\r
+//|Key|Class\r
+//|===\r
+\r
+For example, the following YANG:\r
+\r
+.YANG model\r
+[source, yang]\r
+----\r
+container cont {\r
+  list outter-list {\r
+    key "leaf-in-list";\r
+    leaf number {\r
+      type uint64;\r
+    }\r
+  }\r
+}\r
+----\r
+\r
+The list statement  `example-list` is mapped to the Java interface `ExampleList` and\r
+the `Cont` interface (parent of `ExampleList`) contains getter method with return\r
+type `List<ExampleList>`. The presence of a `key` statement, triggers generation\r
+of `ExampleListKey`, which may be used to identify item in list.\r
+\r
+The end result is this Java:\r
+\r
+.OutterList.java\r
+[source, java]\r
+----\r
+package org.opendaylight.yang.gen.v1.urn.module.rev201379.cont;\r
+\r
+import org.opendaylight.yangtools.yang.binding.DataObject;\r
+import org.opendaylight.yangtools.yang.binding.Augmentable;\r
+import Java.util.List;\r
+import org.opendaylight.yang.gen.v1.urn.module.rev201379.cont.outter.list.ListInList;\r
+\r
+public interface OutterList extends DataObject, Augmentable<OutterList> {\r
+\r
+    List<String> getLeafListInList();\r
+\r
+    List<ListInList> getListInList();\r
+\r
+    /*\r
+    Returns Primary Key of Yang List Type\r
+    */\r
+    OutterListKey getOutterListKey();\r
+\r
+}\r
+----\r
+\r
+.OutterListKey.java\r
+[source, java]\r
+----\r
+package org.opendaylight.yang.gen.v1.urn.module.rev201379.cont;\r
+\r
+import org.opendaylight.yang.gen.v1.urn.module.rev201379.cont.OutterListKey;\r
+import Java.math.BigInteger;\r
+\r
+public class OutterListKey {\r
+\r
+    private BigInteger _leafInList;\r
+\r
+    public OutterListKey(BigInteger _leafInList) {\r
+        super();\r
+        this_leafInList = _leafInList;\r
+    }\r
+\r
+    public BigInteger getLeafInList() {\r
+        return _leafInList;\r
+    }\r
+\r
+    @Override\r
+    public int hashCode() {\r
+        final int prime = 31;\r
+        int result = 1;\r
+        result = prime * result + ((_leafInList == null) ? 0 : _leafInList.hashCode());\r
+        return result;\r
+    }\r
+\r
+    @Override\r
+    public boolean equals(Object obj) {\r
+        if (this == obj) {\r
+            return true;\r
+        }\r
+        if (obj == null) {\r
+            return false;\r
+        }\r
+        if (getClass() != obj.getClass()) {\r
+            return false;\r
+        }\r
+        OutterListKey other = (OutterListKey) obj;\r
+        if (_leafInList == null) {\r
+            if (other._LeafInList != null) {\r
+                return false;\r
+            }\r
+        } else if(!_leafInList.equals(other._leafInList)) {\r
+            return false;\r
+        }\r
+        return true;\r
+    }\r
+\r
+    @Override\r
+    public String toString() {\r
+        StringBuilder builder = new StringBuilder();\r
+        builder.append("OutterListKey [_leafInList=");\r
+        builder.append(_leafInList);\r
+        builder.append("]");\r
+        return builder.toString();\r
+    }\r
+}\r
+----\r
+\r
+===== choice and case statements\r
+A `choice` element is mapped in mostly the same way a `list` element is. The\r
+`choice` element is mapped to and interface (marker interface) and a new getter\r
+method with the return type of a Java `List` of this marker interfaces is added\r
+to the interface corresponding to the parent statement. Any `case` \r
+substatements are mapped to Java interfaces which extend the marker interface.\r
+\r
+For example, the following YANG:\r
+\r
+.YANG model\r
+[source, yang]\r
+----\r
+container cont {\r
+    choice example-choice {\r
+        case foo-case {\r
+          leaf foo {\r
+            type string;\r
+          }\r
+        }\r
+        case bar-case {\r
+            leaf bar {\r
+              type string;\r
+            }\r
+        }\r
+    }\r
+}\r
+----\r
+\r
+is converted into this Java:\r
+\r
+.Cont.java\r
+[source, java]\r
+----\r
+package org.opendaylight.yang.gen.v1.urn.module.rev201379;\r
+\r
+import org.opendaylight.yangtools.yang.binding.DataObject;\r
+import org.opendaylight.yangtools.yang.binding.Augmentable;\r
+import org.opendaylight.yang.gen.v1.urn.module.rev201379.cont.ChoiceTest;\r
+\r
+public interface Cont extends DataObject, Augmentable<Cont> {\r
+\r
+    ExampleChoice getExampleChoice();\r
+\r
+}\r
+----\r
+\r
+.ExampleChoice.java\r
+[source, java]\r
+----\r
+package org.opendaylight.yang.gen.v1.urn.module.rev201379.cont;\r
+\r
+import org.opendaylight.yangtools.yang.binding.DataObject;\r
+\r
+public interface ExampleChoice extends DataContainer {\r
+}\r
+----\r
+\r
+.FooCase.java\r
+[source, java]\r
+----\r
+package org.opendaylight.yang.gen.v1.urn.module.rev201379.cont.example.choice;\r
+\r
+import org.opendaylight.yangtools.yang.binding.DataObject;\r
+import org.opendaylight.yangtools.yang.binding.Augmentable;\r
+import org.opendaylight.yang.gen.v1.urn.module.rev201379.cont.ChoiceTest;\r
+\r
+public interface FooCase extends ExampleChoice, DataObject, Augmentable<FooCase> {\r
+\r
+    String getFoo();\r
+\r
+}\r
+----\r
+\r
+.BarCase.java\r
+[source, java]\r
+----\r
+package org.opendaylight.yang.gen.v1.urn.module.rev201379.cont.example.choice;\r
+\r
+import org.opendaylight.yangtools.yang.binding.DataObject;\r
+import org.opendaylight.yangtools.yang.binding.Augmentable;\r
+import org.opendaylight.yang.gen.v1.urn.module.rev201379.cont.ChoiceTest;\r
+\r
+public interface BarCase extends ExampleChoice, DataObject, Augmentable<BarCase> {\r
+\r
+    String getBar();\r
+\r
+}\r
+----\r
+\r
+===== grouping and uses statements\r
+`grouping`s are mapped to Java interfaces. `uses` statements in some element\r
+(using of concrete grouping) are mapped as extension of interface for this\r
+element with the interface which represents grouping.\r
+\r
+For example, the following YANG:\r
+\r
+.YANG Model\r
+[source, yang]\r
+----\r
+grouping grp {\r
+  leaf foo {\r
+    type string;\r
+  }\r
+}\r
+\r
+container cont {\r
+    uses grp;\r
+}\r
+----\r
+\r
+is converted into this Java:\r
+\r
+.Grp.java\r
+[source, java]\r
+----\r
+package org.opendaylight.yang.gen.v1.urn.module.rev201379;\r
+\r
+import org.opendaylight.yangtools.yang.binding.DataObject;\r
+\r
+public interface Grp extends DataObject {\r
+\r
+    String getFoo();\r
+\r
+}\r
+----\r
+\r
+.Cont.java\r
+[source, java]\r
+----\r
+package org.opendaylight.yang.gen.v1.urn.module.rev201379;\r
+\r
+import org.opendaylight.yangtools.yang.binding.DataObject;\r
+import org.opendaylight.yangtools.yang.binding.Augmentable;\r
+\r
+public interface Cont extends DataObject, Augmentable<Cont>, Grp {\r
+}\r
+----\r
+\r
+\r
+===== rpc, input and output statements\r
+An `rpc` statement is mapped to Java as method of class `ModuleService.java`.\r
+Any substatements of an `rpc` are mapped as follows:\r
+\r
+[options="header"]\r
+|===\r
+|Rpc Substatement|Mapping\r
+|input|presence of input statement triggers generation of interface\r
+|output|presence of output statement triggers generation of interface\r
+|===\r
+\r
+For example, the following YANG:\r
+\r
+.YANG model\r
+[source, yang]\r
+----\r
+rpc rpc-test1 {\r
+    output {\r
+        leaf lf-output {\r
+            type string;\r
+        }\r
+    }\r
+    input {\r
+        leaf lf-input {\r
+            type string;\r
+        }\r
+    }\r
+}\r
+----\r
+\r
+is converted into this Java:\r
+\r
+.ModuleService.java\r
+[source, java]\r
+----\r
+package org.opendaylight.yang.gen.v1.urn.module.rev201379;\r
+\r
+import Java.util.concurrent.Future;\r
+import org.opendaylight.yangtools.yang.common.RpcResult;\r
+\r
+public interface ModuleService {\r
+\r
+    Future<RpcResult<RpcTest1Output>> rpcTest1(RpcTest1Input input);\r
+\r
+}\r
+----\r
+\r
+.RpcTest1Input.java\r
+[source, java]\r
+----\r
+package org.opendaylight.yang.gen.v1.urn.module.rev201379;\r
+\r
+public interface RpcTest1Input {\r
+\r
+    String getLfInput();\r
+\r
+}\r
+----\r
+\r
+.RpcTest1Output.java\r
+[source, java]\r
+----\r
+package org.opendaylight.yang.gen.v1.urn.module.rev201379;\r
+\r
+public interface RpcTest1Output {\r
+\r
+    String getLfOutput();\r
+\r
+}\r
+----\r
+\r
+\r
+===== notification statement\r
+\r
+`notification` statements are mapped to Java interfaces which extend\r
+the Notification interface.\r
+\r
+For example, the following YANG:\r
+\r
+.YANG model\r
+[source, yang]\r
+----\r
+notification notif {\r
+       }\r
+----\r
+\r
+is converted into this Java:\r
+\r
+.Notif.java\r
+[source, java]\r
+----\r
+package org.opendaylight.yang.gen.v1.urn.module.rev201379;\r
+\r
+\r
+import org.opendaylight.yangtools.yang.binding.DataObject;\r
+import org.opendaylight.yangtools.yang.binding.Augmentable;\r
+import org.opendaylight.yangtools.yang.binding.Notification;\r
+\r
+public interface Notif extends DataObject, Augmentable<Notif>, Notification {\r
+}\r
+----\r
+\r
+==== augment statement\r
+`augment` statements are mapped to Java interfaces. The interface starts with\r
+the same name as the name of augmented interface with a suffix corresponding to\r
+the order number of augmenting interface. The augmenting interface also extends\r
+`Augmentation<>` with actual type parameter equal to augmented interface.\r
+\r
+For example, the following YANG:\r
+\r
+.YANG Model\r
+[source, yang]\r
+----\r
+container cont {\r
+}\r
+\r
+augment "/cont" {\r
+  leaf additional-value {\r
+    type string;\r
+  }\r
+}\r
+----\r
+\r
+is converted into this Java:\r
+\r
+.Cont.java\r
+[source, java]\r
+----\r
+package org.opendaylight.yang.gen.v1.urn.module.rev201379;\r
+\r
+import org.opendaylight.yangtools.yang.binding.DataObject;\r
+import org.opendaylight.yangtools.yang.binding.Augmentable;\r
+\r
+public interface Cont extends DataObject, Augmentable<Cont> {\r
+\r
+}\r
+----\r
+\r
+.Cont1.java\r
+[source, java]\r
+----\r
+package org.opendaylight.yang.gen.v1.urn.module.rev201379;\r
+\r
+import org.opendaylight.yangtools.yang.binding.DataObject;\r
+import org.opendaylight.yangtools.yang.binding.Augmentation;\r
+\r
+public interface Cont1 extends DataObject, Augmentation<Cont> {\r
+\r
+}\r
+----\r
+\r
+==== YANG Type mapping\r
+\r
+===== typedef statement\r
+YANG `typedef` statements are mapped to Java classes. A `typedef` may contain following\r
+substatements:\r
+\r
+[options="header"]\r
+|===\r
+|Substatement | Behaviour\r
+|type| determines wrapped type and how class will be generated\r
+|descripton| Javadoc description\r
+|units| is not mapped\r
+|default|is not mapped\r
+|===\r
+\r
+====== Valid Arguments Type\r
+\r
+Simple values of type argument are mapped as follows:\r
+\r
+[options="header"]\r
+|===\r
+|YANG Type |  Java type\r
+|boolean| Boolean\r
+|empty| Boolean\r
+|int8| Byte\r
+|int16|Short\r
+|int32|Integer\r
+|int64|Long\r
+|string|String or, wrapper class (if pattern substatement is specified)\r
+|decimal64|Double\r
+|uint8|Short\r
+|uint16|Integer\r
+|uint32|Long\r
+|uint64|BigInteger\r
+|binary|byte[]\r
+|===\r
+\r
+Complex values of type argument are mapped as follows:\r
+\r
+[options="header"]\r
+|===\r
+|Argument Type| Java type\r
+|enumeration| generated java enum\r
+|bits| generated class for bits\r
+|leafref| same type as referenced leaf\r
+|identityref| Class\r
+|union| generated java class\r
+|instance-identifier| `org.opendaylight.yangtools.yang.binding.InstanceIdentifier`\r
+|===\r
+\r
+===== Enumeration Substatement Enum\r
+The YANG `enumeration` type has to contain some `enum` substatements. An `enumeration` is mapped as Java enum type (standalone class) and every YANG enum substatements is mapped to Java enum's predefined values.\r
+\r
+An `enum` statement can have following substatements:\r
+\r
+[options="header"]\r
+|===\r
+|Enum's Substatement | Java mapping\r
+|description|is not mapped in API\r
+|value| mapped as input parameter for every predefined value of enum\r
+|===\r
+\r
+For example, the following YANG:\r
+\r
+.YANG model\r
+[source, yang]\r
+----\r
+typedef typedef-enumeration {\r
+    type enumeration {\r
+        enum enum1 {\r
+            description "enum1 description";\r
+            value 18;\r
+        }\r
+        enum enum2 {\r
+            value 16;\r
+        }\r
+        enum enum3 {\r
+        }\r
+    }\r
+}\r
+----\r
+\r
+is converted into this Java:\r
+\r
+.TypedefEnumeration.java\r
+[source, java]\r
+----\r
+public enum TypedefEnumeration {\r
+    Enum1(18),\r
+    Enum2(16),\r
+    Enum3(19);\r
+\r
+    int value;\r
+\r
+    private TypedefEnumeration(int value) {\r
+        this.value = value;\r
+    }\r
+}\r
+----\r
+\r
+===== Bits's Substatement Bit\r
+The YANG `bits` type has to contain some bit substatements. YANG `bits` is mapped to\r
+a Java class (standalone class) and every YANG `bits` substatements is mapped to a\r
+boolean attribute of that class. In addition, the class provides overridden versions\r
+of the Object methods `hashCode`, `toString`, and `equals`.\r
+\r
+For example, the following YANG:\r
+\r
+.YANG Model\r
+[source, yang]\r
+----\r
+typedef typedef-bits {\r
+  type bits {\r
+    bit first-bit {\r
+      description "first-bit description";\r
+        position 15;\r
+      }\r
+    bit second-bit;\r
+  }\r
+}\r
+----\r
+\r
+is converted into this Java:\r
+\r
+.TypedefBits.java\r
+[source, java]\r
+----\r
+public class TypedefBits {\r
+\r
+    private Boolean firstBit;\r
+    private Boolean secondBit;\r
+\r
+    public TypedefBits() {\r
+        super();\r
+    }\r
+\r
+    public Boolean getFirstBit() {\r
+        return firstBit;\r
+    }\r
+\r
+    public void setFirstBit(Boolean firstBit) {\r
+        this.firstBit = firstBit;\r
+    }\r
+\r
+    public Boolean getSecondBit() {\r
+        return secondBit;\r
+    }\r
+\r
+    public void setSecondBit(Boolean secondBit) {\r
+        this.secondBit = secondBit;\r
+    }\r
+\r
+    @Override\r
+    public int hashCode() {\r
+        final int prime = 31;\r
+        int result = 1;\r
+        result = prime * result +\r
+         ((firstBit == null) ? 0 : firstBit.hashCode());\r
+        result = prime * result +\r
+         ((secondBit == null) ? 0 : secondBit.hashCode());\r
+        return result;\r
+    }\r
+\r
+    @Override\r
+    public boolean equals(Object obj) {\r
+        if (this == obj) {\r
+            return true;\r
+        }\r
+        if (obj == null) {\r
+            return false;\r
+        }\r
+        if (getClass() != obj.getClass()) {\r
+            return false;\r
+        }\r
+        TypedefBits other = (TypedefBits) obj;\r
+        if (firstBit == null) {\r
+            if (other.firstBit != null) {\r
+                return false;\r
+            }\r
+        } else if(!firstBit.equals(other.firstBit)) {\r
+            return false;\r
+        }\r
+        if (secondBit == null) {\r
+            if (other.secondBit != null) {\r
+                return false;\r
+            }\r
+        } else if(!secondBit.equals(other.secondBit)) {\r
+            return false;\r
+        }\r
+        return true;\r
+    }\r
+\r
+    @Override\r
+    public String toString() {\r
+        StringBuilder builder = new StringBuilder();\r
+        builder.append("TypedefBits [firstBit=");\r
+        builder.append(firstBit);\r
+        builder.append(", secondBit=");\r
+        builder.append(secondBit);\r
+        builder.append("]");\r
+        return builder.toString();\r
+    }\r
+}\r
+----\r
+\r
+===== Union's Substatement Type\r
+If the type of a `typedef` is `union`, it has to contain `type` substatements.\r
+The `union typedef` is mapped to class and its `type` substatements are mapped\r
+to private class members. Every YANG union subtype gets its own Java constructor\r
+with a parameter which represent just that one attribute.\r
+\r
+For example, the following YANG:\r
+\r
+.YANG model\r
+[source, yang]\r
+----\r
+typedef typedef-union {\r
+    type union {\r
+        type int32;\r
+        type string;\r
+    }\r
+}\r
+----\r
+\r
+is converted into this Java:\r
+\r
+.TypdefUnion.java\r
+[source, java]\r
+----\r
+public class TypedefUnion {\r
+\r
+    private Integer int32;\r
+    private String string;\r
+\r
+    public TypedefUnion(Integer int32) {\r
+        super();\r
+        this.int32 = int32;\r
+    }\r
+\r
+    public TypedefUnion(String string) {\r
+        super();\r
+        this.string = string;\r
+    }\r
+\r
+    public Integer getInt32() {\r
+        return int32;\r
+    }\r
+\r
+    public String getString() {\r
+        return string;\r
+    }\r
+\r
+    @Override\r
+    public int hashCode() {\r
+        final int prime = 31;\r
+        int result = 1;\r
+        result = prime * result + ((int32 == null) ? 0 : int32.hashCode());\r
+        result = prime * result + ((string == null) ? 0 : string.hashCode());\r
+        return result;\r
+    }\r
+\r
+    @Override\r
+    public boolean equals(Object obj) {\r
+        if (this == obj) {\r
+            return true;\r
+        }\r
+        if (obj == null) {\r
+            return false;\r
+        }\r
+        if (getClass() != obj.getClass()) {\r
+            return false;\r
+        }\r
+        TypedefUnion other = (TypedefUnion) obj;\r
+        if (int32 == null) {\r
+            if (other.int32 != null) {\r
+                return false;\r
+            }\r
+        } else if(!int32.equals(other.int32)) {\r
+            return false;\r
+        }\r
+        if (string == null) {\r
+            if (other.string != null) {\r
+                return false;\r
+            }\r
+        } else if(!string.equals(other.string)) {\r
+            return false;\r
+        }\r
+        return true;\r
+    }\r
+\r
+    @Override\r
+    public String toString() {\r
+        StringBuilder builder = new StringBuilder();\r
+        builder.append("TypedefUnion [int32=");\r
+        builder.append(int32);\r
+        builder.append(", string=");\r
+        builder.append(string);\r
+        builder.append("]");\r
+        return builder.toString();\r
+    }\r
+}\r
+----\r
+\r
+===== String Mapping\r
+The YANG `string` type can contain the substatements `length`\r
+and `pattern` which are mapped as follows:\r
+\r
+[options="header"]\r
+|===\r
+|Type substatements  |  Mapping to Java\r
+| length | not mapped\r
+| pattern |\r
+\r
+. list of string constants = list of patterns +\r
+. list of Pattern objects +\r
+. static initialization block where list of Patterns is initialized from list of string of constants\r
+|===\r
+\r
+For example, the following YANG:\r
+\r
+.YANG model\r
+[source, yang]\r
+----\r
+typedef typedef-string {\r
+    type string {\r
+        length 44;\r
+        pattern "[a][.]*"\r
+    }\r
+}\r
+----\r
+\r
+is converted into this Java:\r
+\r
+.TypedefString.java\r
+[source, java]\r
+----\r
+public class TypedefString {\r
+\r
+    private static final List<Pattern> patterns = new ArrayList<Pattern>();\r
+    public static final List<String> PATTERN`CONSTANTS = Arrays.asList("[a][.]*");\r
+\r
+    static {\r
+        for (String regEx : PATTERN`CONSTANTS) {\r
+            patterns.add(Pattern.compile(regEx));\r
+        }\r
+    }\r
+\r
+    private String typedefString;\r
+\r
+    public TypedefString(String typedefString) {\r
+        super();\r
+        // Pattern validation\r
+        this.typedefString = typedefString;\r
+    }\r
+\r
+    public String getTypedefString() {\r
+        return typedefString;\r
+    }\r
+\r
+    @Override\r
+    public int hashCode() {\r
+        final int prime = 31;\r
+        int result = 1;\r
+        result = prime * result + ((typedefString == null) ? 0 : typedefString.hashCode());\r
+        return result;\r
+    }\r
+\r
+    @Override\r
+    public boolean equals(Object obj) {\r
+        if (this == obj) {\r
+            return true;\r
+        }\r
+        if (obj == null) {\r
+            return false;\r
+        }\r
+        if (getClass() != obj.getClass()) {\r
+            return false;\r
+        }\r
+        TypedefString other = (TypedefString) obj;\r
+        if (typedefString == null) {\r
+            if (other.typedefString != null) {\r
+                return false;\r
+            }\r
+        } else if(!typedefString.equals(other.typedefString)) {\r
+            return false;\r
+        }\r
+        return true;\r
+    }\r
+\r
+    @Override\r
+    public String toString() {\r
+        StringBuilder builder = new StringBuilder();\r
+        builder.append("TypedefString [typedefString=");\r
+        builder.append(typedefString);\r
+        builder.append("]");\r
+        return builder.toString();\r
+    }\r
+}\r
+----\r
+\r
+==== identity statement\r
+The purpose of the `identity` statement is to define a new globally unique,\r
+abstract, and untyped value.\r
+\r
+The `base` substatement argument is the name of existing identity from which\r
+the new identity is derived.\r
+\r
+Given that, an `identity` statement is mapped to Java abstract class and\r
+any `base` substatements are mapped as `extends` Java keyword.\r
+The identity name is translated to class name.\r
+\r
+For example, the following YANG:\r
+\r
+.YANG Model\r
+[source, yang]\r
+----\r
+identity toast-type {\r
+\r
+}\r
+\r
+identity white-bread {\r
+   base toast-type;\r
+}\r
+----\r
+\r
+is converted into this Java:\r
+\r
+.ToastType.java\r
+[source, java]\r
+----\r
+public abstract class ToastType extends BaseIdentity {\r
+    protected ToastType() {\r
+        super();\r
+    }\r
+}\r
+----\r
+\r
+.WhiteBread.java\r
+[source, java]\r
+----\r
+public abstract class WhiteBread extends ToastType {\r
+    protected WhiteBread() {\r
+        super();\r
+    }\r
+}\r
+----\r
diff --git a/manuals/developer-guide/src/main/asciidoc/yangtools/yangtools.adoc b/manuals/developer-guide/src/main/asciidoc/yangtools/yangtools.adoc
new file mode 100644 (file)
index 0000000..13bdddb
--- /dev/null
@@ -0,0 +1,52 @@
+== YANG Tools
+:rfc6020: https://tools.ietf.org/html/rfc6020
+:lhotka-yang-json: https://tools.ietf.org/html/draft-lhotka-netmod-yang-json-01
+
+=== Overview
+YANG Tools is set of libraries and tooling providing support for use
+{rfc6020}[YANG] for Java (or other JVM-based language) projects and
+applications.
+
+YANG Tools provides following features in OpenDaylight:
+
+- parsing of YANG sources and
+semantic inference of relationship across YANG models as defined in
+{rfc6020}[RFC6020]
+- representation of YANG-modeled data in Java
+** *Normalized Node* representation - DOM-like tree model, which uses conceptual
+  meta-model more tailored to YANG and OpenDaylight use-cases than a standard XML
+  DOM model allows for.
+** *Java Binding* - concrete data model and classes generated from YANG models,
+  designed to provide compile-time safety when working with YANG-modeled data.
+- serialization / deserialization of YANG-modeled data driven by YANG
+models
+** XML - as defined in {rfc6020}[RFC6020]
+** JSON - as defined in {rfc6020}[draft-lhotka-netmod-yang-json-01]
+** Java Binding to Normalized Node and vice-versa
+- Integration of YANG model parsing into Maven build lifecycle and
+support for third-party generators processing YANG models.
+
+YANG Tools project consists of following logical subsystems:
+
+- *Commons* - Set of general purpose code, which is not specific to YANG, but
+  is also useful outside YANG Tools implementation.
+- *YANG Model and Parser* - YANG semantic model and lexical and semantic parser
+  of YANG models, which creates in-memory cross-referenced represenation of
+  YANG models, which is used by other components to determine their behaviour
+  based on the model.
+- *YANG Data* - Definition of Normalized Node APIs and Data Tree APIs, reference
+  implementation of these APIs and implementation of XML and JSON codecs for
+  Normalized Nodes.
+- *YANG Maven Plugin* - Maven plugin which integrates YANG parser into Maven
+  build lifecycle and provides code-generation framework for components, which
+  wants to generate code or other artefacts based on YANG model.
+- *YANG Java Binding* - Mapping of YANG model to generated Java APIs.
+  Java Binding also references to set of compile-time and runtime components which
+  implements this mapping, provides generation of classes and APIs based on
+  YANG models and integrate these Java Binding objects with **YANG Data** APIs
+  and components.
+
+* *Models* - Set of *IETF* and *YANG Tools* models, with generated Java Bindings
+  so they could be simply consumed outside of *YANG Tools*.
+
+include::yang-java-binding-explained.adoc[]