1 = Java Binding Specification 2
2 Tony Tkacik <ttkacik@cisco.com>; Robert Varga <rovarga@cisco.com>; Martin Sunal <msunal@cisco.com>; Martin Ciglan <mciglan@cisco.com>
3 :rfc6020: https://tools.ietf.org/html/rfc6020
12 naming space, in which all identifiers needs to be unique
17 Instantiated Data Node::
18 Instantiated Data Tree::
23 === Binding Specification v2 Concepts
26 Represent node, which is instantiable by users as a part of notification,
27 rpc, action or data tree.
29 Represents node, which is part of instantiated data tree, this interface
30 is not used directly, but rather via <<TreeChildNode>>. See <<instantiated-data-tree-rules>>
33 Represents virtual root of instantiated data tree node.
35 Represents node, which is part of instantiated data tree and is not root of
38 Represents instantiated node, which is subjectible to be extended / augmented
39 by `augment` statement from external module.
41 Represents extension to instantiated node, which is introduced from different
42 model than instantiated node.
43 <<InstanceIdentifier>>::
44 Unique identifier of node / subtree in data tree, which provides unambiguous
45 information, how to reference node / subtree in Instantiated Data Tree.
50 .2+|Statement .2+| In groupings 3+| Instantiable .2+| Augmentable
51 | In Data | In RPC | In Notification
53 | `grouping` | Yes | No | No | No | No
55 | `container` | Yes | Yes | Yes | Yes | Yes
57 | `leaf` | Yes | Yes | Yes | Yes | No
59 | `leaf-list` | Yes | Yes | Yes | Yes | No
61 | `list` | Yes | Yes | Yes | Yes | Yes
63 | `anydata` | Yes | Yes | Yes | Yes | No
65 | `anyxml` | Yes | Yes | Yes | Yes | No
67 | `choice` | Yes | Yes | Yes | Yes | Yes
69 | `case` | Yes | Yes | Yes | Yes | Yes
71 | `input` | Yes | No | Yes | No | Yes
73 | `output` | Yes | No | Yes | No | Yes
75 | `notification` | Yes | No | No | Yes | Yes
81 YANG defines several namespaces and naming space of YANG is wider then applicable
82 namespace of JAVA language. In order to decrease conflicts between various
83 YANG-defined namespaces and classes introduced by Binding Specification, it
86 * separate namespaces by Java package hierarchy
87 ** each namespace must define rules how to construct package name, which
88 will not conflict with other namespace
89 * if multiple classes are generated for YANG statement they need to be in separate
90 packages to decrease possible conflicts with siblings.
91 * if Binding Specification introduces new concepts, which does not have explicit
92 namespace rules in YANG, these concepts needs to be in their own, separate
93 namespaces, in order to not conflict on valid YANG namespace items.
96 This rules allows to identify two types of namespaces:
98 .Namespace types by source of namespace
100 Naming space explicitly defined in YANG specification, which needs to be
101 explicitly supported in order to prevent naming conflicts.
103 Naming space introduced by Binding Specification for additional properties
104 and functionality of Binding Specification. This namespaces needs to be separate
105 from YANG namespaces in order to not have naming conflict with YANG-derived
109 Binding Specification v2 uses following namespaces:
111 .Concrete namespaces used in Binding Specification
112 <<module-namespace>>::
113 YANG namespace containing representation for all modules.
114 <<identity-namespace>>::
115 YANG namespace containing representation for all `identity` statements. Identities
116 needs to be separated to prevent naming conflict between Grouping, Data, Type
119 YANG namespace containing representation for all `typedef` statements and
120 annonymous definitions of `union`, `enumeration` and `bits` types. Types needs
121 to be seperated to prevent naming conflict between Identity, Grouping and Data
123 <<grouping-namespace>>::
124 YANG namespace containing representation for all `grouping` statements and their
125 child data node statements. Groupings needs to be separated to prevent naming
126 conflict between Identity, Type, Data namespaces.
128 Binding namespace containing representation for all `key` statements.
129 Representations of key statements needs to be in separate namespace, since it is not defined
130 in YANG specification.
132 YANG namespace containing representation of instantiated data tree.
133 Data needs to be separated to prevent naming conflict between Identity, Type,
136 Binding namespace containing Transfer Objects and Builders representing
137 instantiated data tree items.
139 NOTE: Most of Binding Namespaces were introduced to decrease possibility of name
140 conflict between concepts defined in YANG and additional concepts introduced
141 by Binding Specification.
143 === Package hierarchy
145 .Package hierarchy for model
148 |Namespace | Package | Description
150 | <<identity-namespace, Identity>> | `ident`
151 | flat package containing representation for all `identity`
153 .3+| <<type-namespace, Type>> | `type`
154 | flat package containing representations for all top-level
158 | path-based package hierarchy containing representation
159 for `typedef` statements nested in grouping statements, or anonymous types
160 requiring code generation defined inside groupings
163 | path-based package hierarchy containing representation
164 for `typedef` statements nested in grouping statements, or anonymous types
165 requiring code generation defined inside instantiated data nodes
167 | <<key-namespace, Key>> | `key`
168 | path-based package hierarchy containing representation
169 of key statements for grouping code generation defined inside groupings
171 | <<grouping-namespace, Grouping>> | `grp`
172 | path-based package hierarchy containing representation
173 for `grouping` statements and data node statements nested in these groupings
175 | <<data-namespace, Data>> | `data`
176 | path-based package hierarchy containing representation of instantiated
179 | <<dto-namespace, Builder>> | `dto`
180 | path-based package hierarchy containing Tranfer Objects and their builders
181 for instantiated data nodes
189 [[identity-namespace]]
190 === Identity Namespace
196 [[grouping-namespace]]
197 === Grouping Namespace
206 === Builder Namespace
213 [[subpackage-structure]]
214 === Subpackage Naming
221 === `typedef` statement
223 ==== Globally scoped `typedef`
225 ==== Subtree scoped `typedef`
227 Subtree scoped `typedef` statement is type definition, which is not substatement
228 of `module` or `submodule`, and is only visible to child elements of parent
231 * Representation is generated in Type namespace according to following rules:
236 YANG types does not provide single, simple model of behaviour - some times
237 exhibits special properties to extensibility or limiting scope of valid values
241 .Base types and their behaviours
243 | YANG Type | Description | Java Mapping
246 | `binary` | Any binary data | `Binary`?
247 | `bits` | A set of bits or flags | Custom class
248 | `boolean` | `true` or `false` | `Boolean`
249 | `decimal64` | 64-bit signed decimal number | No
250 | `empty` | A leaf that does not have any value | No
251 | `enumeration` | Enumerated strings | No
252 | `identityref` | A reference to an abstract identity | Yes
253 | `instance-identifier` | References a data tree node | Yes
254 | `int8` | 8-bit signed integer | No
255 | `int16` | 16-bit signed integer | No
256 | `int32` | 32-bit signed integer | No
257 | `int64` | 64-bit signed integer | No
258 | `leafref` | A reference to a leaf instance | Maybe
259 | `string` | Human-readable string | No
260 | `uint8` | 8-bit unsigned integer | No
261 | `uint16` | 16-bit unsigned integer | No
262 | `uint32` | 32-bit unsigned integer | No
263 | `uint64` | 64-bit unsigned integer | No
264 | `union` | Choice of member types | Maybe
267 FIXME: Finalize table
282 ==== `enumeration` type
285 ==== `identityref` type
286 ==== `instance-identifier` type
294 Data nodes could be separated into two distinct groups, based on presence of
298 Node, which according to YANG schema does not have child nodes, is leaf node
299 and carries only simple value.
301 Node, which according to YANG schema may have child nodes, node itself does not
302 carry values, values are stored in descendant leaf nodes.
306 === `leaf-list` Statement
309 === `container` Statement
311 Builders will be located in package "dto"
319 container foo-builder {
323 [uml, file="container-builder.png"]
325 set namespaceSeparator none
330 interface data.FooBuilder {
334 In situations where we have a containing element which has as its child a single container, we should make it easy to autobox it. This should not be implemented in the interfaces themselves, but rather should be a method in the associated builder.
338 container example-outter {
339 container example-inner {
363 [uml, file="list-Keyed.png"]
365 set namespaceSeparator none
370 interface key.foo.FooIdentifier {
373 interface type.foo.identifier.IdentifierUnion {
376 data.Foo o- key.foo.FooIdentifier
377 key.foo.FooIdentifier o- type.foo.identifier.IdentifierUnion
380 ==== List without Key
382 === `choice` Statement
394 leaf bar { type string; }
400 [uml, file="case.png"]
402 set namespaceSeparator none
410 + getBase() : data.top.Base;
412 interface data.top.Base
413 interface data.top.base.Foo {
414 + getFoo() : data.top.base.foo.Foo
416 interface data.top.base.foo.Foo
417 interface data.top.base.Bar {
421 data.top.Base -u-|> Choice
422 data.top.base.Foo -u-|> Case
423 data.top.base.Bar -u-|> Case
425 data.top.base.Foo -u-|> data.top.Base
426 data.top.base.Bar -u-|> data.top.base.Foo
428 data.Top o- data.top.Base
429 data.top.base.Foo o- data.top.base.foo.Foo
434 [[instantiated-data-node-rules]]
435 === Instantiated Data Node Rules
438 FIXME: Do we need section per type, or should just general rules be described.
441 ==== `container` Statement
444 FIXME: Here should be Augmentable & Instantiated
447 ==== `leaf` Statement
449 ==== `leaf-list` Statement
451 ==== `choice` Statement
453 ==== `case` Statement
456 FIXME: Here should be Augmentable & Instantiated
459 ==== `list` Statement
462 FIXME: Here should be Augmentable & Instantiated, List signature uses concrete
466 ==== `input` Statement
469 FIXME: Here should be Augmentable & Instantiated
472 ==== `output` Statement
475 FIXME: Here should be Augmentable & Instantiated
478 ==== `notification` Statement
481 FIXME: Here should be Augmentable & Instantiated
484 [[instantiated-data-tree-rules]]
485 === Instantiated Data Tree Rules
488 ==== `container` Statement
491 FIXME: Here should be Augmentable & Instantied & ChildDataNode
495 ==== `leaf` Statement
497 ==== `leaf-list` Statement
499 ==== `case` Statement
502 FIXME: Here should be Augmentable & Instantied & ChildDataNode
505 ==== `list` Statement
508 FIXME: Here should be Augmentable & Instantied & ChildDataNode
511 === `grouping` Statement
513 * `grouping` statement is represented by `interface`
514 ** class name is generated according to <<class-naming>> with suffix `Grouping`
515 * Representations of `grouping` statements are generated into <<grouping-namespace>>
516 * data schema nodes under grouping are represented by `interface` and are generated
517 into <<grouping-namespace>>
518 ** getters (accessors) from parent nodes are generated according to <<accessor-rules>>
519 ** class name is generated according to <<class-naming>> with suffix `Data`
520 ** data schema nodes does not follow <<instantiated-data-tree-rules>>, these interfaces
521 are used only in instantiated data tree.
528 grouping simple { <1>
530 leaf bar { type string;} <3>
533 <1> Is represented by interface `grp.SimpleGrouping`
534 <2> Is represented by interface `grp.simple.FooData` and getter in `grp.SimpleGrouping`
535 with signature `public grp.simple.FooData getFoo();`
536 <3> Is represented by getter in `grp.SimpleGrouping` with signature `public String getBar()`
538 [uml, file="grouping1.png"]
540 interface grp.SimpleGrouping {
542 + getFoo() : grp.simple.FooData
544 interface grp.simple.FooData
545 grp.SimpleGrouping o- grp.simple.FooData
549 ==== Data Node substatements
551 Representations of data node substatements are generated according to rules
552 described in <<data-node-rules>> with following changes:
554 * Interface names for `case`, `choice`, `container` and `list`, is suffixed by
555 `Data` suffix, in order to not conflict with same named groupings inside same
557 ** Getters in parent node, are still generated without `Data` suffix, so
558 the getter signature is in form `FooData getFoo()`
559 ** If return value of getter is constructed using generics (eg. `list`)
560 instead of signature `List<ListItem>` or `Map<ListKey, ListItem>`, wildcarded
561 `? extends ListItem` generic argument are used to allow for overriding during
562 <<uses-statement,instantation of grouping>>.
565 ==== `list` substatement
568 FIXME: Add reasoning / examples for need to use ? extends, instead of directly
572 ==== `leaf-list` susbstatement
575 FIXME: Add reasoning / examples for need to use ? extends, instead of directly
576 using generics for types, which may need instantiation
582 * `uses` statement triggers interface of parent statement to extend (implement)
583 interface of `grouping` referenced by `uses` argument.
584 * As in YANG `uses` statement triggers instatiation of data children of `grouping`
585 which will result in generation of these children as-if they were direct
586 children of parent statement
587 ** data node children are generated according to rules defined for parent statement.
588 Different rules apply based on parent type (instantiated data tree, `input`,
589 `output` or `grouping`)
590 ** interfaces generated for data children extends (implements) interfaces for
591 same children generated for referenced `grouping`
593 .Simple Grouping and Uses
600 leaf bar { type string;}
608 [uml, file="grouping2.png"]
610 set namespaceSeparator none
612 interface grp.SimpleGrouping {
614 + getFoo() : grp.simple.FooData
616 interface grp.simple.FooData
618 + getFoo() : data.top.Foo
620 interface data.top.Foo
622 grp.SimpleGrouping o-- grp.simple.FooData
624 data.Top o-- data.top.Foo
625 data.Top -|> grp.SimpleGrouping
626 data.top.Foo -|> grp.simple.FooData
629 NOTE: Diagram does not show all details for `data.Top` and `data.top.Foo`, which
630 are based on <<instantiated-data-tree-rules>>
634 .Grouping with Nested Grouping
640 set namespaceSeparator none
641 grouping with-inner {
654 [uml, file="grouping3.png"]
656 set namespaceSeparator none
658 interface grp.withinner.inner.ContData
659 interface grp.withinner.InnerGrouping {
660 + getCont() : grp.withinner.inner.ContData
664 interface grp.withinner.ContData
666 interface grp.WithInnerGrouping {
667 + getCont() : grp.withinner.ContData
672 + getCont() : data.top.Cont
675 interface data.top.Cont {
678 data.Top o-- data.top.Cont : contains
680 data.Top -|> grp.WithInnerGrouping
681 data.top.Cont -|> grp.withinner.ContData
683 grp.WithInnerGrouping -|> grp.withinner.InnerGrouping : uses (implements)
684 grp.WithInnerGrouping o-- grp.withinner.ContData : contains
685 grp.withinner.InnerGrouping o-- grp.withinner.inner.ContData : contains
687 grp.withinner.ContData -|> grp.withinner.inner.ContData : is concretization of (implements)
691 NOTE: Diagram does not show all details for `data.Top` and `data.top.Cont`, which
692 are based on <<instantiated-data-tree-rules>>
697 ==== `augment` substatement
699 .Uses & Augment in instantiated Data Tree
722 [uml, file="grouping4.png"]
724 set namespaceSeparator none
727 interface data.top.Nested
728 interface data.top.nested.Bar
730 data.Top o-- data.top.Nested
731 data.top.Nested o-- data.top.nested.Bar
733 interface grp.ExampleGrouping
734 interface grp.example.NestedData
737 grp.ExampleGrouping o-- grp.example.NestedData
739 data.Top -|> grp.ExampleGrouping
740 data.top.Nested -|> grp.example.NestedData
743 NOTE: Diagram does not show all details for `data.Top`, `data.top.Nested` and
744 `data.top.nested.Bar`, which are based on <<instantiated-data-tree-rules>>
750 .Uses & Augment in grouping
773 [uml, file="grouping5.png"]
775 set namespaceSeparator none
777 interface grp.TopGrouping
778 interface grp.top.NestedData
779 interface grp.top.nested.BarData
781 grp.TopGrouping o-- grp.top.NestedData
782 grp.top.NestedData o-- grp.top.nested.BarData
784 interface grp.ExampleGrouping
785 interface grp.example.NestedData
787 grp.ExampleGrouping o-- grp.example.NestedData
789 grp.TopGrouping -|> grp.ExampleGrouping
790 grp.top.NestedData -|> grp.example.NestedData
795 === `augment` statement
797 Representation of `augment` statement depends on module in which target node of
798 augment statement is defined
800 * <<uses-augment, augment is substatement of uses>> - data nodes are represented
801 as-if their statements were inlined in target node.
802 See <<uses-augment, uses Statement: augment Substatement>> section for details.
803 * <<augment-same-module,target node in same module as augment>> - data nodes are
804 represented as-if their statements were inlined in target.
805 See <<augment-same-module>> for details & examples.
806 * <<augment-other-module, target node in other module as augment>> - interface representing
807 augmentation is generated, child data nodes are generated by rules for
808 <<instantiated-data-node-rules>>.
809 See <<augment-other-module>> for details & examples.
811 `augment` statement targets only instantiated data nodes, so child data node
812 representation are always ge
814 [[augment-same-module]]
815 ==== Augmentation target in same module
817 All data node children are generated as-if they were directly defined inside
818 target node. There are no externally observable artefacts in generated
819 representation of these nodes, which would point out that they were defined
820 using `augment` statement instead of directly inlining them in target node.
822 .Why augment of same module is same as inlining
825 This rule may seems counterintuitive at first sight, but YANG defines
826 backwards compatibility in terms of effective model instead of way how model
827 is represented. `augment` statement, when targeting node in same module is not
828 externally observable and could factored out by inlining these statements.
830 Definition of `augment` statement in YANG also defines different behaviour when
831 target is same module and allows all features as-if this statements were
835 .Augment with target in same module
837 .YANG module written using augmentations
850 .Same module written without need to augment
859 .Same module written with grouping
871 Java representation for all variants
872 [uml, file="augment1.png"]
874 set namespaceSeparator none
877 interface data.top.Foo
879 data.Top o- data.top.Foo
884 [[augment-other-module]]
885 ==== Augmentation target in other module
887 .Augment with target in other module
901 import top { prefix top; }
912 [uml,file="augment2.png"]
914 set namespaceSeparator none
916 interface Augmentable<T>
917 interface Augmentation<T>
919 interface top.data.Top
920 interface foo.data.FooTop {
924 interface foo.data.top.Bar
926 top.data.Top -u-|> Augmentable : T = top.data.Top
927 foo.data.FooTop -u-|> Augmentation : T = top.data.Top
928 top.data.Top o-- foo.data.FooTop
929 foo.data.FooTop o-- foo.data.top.Bar
934 .Multiple augments with same target
948 import top { prefix top; }
965 [uml,file="augment3.png"]
967 set namespaceSeparator none
969 interface Augmentable<T>
970 interface Augmentation<T>
972 interface top.data.Top
973 interface foo.data.FooTop {
978 interface foo.data.top.Bar
979 interface foo.data.top.Baz
981 top.data.Top -u-|> Augmentable : T = top.data.Top
982 foo.data.FooTop -u-|> Augmentation : T = top.data.Top
983 top.data.Top o-- foo.data.FooTop
984 foo.data.FooTop o-- foo.data.top.Bar
985 foo.data.FooTop o-- foo.data.top.Baz
990 .Multiple augments with different targets
1008 import target { prefix t; }
1010 augment "/t:first" {
1016 augment "/t:second" {
1025 [uml, file="augment4.png"]
1027 set namespaceSeparator none
1029 interface Augmentable<T>
1030 interface Augmentation<T>
1032 interface target.data.First
1033 interface target.data.Second
1035 interface foo.data.FooFirst {
1038 interface foo.data.FooSecond {
1042 interface foo.data.first.Bar
1043 interface foo.data.second.Baz
1045 target.data.First -u-|> Augmentable : T = target.data.First
1046 target.data.Second -u-|> Augmentable : T = target.data.Second
1048 foo.data.FooFirst -u-|> Augmentation : T = target.data.First
1049 foo.data.FooSecond -u-|> Augmentation : T = target.data.Second
1052 target.data.First o-- foo.data.FooFirst
1053 target.data.Second o-- foo.data.FooSecond
1055 foo.data.FooFirst o-- foo.data.first.Bar
1056 foo.data.FooSecond o-- foo.data.second.Baz
1074 grouping key.grp.nodes.node.nodeidentifier
1076 instantiated key.data.nodes.node.nodeidentifier