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.
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.
108 Binding Specification v2 uses following namespaces:
110 .Concrete namespaces used in Binding Specification
111 <<module-namespace>>::
112 YANG namespace containing representation for all modules.
113 <<identity-namespace>>::
114 YANG namespace containing representation for all `identity` statements. Identities
115 needs to be separated to prevent naming conflict between Grouping, Data, Type
118 YANG namespace containing representation for all `typedef` statements and
119 annonymous definitions of `union`, `enumeration` and `bits` types. Types needs
120 to be seperated to prevent naming conflict between Identity, Grouping and Data
122 <<grouping-namespace>>::
123 YANG namespace containing representation for all `grouping` statements and their
124 child data node statements. Groupings needs to be separated to prevent naming
125 conflict between Identity, Type, Data namespaces.
127 Binding namespace containing representation for all `key` statements.
128 Representations of key statements needs to be in separate namespace, since it is not defined
129 in YANG specification.
131 YANG namespace containing representation of instantiated data tree.
132 Data needs to be separated to prevent naming conflict between Identity, Type,
135 Binding namespace containing Transfer Objects and Builders representing
136 instantiated data tree items.
138 NOTE: Most of Binding Namespaces were introduced to decrease possibility of name
139 conflict between concepts defined in YANG and additional concepts introduced
140 by Binding Specification.
142 === Package hierarchy
144 .Package hierarchy for model
147 |Namespace | Package | Description
149 | <<identity-namespace, Identity>> | `ident`
150 | flat package containing representation for all `identity`
152 .3+| <<type-namespace, Type>> | `type`
153 | flat package containing representations for all top-level
157 | path-based package hierarchy containing representation
158 for `typedef` statements nested in grouping statements, or anonymous types
159 requiring code generation defined inside groupings
162 | path-based package hierarchy containing representation
163 for `typedef` statements nested in grouping statements, or anonymous types
164 requiring code generation defined inside instantiated data nodes
166 | <<key-namespace, Key>> | `key`
167 | path-based package hierarchy containing representation
168 of key statements for grouping code generation defined inside groupings
170 | <<grouping-namespace, Grouping>> | `grp`
171 | path-based package hierarchy containing representation
172 for `grouping` statements and data node statements nested in these groupings
174 | <<data-namespace, Data>> | `data`
175 | path-based package hierarchy containing representation of instantiated
178 | <<dto-namespace, Builder>> | `dto`
179 | path-based package hierarchy containing Tranfer Objects and their builders
180 for instantiated data nodes
188 [[identity-namespace]]
189 === Identity Namespace
195 [[grouping-namespace]]
196 === Grouping Namespace
205 === Builder Namespace
212 [[subpackage-structure]]
213 === Subpackage Naming
220 === `typedef` statement
222 ==== Globally scoped `typedef`
224 ==== Subtree scoped `typedef`
226 Subtree scoped `typedef` statement is type definition, which is not substatement
227 of `module` or `submodule`, and is only visible to child elements of parent
230 * Representation is generated in Type namespace according to following rules:
235 YANG types does not provide single, simple model of behaviour - some times
236 exhibits special properties to extensibility or limiting scope of valid values
240 .Base types and their behaviours
242 | YANG Type | Description | Java Mapping
245 | `binary` | Any binary data | `Binary`?
246 | `bits` | A set of bits or flags | Custom class
247 | `boolean` | `true` or `false` | `Boolean`
248 | `decimal64` | 64-bit signed decimal number | No
249 | `empty` | A leaf that does not have any value | No
250 | `enumeration` | Enumerated strings | No
251 | `identityref` | A reference to an abstract identity | Yes
252 | `instance-identifier` | References a data tree node | Yes
253 | `int8` | 8-bit signed integer | No
254 | `int16` | 16-bit signed integer | No
255 | `int32` | 32-bit signed integer | No
256 | `int64` | 64-bit signed integer | No
257 | `leafref` | A reference to a leaf instance | Maybe
258 | `string` | Human-readable string | No
259 | `uint8` | 8-bit unsigned integer | No
260 | `uint16` | 16-bit unsigned integer | No
261 | `uint32` | 32-bit unsigned integer | No
262 | `uint64` | 64-bit unsigned integer | No
263 | `union` | Choice of member types | Maybe
266 FIXME: Finalize table
281 ==== `enumeration` type
284 ==== `identityref` type
285 ==== `instance-identifier` type
293 Data nodes could be separated into two distinct groups, based on presence of
297 Node, which according to YANG schema does not have child nodes, is leaf node
298 and carries only simple value.
300 Node, which according to YANG schema may have child nodes, node itself does not
301 carry values, values are stored in descendant leaf nodes.
305 === `leaf-list` Statement
308 === `container` Statement
310 Builders will be located in package "dto"
318 container foo-builder {
322 [uml, file="container-builder.png"]
324 set namespaceSeparator none
329 interface data.FooBuilder {
333 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.
337 container example-outter {
338 container example-inner {
353 key identifier key fookey;
369 [uml, file="list-Keyed.png"]
371 set namespaceSeparator none
376 interface key.foo.FooIdentifier {
379 interface key.foo.FooKey {
382 interface key.foo.FooFooKey {
385 interface type.foo.identifier.IdentifierUnion {
388 data.Foo o- key.foo.FooIdentifier
389 data.Foo o- key.foo.FooKey
390 data.Foo o- key.foo.FooFooKey
391 key.foo.FooIdentifier o- type.foo.identifier.IdentifierUnion
394 ==== List without Key
396 === `choice` Statement
408 leaf bar { type string; }
414 [uml, file="case.png"]
416 set namespaceSeparator none
424 + getBase() : data.top.Base;
426 interface data.top.Base
427 interface data.top.base.Foo {
428 + getFoo() : data.top.base.foo.Foo
430 interface data.top.base.foo.Foo
431 interface data.top.base.Bar {
435 data.top.Base -u-|> Choice
436 data.top.base.Foo -u-|> Case
437 data.top.base.Bar -u-|> Case
439 data.top.base.Foo -u-|> data.top.Base
440 data.top.base.Bar -u-|> data.top.Base
442 data.Top o- data.top.Base
443 data.top.base.Foo o- data.top.base.foo.Foo
448 [[instantiated-data-node-rules]]
449 === Instantiated Data Node Rules
452 FIXME: Do we need section per type, or should just general rules be described.
455 ==== `container` Statement
458 FIXME: Here should be Augmentable & Instantiated
461 ==== `leaf` Statement
463 ==== `leaf-list` Statement
465 ==== `choice` Statement
467 ==== `case` Statement
470 FIXME: Here should be Augmentable & Instantiated
473 ==== `list` Statement
476 FIXME: Here should be Augmentable & Instantiated, List signature uses concrete
480 ==== `input` Statement
483 FIXME: Here should be Augmentable & Instantiated
486 ==== `output` Statement
489 FIXME: Here should be Augmentable & Instantiated
492 ==== `notification` Statement
495 FIXME: Here should be Augmentable & Instantiated
498 [[instantiated-data-tree-rules]]
499 === Instantiated Data Tree Rules
502 ==== `container` Statement
505 FIXME: Here should be Augmentable & Instantied & ChildDataNode
509 ==== `leaf` Statement
511 ==== `leaf-list` Statement
513 ==== `case` Statement
516 FIXME: Here should be Augmentable & Instantied & ChildDataNode
519 ==== `list` Statement
522 FIXME: Here should be Augmentable & Instantied & ChildDataNode
525 === `grouping` Statement
527 * `grouping` statement is represented by `interface`
528 ** interface name is generated according to <<class-naming>> with suffix `Grouping`
529 * Representations of `grouping` statements are generated into <<grouping-namespace>>
530 * schema nodes under grouping are represented by `interface` and are generated
531 into <<grouping-namespace>> + name of grouping
532 ** getters (accessors) from parent nodes are generated according to <<accessor-rules>>
533 ** class name is generated according to <<class-naming>> with suffix `Data`
534 ** schema nodes does not follow <<instantiated-data-tree-rules>>, these interfaces
535 are used only in instantiated data tree.
542 grouping simple { <1>
544 leaf bar { type string;} <3>
547 <1> Is represented by interface `grp.SimpleGrouping`
548 <2> Is represented by interface `grp.simple.FooData` and getter in `grp.SimpleGrouping`
549 with signature `public grp.simple.FooData getFoo();`
550 <3> Is represented by getter in `grp.SimpleGrouping` with signature `public String getBar()`
552 [uml, file="grouping1.png"]
554 interface grp.SimpleGrouping {
556 + getFoo() : grp.simple.FooData
558 interface grp.simple.FooData
559 grp.SimpleGrouping o- grp.simple.FooData
563 ==== Data Node substatements
565 Representations of data node substatements are generated according to rules
566 described in <<data-node-rules>> with following changes:
568 MS: proposed interface names:
569 case - <NodeName>Case
570 choice - <<NodeName>Choice
571 container, list - <NodeName>
574 MC: I would keep Data suffix, but idea about distinguishing cases and choices
577 * Interface names for `case`, `choice`, `container` and `list`, is suffixed by
578 `Data` suffix, in order to not conflict with same named groupings inside same
580 ** Getters in parent node, are still generated without `Data` suffix, so
581 the getter signature is in form `FooData getFoo()`
582 ** If return value of getter is constructed using generics (eg. `list`)
583 instead of signature `List<ListItem>` or `Map<ListKey, ListItem>`, wildcarded
584 `? extends ListItem` generic argument are used to allow for overriding during
585 <<uses-statement,instantation of grouping>>.
588 ==== `list` substatement
591 FIXME: Add reasoning / examples for need to use ? extends, instead of directly
595 ==== `leaf-list` susbstatement
598 FIXME: Add reasoning / examples for need to use ? extends, instead of directly
599 using generics for types, which may need instantiation
605 * `uses` statement triggers interface of parent statement to extend (implement)
606 interface of `grouping` referenced by `uses` argument.
607 * As in YANG `uses` statement triggers instatiation of data children of `grouping`
608 which will result in generation of these children as-if they were direct
609 children of parent statement
610 ** data node children are generated according to rules defined for parent statement.
611 Different rules apply based on parent type (instantiated data tree, `input`,
612 `output` or `grouping`)
613 ** interfaces generated for data children extends (implements) interfaces for
614 same children generated for referenced `grouping`
616 .Simple Grouping and Uses
623 leaf bar { type string;}
630 [uml, file="grouping2.png"]
632 set namespaceSeparator none
634 interface grp.SimpleGrouping {
636 + getFoo() : grp.simple.FooData
638 interface grp.simple.FooData
640 + getFoo() : data.top.Foo
642 interface data.top.Foo
644 grp.SimpleGrouping o-- grp.simple.FooData
646 data.Top o-- data.top.Foo
647 data.Top -|> grp.SimpleGrouping
648 data.top.Foo -|> grp.simple.FooData
651 NOTE: Diagram does not show all details for `data.Top` and `data.top.Foo`, which
652 are based on <<instantiated-data-tree-rules>>
656 .Grouping with Nested Grouping
662 grouping with-inner {
674 [uml, file="grouping3.png"]
676 set namespaceSeparator none
678 interface grp.withinner.inner.ContData
679 interface grp.withinner.InnerGrouping {
680 + getCont() : grp.withinner.inner.ContData
684 interface grp.withinner.ContData
686 interface grp.WithInnerGrouping {
687 + getCont() : grp.withinner.ContData
692 + getCont() : data.top.Cont
695 interface data.top.Cont {
698 data.Top o-- data.top.Cont : contains
700 data.Top -|> grp.WithInnerGrouping
701 data.top.Cont -|> grp.withinner.ContData
703 grp.WithInnerGrouping -|> grp.withinner.InnerGrouping : uses (implements)
704 grp.WithInnerGrouping o-- grp.withinner.ContData : contains
705 grp.withinner.InnerGrouping o-- grp.withinner.inner.ContData : contains
707 grp.withinner.ContData -|> grp.withinner.inner.ContData : is concretization of (implements)
711 NOTE: Diagram does not show all details for `data.Top` and `data.top.Cont`, which
712 are based on <<instantiated-data-tree-rules>>
717 ==== `augment` substatement
719 .Uses & Augment in instantiated Data Tree
742 [uml, file="grouping4.png"]
744 set namespaceSeparator none
747 interface data.top.Nested
748 interface data.top.nested.Bar
750 data.Top o-- data.top.Nested
751 data.top.Nested o-- data.top.nested.Bar
753 interface grp.ExampleGrouping
754 interface grp.example.NestedData
757 grp.ExampleGrouping o-- grp.example.NestedData
759 data.Top -|> grp.ExampleGrouping
760 data.top.Nested -|> grp.example.NestedData
763 NOTE: Diagram does not show all details for `data.Top`, `data.top.Nested` and
764 `data.top.nested.Bar`, which are based on <<instantiated-data-tree-rules>>
770 .Uses & Augment in grouping
793 [uml, file="grouping5.png"]
795 set namespaceSeparator none
797 interface grp.TopGrouping
798 interface grp.top.NestedData
799 interface grp.top.nested.BarData
801 grp.TopGrouping o-- grp.top.NestedData
802 grp.top.NestedData o-- grp.top.nested.BarData
804 interface grp.ExampleGrouping
805 interface grp.example.NestedData
807 grp.ExampleGrouping o-- grp.example.NestedData
809 grp.TopGrouping -|> grp.ExampleGrouping
810 grp.top.NestedData -|> grp.example.NestedData
815 === `augment` statement
817 Representation of `augment` statement depends on module in which target node of
818 augment statement is defined
820 * <<uses-augment, augment is substatement of uses>> - data nodes are represented
821 as-if their statements were inlined in target node.
822 See <<uses-augment, uses Statement: augment Substatement>> section for details.
823 * <<augment-same-module,target node in same module as augment>> - data nodes are
824 represented as-if their statements were inlined in target.
825 See <<augment-same-module>> for details & examples.
826 * <<augment-other-module, target node in other module as augment>> - interface representing
827 augmentation is generated, child data nodes are generated by rules for
828 <<instantiated-data-node-rules>>.
829 See <<augment-other-module>> for details & examples.
830 `augment` statement targets only instantiated data nodes, so child data nodes
831 representation is always generated.
833 [[augment-same-module]]
834 ==== Augmentation target in same module
836 All data node children are generated as-if they were directly defined inside
837 target node. There are no externally observable artefacts in generated
838 representation of these nodes, which would point out that they were defined
839 using `augment` statement instead of directly inlining them in target node.
841 .Why augment of same module is same as inlining
844 This rule may seems counterintuitive at first sight, but YANG defines
845 backwards compatibility in terms of effective model instead of way how model
846 is represented. `augment` statement, when targeting node in same module is not
847 externally observable and could factored out by inlining these statements.
849 Definition of `augment` statement in YANG also defines different behaviour when
850 target is same module and allows all features as-if this statements were
854 .Augment with target in same module
856 .YANG module written using augmentations
869 .Same module written without need to augment
878 .Same module written with grouping
890 Java representation for all variants
891 [uml, file="augment1.png"]
893 set namespaceSeparator none
896 interface data.top.Foo
898 data.Top o- data.top.Foo
903 [[augment-other-module]]
904 ==== Augmentation target in other module
906 .Augment with target in other module
920 import top { prefix top; }
931 [uml,file="augment2.png"]
933 set namespaceSeparator none
935 interface Augmentable<T>
936 interface Augmentation<T>
938 interface top.data.Top
939 interface foo.data.FooTop {
943 interface foo.data.top.Bar
945 top.data.Top -u-|> Augmentable : T = top.data.Top
946 foo.data.FooTop -u-|> Augmentation : T = top.data.Top
947 top.data.Top o-- foo.data.FooTop
948 foo.data.FooTop o-- foo.data.top.Bar
953 .Multiple augments with same target
967 import top { prefix top; }
984 [uml,file="augment3.png"]
986 set namespaceSeparator none
988 interface Augmentable<T>
989 interface Augmentation<T>
991 interface top.data.Top
992 interface foo.data.FooTop {
997 interface foo.data.top.Bar
998 interface foo.data.top.Baz
1000 top.data.Top -u-|> Augmentable : T = top.data.Top
1001 foo.data.FooTop -u-|> Augmentation : T = top.data.Top
1002 top.data.Top o-- foo.data.FooTop
1003 foo.data.FooTop o-- foo.data.top.Bar
1004 foo.data.FooTop o-- foo.data.top.Baz
1009 .Multiple augments with different targets
1027 import target { prefix t; }
1029 augment "/t:first" {
1035 augment "/t:second" {
1044 [uml, file="augment4.png"]
1046 set namespaceSeparator none
1048 interface Augmentable<T>
1049 interface Augmentation<T>
1051 interface target.data.First
1052 interface target.data.Second
1054 interface foo.data.FooFirst {
1057 interface foo.data.FooSecond {
1061 interface foo.data.first.Bar
1062 interface foo.data.second.Baz
1064 target.data.First -u-|> Augmentable : T = target.data.First
1065 target.data.Second -u-|> Augmentable : T = target.data.Second
1067 foo.data.FooFirst -u-|> Augmentation : T = target.data.First
1068 foo.data.FooSecond -u-|> Augmentation : T = target.data.Second
1071 target.data.First o-- foo.data.FooFirst
1072 target.data.Second o-- foo.data.FooSecond
1074 foo.data.FooFirst o-- foo.data.first.Bar
1075 foo.data.FooSecond o-- foo.data.second.Baz
1093 grouping key.grp.nodes.node.<nodeidentifier>
1095 instantiated key.data.nodes.node.<nodeidentifier>