797750c68cb0ffb438183c592cb3badb36179acb
[mdsal.git] / binding2 / mdsal-binding2-spec / src / site / asciidoc / binding-2.adoc
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
4 :toc:
5 :toclevels: 4
6
7 == Introduction
8
9 === Terminology
10
11 Namespace::
12   naming space, in which all identifiers needs to be unique
13 identifiers.
14 Data Node::
15 Data Tree::
16 Instance Identifier::
17 Instantiated Data Node::
18 Instantiated Data Tree::
19 Transfer Object::
20 Builder::
21   builder
22
23 === YANG Identifiers Mapping
24
25 Every non-Java char in identifier is converted to Java char by its unicode name http://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.8
26 JAVA SE SPECIFICATIONS - Identifiers. This mapping solves various issues from Binding Specification v1, which led to compilation issues.
27
28 There are special types of mapping non-java chars to original identifiers according to specific Java type:
29
30 * class, enum, interface
31
32 ** without special separator
33 the first character of identifier, any other first character of identifier part mapped by
34 ** non-Java char name from unicode and char in identifier behind non-java char name are converting to upper case
35
36  examples:
37  example* - ExampleAsterisk
38  example*example - ExampleAserisksExample
39  \example - ReverseSolidusExample
40  1example - DigitOneExample
41  example1 - Example1
42  int - IntReservedKeyword
43  con - ConReservedKeyword
44
45 * enum value, constant
46 ** used underscore as special separator
47 ** converted identifier to upper case
48
49  examples:
50  example* - EXAMPLE_ASTERISK
51  example*example - EXAMPLE_ASTERISK_EXAMPLE
52  \example - REVERSE_SOLIDUS_EXAMPLE
53  1example - DIGIT_ONE_EXAMPLE
54  example1 - EXAMPLE1
55  int - INT_RESERVED_KEYWORD
56  con - CON_RESERVED_KEYWORD
57
58 * method, variable
59 ** without special separator
60 ** the first character of identifier is converting to lower case
61 ** any other first character of identifier part mapped by non-Java char name from unicode and char in identifier behind non-java char name are converting to upper case
62
63  examples:
64  example* - exampleAsterisk
65  example*example - exampleAserisksExample
66  \example - reverseSolidusExample
67  1example - digitOneExample
68  example1 - example1
69  int - intReservedKeyword
70  con - conReservedKeyword
71
72 * package - full package name - https://docs.oracle.com/javase/tutorial/java/package/namingpkgs.html
73 ** parts of package name are separated by dots
74 ** parts of package name are converting to lower case
75 ** if parts of package name are reserved Java or Windows keywords, such as 'int' the suggested convention is to add an underscore to keyword
76 ** dash is parsed as underscore according to https://docs.oracle.com/javase/tutorial/java/package/namingpkgs.html
77
78  examples:
79  org.example* - org.exampleasterisk
80  org.example*example - org.exampleasteriskexample
81  org.example - org.reversesolidusexample
82  org.1example - org.digitoneexample
83  org.example1 - org.example1
84  org.int - org.int_
85  org.con - org.con_
86  org.foo-cont - org.foo_cont
87
88 ==== Special case - '-' in identifiers
89 There is special case in CLASS, INTERFACE, ENUM, ENUM VALUE, CONSTANT, METHOD and VARIABLE if
90 identifier contains single dash - then the converter ignores the single dash in the way of the
91 non-java chars. In other way, if dash is the first or the last char in the identifier or there is
92 more dashes in a row in the identifier, then these dashes are converted as non-java chars.
93
94 Example:
95
96 * class, enum, interface
97
98  foo-cont - FooCont
99  foo--cont - FooHyphenMinusHyphenMinusCont
100  -foo - HyphenMinusFoo
101  foo- - FooHyphenMinus
102
103 * enum value, constant
104
105  foo-cont - FOO_CONT
106  foo--cont - FOO_HYPHEN_MINUS_HYPHEN_MINUS_CONT
107  -foo - HYPHEN_MINUS_FOO
108  foo- - FOO_HYPHEN_MINUS
109
110 * method, variable
111
112  foo-cont - fooCont
113  foo--cont - fooHyphenMinusHyphenMinusCont
114  -foo - hyphenMinusFoo
115  foo- - fooHyphenMinus
116
117 ==== Special case - same class (or enum or interface) names with different camel cases
118 Next special case talks about normalizing class name which already exists in package - but with
119 different camel cases (foo, Foo, fOo, ...). To every next classes with same names will by added
120 their actual rank (serial number), except the first one. This working for CLASS, ENUM and
121 INTEFACE java identifiers. If there exist the same ENUM VALUES in ENUM (with different camel
122 cases), then it's parsed with same logic like CLASSES, ENUMS and INTERFACES but according to list
123 of pairs of their ENUM parent. Example:
124
125 * class, enum, interface
126
127  package name org.example, class (or interface or enum) Foo - normalized to Foo
128  package name org.example, class (or interface or enum) fOo - normalized to Foo1
129
130 * enum value
131
132  type enumeration {
133      enum foo;
134      enum Foo;
135  }
136  YANG enum values will be mapped to 'FOO' and 'FOO_1' Java enum values.
137
138
139 === Binding Specification v2 Concepts
140
141 <<Instantiable>>::
142   Represent node, which is instantiable by users as a part of notification,
143   rpc, action or data tree.
144 <<TreeNode>>::
145   Represents node, which is part of instantiated data tree, this interface
146   is not used directly, but rather via <<TreeChildNode>>. See <<instantiated-data-tree-rules>>
147   for more information.
148 <<TreeRoot>>::
149   Represents virtual root of instantiated data tree.
150 <<TreeChildNode>>::
151   Represents node, which is part of instantiated data tree and is not root of
152   data tree.
153 <<Augmentable>>::
154   Represents instantiated node, which is subjectible to be extended / augmented
155   by `augment` statement from external module.
156 <<Augmentation>>::
157   Represents extension to instantiated node, which is introduced from different
158   model than instantiated node.
159 <<InstanceIdentifier>>::
160   Unique identifier of node / subtree in data tree, which provides unambiguous
161   information, how to reference node / subtree in Instantiated Data Tree.
162
163
164 [cols="6"]
165 |===
166 .2+|Statement .2+| In groupings 3+| Instantiable .2+| Augmentable
167 | In Data | In RPC | In Notification
168
169 | `grouping` | Yes | No | No | No | No
170
171 | `container` | Yes | Yes | Yes | Yes | Yes
172
173 | `leaf` | Yes | Yes | Yes | Yes | No
174
175 | `leaf-list` | Yes | Yes | Yes | Yes | No
176
177 | `list` | Yes | Yes | Yes | Yes | Yes
178
179 | `anydata` | Yes | Yes | Yes | Yes | No
180
181 | `anyxml` | Yes | Yes | Yes | Yes | No
182
183 | `choice` | Yes | Yes | Yes | Yes | Yes
184
185 | `case` | Yes | Yes | Yes | Yes | Yes
186
187 | `input` | Yes | No | Yes | No | Yes
188
189 | `output` | Yes | No | Yes | No | Yes
190
191 | `notification` | Yes | No | No | Yes | Yes
192
193 |===
194
195 == Namespaces
196
197 YANG defines several namespaces and naming space of YANG is wider then applicable
198 namespace of JAVA language. In order to decrease conflicts between various
199 YANG-defined namespaces and classes introduced by Binding Specification, it
200 is needed to:
201
202 * separate namespaces by Java package hierarchy
203 ** each namespace must define rules how to construct package name, which
204    will not conflict with other namespace
205 * if multiple classes are generated for YANG statement they need to be in separate
206   packages to decrease possible conflicts with siblings.
207 * if Binding Specification introduces new concepts, which does not have explicit
208   namespace rules in YANG, these concepts needs to be in their own, separate
209   namespaces, in order to not conflict on valid YANG namespace items.
210
211
212 This rules allows to identify two types of namespaces:
213
214 .Namespace types by source of namespace
215 YANG namespace::
216   Naming space explicitly defined in YANG specification, which needs to be
217   explicitly supported in order to prevent naming conflicts.
218 Binding namespace::
219   Naming space introduced by Binding Specification for additional properties
220   and functionality of Binding Specification. This namespaces needs to be separate
221   from YANG namespaces in order to not have naming conflict with YANG-derived.
222
223
224 Binding Specification v2 uses following namespaces:
225
226 .Concrete namespaces used in Binding Specification
227 <<module-namespace>>::
228   YANG namespace containing representation for all modules.
229 <<identity-namespace>>::
230   YANG namespace containing representation for all `identity` statements. Identities
231   needs to be separated to prevent naming conflict between Grouping, Data, Type
232   namespaces.
233 <<type-namespace>>::
234   YANG namespace containing representation for all `typedef` statements and
235   annonymous definitions of `union`, `enumeration` and `bits` types. Types needs
236   to be seperated to prevent naming conflict between Identity, Grouping and Data
237   namespaces.
238 <<grouping-namespace>>::
239   YANG namespace containing representation for all `grouping` statements and their
240   child data node statements. Groupings needs to be separated to prevent naming
241   conflict between Identity, Type, Data namespaces.
242 <<key-namespace>>::
243   Binding namespace containing representation for all `key` statements.
244   Representations of key statements needs to be in separate namespace, since it is not defined
245   in YANG specification.
246 <<data-namespace>>::
247   YANG namespace containing representation of instantiated data tree.
248   Data needs to be separated to prevent naming conflict between Identity, Type,
249   Grouping namespaces.
250 <<dto-namespace>>::
251   Binding namespace containing Transfer Objects and Builders representing
252   instantiated data tree items.
253
254 NOTE: Most of Binding Namespaces were introduced to decrease possibility of name
255 conflict between concepts defined in YANG and additional concepts introduced
256 by Binding Specification.
257
258 === Package hierarchy
259
260 .Package hierarchy for model
261 [cols="1,1,4"]
262 |===
263 |Namespace | Package  | Description
264
265 | <<identity-namespace, Identity>> | `ident`
266 | flat package containing representation for all `identity`
267
268 .3+| <<type-namespace, Type>> | `type`
269 | flat package containing representations for all top-level
270    `typedef` statements
271
272 | `type.grp`
273 | path-based package hierarchy containing representation
274   for `typedef` statements nested in grouping statements, or anonymous types
275   requiring code generation defined inside groupings
276
277 | `type.data`
278 | path-based package hierarchy containing representation
279   for `typedef` statements nested in grouping statements, or anonymous types
280   requiring code generation defined inside instantiated data nodes
281
282 |  <<key-namespace, Key>> | `key`
283 | path-based package hierarchy containing representation
284   of key statements for grouping code generation defined inside groupings
285
286 | <<grouping-namespace, Grouping>> | `grp`
287 | path-based package hierarchy containing representation
288   for `grouping` statements and data node statements nested in these groupings
289
290 | <<data-namespace, Data>> | `data`
291 | path-based package hierarchy containing representation of instantiated
292   data nodes
293
294 | <<dto-namespace, Builder>> | `dto`
295 | path-based package hierarchy containing Tranfer Objects and their builders
296   for instantiated data nodes
297 |===
298
299 [[module-namespace]]
300 === Module Namespace
301
302
303
304 [[identity-namespace]]
305 === Identity Namespace
306
307
308 [[type-namespace]]
309 === Type Namespace
310
311 [[grouping-namespace]]
312 === Grouping Namespace
313
314 [[key-namespace]]
315 === Key Namespace
316
317 [[data-namespace]]
318 === Data Namespace
319
320 [[dto-namespace]]
321 === Builder Namespace
322
323 == Generic rules
324
325 [[class-naming]]
326 === Class Naming
327
328 [[subpackage-structure]]
329 === Subpackage Naming
330
331 [[accessor-rules]]
332 === Accessor rules
333
334 == Type rules
335
336 === `typedef` statement
337
338 ==== Globally scoped `typedef`
339
340 ==== Subtree scoped `typedef`
341
342 Subtree scoped `typedef` statement is type definition, which is not substatement
343 of `module` or `submodule`, and is only visible to child elements of parent
344 statement.
345
346 * Representation is generated in Type namespace according to following rules:
347
348
349 === Type mapping
350
351 YANG types does not provide single, simple model of behaviour - some times
352 exhibits special properties to extensibility or limiting scope of valid values
353 when type is derived
354
355 ////
356 .Base types and their behaviours
357 |===
358 | YANG Type | Description | Java Mapping
359
360
361 | `binary`              | Any binary data | `Binary`?
362 | `bits`                | A set of bits or flags | Custom class
363 | `boolean`             | `true` or `false` | `Boolean`
364 | `decimal64`           | 64-bit signed decimal number  | No
365 | `empty`               | A leaf that does not have any value | No
366 | `enumeration`         | Enumerated strings | No
367 | `identityref`         | A reference to an abstract identity | Yes
368 | `instance-identifier` | References a data tree node | Yes
369 | `int8`                | 8-bit signed integer | No
370 | `int16`               | 16-bit signed integer | No
371 | `int32`               | 32-bit signed integer | No
372 | `int64`               | 64-bit signed integer | No
373 | `leafref`             | A reference to a leaf instance | Maybe
374 | `string`              | Human-readable string | No
375 | `uint8`               | 8-bit unsigned integer | No
376 | `uint16`              | 16-bit unsigned integer | No
377 | `uint32`              | 32-bit unsigned integer | No
378 | `uint64`              | 64-bit unsigned integer | No
379 | `union`               | Choice of member types | Maybe
380
381 |===
382 FIXME: Finalize table
383 ////
384
385 ==== `boolean` type
386 ==== `empty` type
387 ==== `int8` type
388 ==== `int16` type
389 ==== `int32` type
390 ==== `int64` type
391 ==== `uint8` type
392 ==== `uint16` type
393 ==== `uint32` type
394 ==== `uint64` type
395 ==== `string` type
396 ==== `binary` type
397 ==== `enumeration` type
398 ==== `bits` type
399
400 ==== `identityref` type
401 ==== `instance-identifier` type
402
403 ==== `leafref` type
404 ==== `union` type
405
406 [[data-node-rules]]
407 == Data Node rules
408
409 Data nodes could be separated into two distinct groups, based on presence of
410 child nodes:
411
412 Leaf node::
413   Node, which according to YANG schema does not have child nodes, is leaf node
414   and carries only simple value.
415 Interior node::
416   Node, which according to YANG schema may have child nodes, node itself does not
417   carry values, values are stored in descendant leaf nodes.
418
419 === `leaf` Statement
420
421 === `leaf-list` Statement
422
423
424 === `container` Statement
425
426 Builders will be located in package "dto"
427
428
429 [source,yang]
430 ----
431 container foo {
432 }
433
434 container foo-builder {
435 }
436 ----
437
438 [uml, file="container-builder.png"]
439 --
440 set namespaceSeparator none
441
442 interface data.Foo {
443 }
444
445 interface data.FooBuilder {
446 }
447 --
448
449 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.
450
451 [source,yang]
452 ----
453 container example-outter {
454     container example-inner {
455         leaf example {
456             type string;
457         }
458     }
459 }
460 ----
461
462 === `list` Statement
463
464 ==== Keyed List
465
466 [source,yang]
467 ----
468 list foo {
469     key identifier key fookey;
470     leaf identifier {
471         type union {
472             type string;
473         }
474     }
475
476     leaf key {
477         type string;
478     }
479
480     leaf fookey {
481         type string;
482     }
483 }
484 ----
485 [uml, file="list-Keyed.png"]
486 --
487 set namespaceSeparator none
488
489 interface data.Foo {
490 }
491
492 interface key.foo.FooIdentifier {
493 }
494
495 interface key.foo.FooKey {
496 }
497
498 interface key.foo.FooFooKey {
499 }
500
501 interface type.foo.identifier.IdentifierUnion {
502 }
503
504 data.Foo o- key.foo.FooIdentifier
505 data.Foo o- key.foo.FooKey
506 data.Foo o- key.foo.FooFooKey
507 key.foo.FooIdentifier o- type.foo.identifier.IdentifierUnion
508 --
509
510 ==== List without Key
511
512 === `choice` Statement
513
514 === `case` Statement
515
516 [source,yang]
517 ----
518 container top {
519   choice base {
520     case foo {
521       container foo;
522     }
523     case bar {
524       leaf bar { type string; }
525     }
526   }
527 }
528 ----
529
530 [uml, file="case.png"]
531 --
532 set namespaceSeparator none
533
534 package spec {
535   interface Choice
536   interface Case
537 }
538
539 interface data.Top {
540   + getBase() : data.top.Base;
541 }
542 interface data.top.Base
543 interface data.top.base.Foo {
544   + getFoo() : data.top.base.foo.Foo
545 }
546 interface data.top.base.foo.Foo
547 interface data.top.base.Bar {
548   + getBar() : String
549 }
550
551 data.top.Base -u-|> Choice
552 data.top.base.Foo -u-|> Case
553 data.top.base.Bar -u-|> Case
554
555 data.top.base.Foo -u-|> data.top.Base
556 data.top.base.Bar -u-|> data.top.Base
557
558 data.Top o- data.top.Base
559 data.top.base.Foo o- data.top.base.foo.Foo
560 --
561
562 == Specific rules
563
564 [[instantiated-data-node-rules]]
565 === Instantiated Data Node Rules
566
567 ////
568 FIXME: Do we need section per type, or should just general rules be described.
569 ////
570
571 ==== `container` Statement
572
573 ////
574 FIXME: Here should be Augmentable & Instantiated
575 ////
576
577 ==== `leaf` Statement
578
579 ==== `leaf-list` Statement
580
581 ==== `choice` Statement
582
583 ==== `case` Statement
584
585 ////
586 FIXME: Here should be Augmentable & Instantiated
587 ////
588
589 ==== `list` Statement
590
591 ////
592 FIXME: Here should be Augmentable & Instantiated, List signature uses concrete
593 interfaces
594 ////
595
596 ==== `input` Statement
597
598 ////
599 FIXME: Here should be Augmentable & Instantiated
600 ////
601
602 ==== `output` Statement
603
604 ////
605 FIXME: Here should be Augmentable & Instantiated
606 ////
607
608 ==== `notification` Statement
609
610 ////
611 FIXME: Here should be Augmentable & Instantiated
612 ////
613
614 [[instantiated-data-tree-rules]]
615 === Instantiated Data Tree Rules
616
617
618 ==== `container` Statement
619
620 ////
621 FIXME: Here should be Augmentable & Instantied & ChildDataNode
622 ////
623
624
625 ==== `leaf` Statement
626
627 ==== `leaf-list` Statement
628
629 ==== `case` Statement
630
631 ////
632 FIXME: Here should be Augmentable & Instantied & ChildDataNode
633 ////
634
635 ==== `list` Statement
636
637 ////
638 FIXME: Here should be Augmentable & Instantied & ChildDataNode
639 ////
640
641 === `grouping` Statement
642
643 * `grouping` statement is represented by `interface`
644 ** interface name is generated according to <<class-naming>> with suffix `Grouping`
645 * Representations of `grouping` statements are generated into <<grouping-namespace>>
646 * schema nodes under grouping are represented by `interface` and are generated
647   into <<grouping-namespace>> + name of grouping
648 ** getters (accessors) from parent nodes are generated according to <<accessor-rules>>
649 ** class name is generated according to <<class-naming>> with suffix `Data`
650 ** schema nodes does not follow <<instantiated-data-tree-rules>>, these interfaces
651    are used only in instantiated data tree.
652
653 .Simple Grouping
654 ====
655 .YANG Snippet
656 [source, yang]
657 ----
658 grouping simple  { <1>
659   container foo; <2>
660   leaf bar { type string;} <3>
661 }
662 ----
663 <1> Is represented by interface `grp.SimpleGrouping`
664 <2> Is represented by interface `grp.simple.FooData` and getter in `grp.SimpleGrouping`
665     with signature `public grp.simple.FooData getFoo();`
666 <3> Is represented by getter in `grp.SimpleGrouping` with signature `public String getBar()`
667
668 [uml, file="grouping1.png"]
669 --
670 interface grp.SimpleGrouping {
671   + getBar() : String
672   + getFoo() : grp.simple.FooData
673 }
674 interface grp.simple.FooData
675 grp.SimpleGrouping o- grp.simple.FooData
676 --
677 ====
678
679 ==== Data Node substatements
680
681 Representations of data node substatements are generated according to rules
682 described in <<data-node-rules>> with following changes:
683 ////
684 MS: proposed interface names:
685 case - <NodeName>Case
686 choice - <<NodeName>Choice
687 container, list - <NodeName>
688 ////
689 ////
690 MC: I would keep Data suffix, but idea about distinguishing cases and choices
691 is to think about
692 ////
693 * Interface names for `case`, `choice`, `container` and `list`, is suffixed by
694   `Data` suffix, in order to not conflict with same named groupings inside same
695   package
696 ** Getters in parent node, are still generated without `Data` suffix, so
697    the getter signature is in form `FooData getFoo()`
698 **  If return value of getter is constructed using generics (eg. `list`)
699     instead of signature `List<ListItem>` or `Map<ListKey, ListItem>`, wildcarded
700     `? extends ListItem` generic argument are used to allow for overriding during
701     <<uses-statement,instantation of grouping>>.
702
703
704 ==== `list` substatement
705
706 ////
707 FIXME: Add reasoning / examples for need to use ? extends, instead of directly
708 using generics.
709 ////
710
711 ==== `leaf-list` susbstatement
712
713 ////
714 FIXME: Add reasoning / examples for need to use ? extends, instead of directly
715 using generics for types, which may need instantiation
716 ////
717
718 [[uses-statement]]
719 === `uses` Statement
720
721 * `uses` statement triggers interface of parent statement to extend (implement)
722   interface of `grouping` referenced by `uses` argument.
723 * As in YANG `uses` statement triggers instatiation of data children of `grouping`
724   which will result in generation of these children as-if they were direct
725   children of parent statement
726 **  data node children are generated according to rules defined for parent statement.
727     Different rules apply based on parent type (instantiated data tree, `input`,
728     `output` or `grouping`)
729 **  interfaces generated for data children extends (implements) interfaces for
730     same children generated for referenced `grouping`
731
732 .Simple Grouping and Uses
733 ====
734 .YANG Snippet
735 [source, yang]
736 ----
737 grouping simple  {
738   container foo;
739   leaf bar { type string;}
740 }
741
742 container top {
743   uses simple;
744 }
745 ----
746 [uml, file="grouping2.png"]
747 --
748 set namespaceSeparator none
749
750 interface grp.SimpleGrouping {
751   + getBar() : String
752   + getFoo() : grp.simple.FooData
753 }
754 interface grp.simple.FooData
755 interface data.Top {
756   + getFoo() : data.top.Foo
757 }
758 interface data.top.Foo
759
760 grp.SimpleGrouping o-- grp.simple.FooData
761
762 data.Top o-- data.top.Foo
763 data.Top -|> grp.SimpleGrouping
764 data.top.Foo -|> grp.simple.FooData
765 --
766
767 NOTE: Diagram does not show all details for `data.Top` and `data.top.Foo`, which
768 are based on <<instantiated-data-tree-rules>>
769
770 ====
771
772 .Grouping with Nested Grouping
773 ====
774
775 .YANG Snippet
776 [source, yang]
777 ----
778 grouping with-inner {
779   grouping inner {
780     container cont;
781   }
782   uses inner;
783 }
784
785 container top {
786   uses with-inner;
787 }
788 ----
789
790 [uml, file="grouping3.png"]
791 --
792 set namespaceSeparator none
793
794 interface grp.withinner.inner.ContData
795 interface grp.withinner.InnerGrouping {
796   + getCont() : grp.withinner.inner.ContData
797 }
798
799
800 interface grp.withinner.ContData
801
802 interface grp.WithInnerGrouping {
803   + getCont() : grp.withinner.ContData
804 }
805
806
807 interface data.Top {
808   + getCont() : data.top.Cont
809 }
810
811 interface data.top.Cont {
812
813 }
814 data.Top o-- data.top.Cont : contains
815
816 data.Top -|> grp.WithInnerGrouping
817 data.top.Cont -|> grp.withinner.ContData
818
819 grp.WithInnerGrouping -|> grp.withinner.InnerGrouping : uses (implements)
820 grp.WithInnerGrouping o-- grp.withinner.ContData : contains
821 grp.withinner.InnerGrouping o-- grp.withinner.inner.ContData : contains
822
823 grp.withinner.ContData -|> grp.withinner.inner.ContData : is concretization of (implements)
824
825 --
826
827 NOTE: Diagram does not show all details for `data.Top`  and `data.top.Cont`, which
828 are based on <<instantiated-data-tree-rules>>
829
830 ====
831
832 [[uses-augment]]
833 ==== `augment` substatement
834
835 .Uses & Augment in instantiated Data Tree
836 ====
837 [source,yang]
838 ----
839 grouping example {
840   container nested {
841     leaf foo {
842       type string;
843     }
844   }
845 }
846
847 container top {
848   uses example {
849     augment nested {
850       container bar {
851       }
852     }
853   }
854 }
855
856 ----
857
858 [uml, file="grouping4.png"]
859 --
860 set namespaceSeparator none
861
862 interface data.Top
863 interface data.top.Nested
864 interface data.top.nested.Bar
865
866 data.Top o-- data.top.Nested
867 data.top.Nested o-- data.top.nested.Bar
868
869 interface grp.ExampleGrouping
870 interface grp.example.NestedData
871
872
873 grp.ExampleGrouping o-- grp.example.NestedData
874
875 data.Top -|> grp.ExampleGrouping
876 data.top.Nested -|> grp.example.NestedData
877 --
878
879 NOTE: Diagram does not show all details for `data.Top`, `data.top.Nested` and
880 `data.top.nested.Bar`, which are based on <<instantiated-data-tree-rules>>
881
882
883 ====
884
885
886 .Uses & Augment in grouping
887 ====
888 [source,yang]
889 ----
890 grouping example {
891   container nested {
892     leaf foo {
893       type string;
894     }
895   }
896 }
897
898 grouping top {
899   uses example {
900     augment nested {
901       container bar {
902       }
903     }
904   }
905 }
906
907 ----
908
909 [uml, file="grouping5.png"]
910 --
911 set namespaceSeparator none
912
913 interface grp.TopGrouping
914 interface grp.top.NestedData
915 interface grp.top.nested.BarData
916
917 grp.TopGrouping o-- grp.top.NestedData
918 grp.top.NestedData o-- grp.top.nested.BarData
919
920 interface grp.ExampleGrouping
921 interface grp.example.NestedData
922
923 grp.ExampleGrouping o-- grp.example.NestedData
924
925 grp.TopGrouping -|> grp.ExampleGrouping
926 grp.top.NestedData -|> grp.example.NestedData
927 --
928
929 ====
930
931 === `augment` statement
932
933 Representation of `augment` statement depends on module in which target node of
934 augment statement is defined
935
936 * <<uses-augment, augment is substatement of uses>> - data nodes are represented
937   as-if their statements were inlined in target node.
938   See <<uses-augment, uses Statement: augment Substatement>> section for details.
939 * <<augment-same-module,target node in same module as augment>> - data nodes are
940   represented as-if their statements were inlined in target.
941   See <<augment-same-module>> for details & examples.
942 * <<augment-other-module, target node in other module as augment>> - interface representing
943   augmentation is generated, child data nodes are generated by rules for
944   <<instantiated-data-node-rules>>.
945   See <<augment-other-module>> for details & examples.
946 `augment` statement targets only instantiated data nodes, so child data nodes
947 representation is always generated.
948
949 [[augment-same-module]]
950 ==== Augmentation target in same module
951
952 All data node children are generated as-if they were directly defined inside
953 target node. There are no externally observable artefacts in generated
954 representation of these nodes, which would point out that they were defined
955 using `augment` statement instead of directly inlining them in target node.
956
957 .Why augment of same module is same as inlining
958 [IMPORTANT]
959 ====
960 This rule may seems counterintuitive at first sight, but YANG defines
961 backwards compatibility in terms of effective model instead of way how model
962 is represented. `augment` statement, when targeting node in same module is not
963 externally observable and could factored out by inlining these statements.
964
965 Definition of `augment` statement in YANG also defines different behaviour when
966 target is same module and allows all features as-if this statements were
967 directly inlined.
968 ====
969
970 .Augment with target in same module
971 ====
972 .YANG module written using augmentations
973 [source,yang]
974 ----
975 container top {
976
977 }
978
979 augment "/top" {
980   container foo {
981
982   }
983 }
984 ----
985 .Same module written without need to augment
986 ----
987 container top {
988   container foo {
989
990   }
991 }
992
993 ----
994 .Same module written with grouping
995 ----
996 grouping a {
997     container foo {
998     }
999 }
1000
1001 container top {
1002     uses a;
1003 }
1004
1005 ----
1006 Java representation for all variants
1007 [uml, file="augment1.png"]
1008 --
1009 set namespaceSeparator none
1010
1011 interface data.Top
1012 interface data.top.Foo
1013
1014 data.Top o- data.top.Foo
1015 --
1016
1017 ====
1018
1019 [[augment-other-module]]
1020 ==== Augmentation target in other module
1021
1022 .Augment with target in other module
1023 ====
1024 [source,yang]
1025 ----
1026 module top {
1027   ...
1028
1029   container top {
1030
1031   }
1032 }
1033
1034 module foo {
1035   ...
1036   import top { prefix top; }
1037   ...
1038   augment "/top:top" {
1039     container bar {
1040
1041     }
1042   }
1043 }
1044
1045 ----
1046
1047 [uml,file="augment2.png"]
1048 --
1049 set namespaceSeparator none
1050
1051 interface Augmentable<T>
1052 interface Augmentation<T>
1053
1054 interface top.data.Top
1055 interface foo.data.FooTop  {
1056   + getBar() : Bar
1057 }
1058
1059 interface foo.data.top.Bar
1060
1061 top.data.Top -u-|> Augmentable : T = top.data.Top
1062 foo.data.FooTop -u-|> Augmentation : T = top.data.Top
1063 top.data.Top o-- foo.data.FooTop
1064 foo.data.FooTop o-- foo.data.top.Bar
1065 --
1066
1067 ====
1068
1069 .Multiple augments with same target
1070 ====
1071 [source,yang]
1072 ----
1073 module top {
1074   ...
1075
1076   container top {
1077
1078   }
1079 }
1080
1081 module foo {
1082   ...
1083   import top { prefix top; }
1084   ...
1085   augment "/top:top" {
1086     container bar {
1087
1088     }
1089   }
1090
1091   augment "/top:top" {
1092     container baz {
1093
1094     }
1095   }
1096 }
1097
1098 ----
1099
1100 [uml,file="augment3.png"]
1101 --
1102 set namespaceSeparator none
1103
1104 interface Augmentable<T>
1105 interface Augmentation<T>
1106
1107 interface top.data.Top
1108 interface foo.data.FooTop {
1109   + getBar() : Bar
1110   + getBaz() : Baz
1111 }
1112
1113 interface foo.data.top.Bar
1114 interface foo.data.top.Baz
1115
1116 top.data.Top -u-|> Augmentable : T = top.data.Top
1117 foo.data.FooTop -u-|> Augmentation : T = top.data.Top
1118 top.data.Top o-- foo.data.FooTop
1119 foo.data.FooTop o-- foo.data.top.Bar
1120 foo.data.FooTop o-- foo.data.top.Baz
1121 --
1122
1123 ====
1124
1125 .Multiple augments with different targets
1126 ====
1127 [source,yang]
1128 ----
1129 module target {
1130   ...
1131
1132   container first {
1133
1134   }
1135
1136   container second {
1137
1138   }
1139 }
1140
1141 module foo {
1142   ...
1143   import target { prefix t; }
1144   ...
1145   augment "/t:first" {
1146     container bar {
1147
1148     }
1149   }
1150
1151   augment "/t:second" {
1152     container baz {
1153
1154     }
1155   }
1156 }
1157
1158 ----
1159
1160 [uml, file="augment4.png"]
1161 --
1162 set namespaceSeparator none
1163
1164 interface Augmentable<T>
1165 interface Augmentation<T>
1166
1167 interface target.data.First
1168 interface target.data.Second
1169
1170 interface foo.data.FooFirst {
1171   + getBar() : Bar
1172 }
1173 interface foo.data.FooSecond {
1174   + getBaz() : Baz
1175 }
1176
1177 interface foo.data.first.Bar
1178 interface foo.data.second.Baz
1179
1180 target.data.First -u-|> Augmentable : T = target.data.First
1181 target.data.Second -u-|> Augmentable : T = target.data.Second
1182
1183 foo.data.FooFirst -u-|> Augmentation : T = target.data.First
1184 foo.data.FooSecond -u-|> Augmentation : T = target.data.Second
1185
1186
1187 target.data.First o-- foo.data.FooFirst
1188 target.data.Second o-- foo.data.FooSecond
1189
1190 foo.data.FooFirst o-- foo.data.first.Bar
1191 foo.data.FooSecond o-- foo.data.second.Baz
1192 --
1193 ====
1194
1195 .Key in grouping
1196 ====
1197 [source,yang]
1198 ----
1199 grouping nodes {
1200     list node {
1201         key id;
1202         leaf id {
1203             type string;
1204         }
1205     }
1206 }
1207
1208 ----
1209 grouping key.grp.nodes.node.<nodeidentifier>
1210
1211 instantiated key.data.nodes.node.<nodeidentifier>