b5ec36ad131d70ae1d76ee548960112cc519456e
[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     leaf boo-non-key {
485         type string;
486     }
487 }
488 ----
489 [uml, file="list-Keyed.png"]
490 --
491 set namespaceSeparator none
492
493 interface data.Foo {
494     + getFooIdentifier() : key.foo.FooIdentifier
495     + getFooKey() : key.foo.FooKey
496     + getFooFooKey() : key.foo.FooFooKey
497     + getKey() : key.foo.wrapper.FooKey
498 }
499
500 interface key.foo.wrapper.FooKey {
501     + getFooIdentifier() : key.foo.FooIdentifier
502     + getFooKey() : key.foo.FooKey
503     + getFooFooKey() : key.foo.FooFooKey
504 }
505
506 interface type.foo.identifier.IdentifierUnion
507 interface key.foo.FooIdentifier {
508     + getIdentifier() : type.foo.identifier.IdentifierUnion
509 }
510
511 interface key.foo.FooKey {
512     + getKey() : String
513 }
514
515 interface key.foo.FooFooKey {
516     + getFooKey() : String
517 }
518
519 interface data.foo.FooBooNonKey {
520     + getBooNonKey() : String
521 }
522
523 key.foo.FooIdentifier o- type.foo.identifier.IdentifierUnion
524
525 data.foo.FooBooNonKey -u-|> data.Foo
526 key.foo.wrapper.FooKey -u-|> data.Foo
527
528 key.foo.FooKey -u-|> data.Foo
529 key.foo.FooFooKey -u-|> data.Foo
530 key.foo.FooIdentifier -u-|> data.Foo
531
532 key.foo.FooKey -u-|> key.foo.wrapper.FooKey
533 key.foo.FooFooKey -u-|> key.foo.wrapper.FooKey
534 key.foo.FooIdentifier -u-|> key.foo.wrapper.FooKey
535 --
536
537 ==== List without Key
538
539 === `choice` Statement
540
541 === `case` Statement
542
543 [source,yang]
544 ----
545 container top {
546   choice base {
547     case foo {
548       container foo;
549     }
550     case bar {
551       leaf bar { type string; }
552     }
553   }
554 }
555 ----
556
557 [uml, file="case.png"]
558 --
559 set namespaceSeparator none
560
561 package spec {
562   interface Choice
563   interface Case
564 }
565
566 interface data.Top {
567   + getBase() : data.top.Base;
568 }
569 interface data.top.Base
570 interface data.top.base.Foo {
571   + getFoo() : data.top.base.foo.Foo
572 }
573 interface data.top.base.foo.Foo
574 interface data.top.base.Bar {
575   + getBar() : String
576 }
577
578 data.top.Base -u-|> Choice
579 data.top.base.Foo -u-|> Case
580 data.top.base.Bar -u-|> Case
581
582 data.top.base.Foo -u-|> data.top.Base
583 data.top.base.Bar -u-|> data.top.Base
584
585 data.Top o- data.top.Base
586 data.top.base.Foo o- data.top.base.foo.Foo
587 --
588
589 == Specific rules
590
591 [[instantiated-data-node-rules]]
592 === Instantiated Data Node Rules
593
594 ////
595 FIXME: Do we need section per type, or should just general rules be described.
596 ////
597
598 ==== `container` Statement
599
600 ////
601 FIXME: Here should be Augmentable & Instantiated
602 ////
603
604 ==== `leaf` Statement
605
606 ==== `leaf-list` Statement
607
608 ==== `choice` Statement
609
610 ==== `case` Statement
611
612 ////
613 FIXME: Here should be Augmentable & Instantiated
614 ////
615
616 ==== `list` Statement
617
618 ////
619 FIXME: Here should be Augmentable & Instantiated, List signature uses concrete
620 interfaces
621 ////
622
623 ==== `input` Statement
624
625 ////
626 FIXME: Here should be Augmentable & Instantiated
627 ////
628
629 ==== `output` Statement
630
631 ////
632 FIXME: Here should be Augmentable & Instantiated
633 ////
634
635 ==== `notification` Statement
636
637 ////
638 FIXME: Here should be Augmentable & Instantiated
639 ////
640
641 [[instantiated-data-tree-rules]]
642 === Instantiated Data Tree Rules
643
644
645 ==== `container` Statement
646
647 ////
648 FIXME: Here should be Augmentable & Instantied & ChildDataNode
649 ////
650
651
652 ==== `leaf` Statement
653
654 ==== `leaf-list` Statement
655
656 ==== `case` Statement
657
658 ////
659 FIXME: Here should be Augmentable & Instantied & ChildDataNode
660 ////
661
662 ==== `list` Statement
663
664 ////
665 FIXME: Here should be Augmentable & Instantied & ChildDataNode
666 ////
667
668 === `grouping` Statement
669
670 * `grouping` statement is represented by `interface`
671 ** interface name is generated according to <<class-naming>> with suffix `Grouping`
672 * Representations of `grouping` statements are generated into <<grouping-namespace>>
673 * schema nodes under grouping are represented by `interface` and are generated
674   into <<grouping-namespace>> + name of grouping
675 ** getters (accessors) from parent nodes are generated according to <<accessor-rules>>
676 ** class name is generated according to <<class-naming>> with suffix `Data`
677 ** schema nodes does not follow <<instantiated-data-tree-rules>>, these interfaces
678    are used only in instantiated data tree.
679
680 .Simple Grouping
681 ====
682 .YANG Snippet
683 [source, yang]
684 ----
685 grouping simple  { <1>
686   container foo; <2>
687   leaf bar { type string;} <3>
688 }
689 ----
690 <1> Is represented by interface `grp.SimpleGrouping`
691 <2> Is represented by interface `grp.simple.FooData` and getter in `grp.SimpleGrouping`
692     with signature `public grp.simple.FooData getFoo();`
693 <3> Is represented by getter in `grp.SimpleGrouping` with signature `public String getBar()`
694
695 [uml, file="grouping1.png"]
696 --
697 interface grp.SimpleGrouping {
698   + getBar() : String
699   + getFoo() : grp.simple.FooData
700 }
701 interface grp.simple.FooData
702 grp.SimpleGrouping o- grp.simple.FooData
703 --
704 ====
705
706 ==== Data Node substatements
707
708 Representations of data node substatements are generated according to rules
709 described in <<data-node-rules>> with following changes:
710 ////
711 MS: proposed interface names:
712 case - <NodeName>Case
713 choice - <<NodeName>Choice
714 container, list - <NodeName>
715 ////
716 ////
717 MC: I would keep Data suffix, but idea about distinguishing cases and choices
718 is to think about
719 ////
720 * Interface names for `case`, `choice`, `container` and `list`, is suffixed by
721   `Data` suffix, in order to not conflict with same named groupings inside same
722   package
723 ** Getters in parent node, are still generated without `Data` suffix, so
724    the getter signature is in form `FooData getFoo()`
725 **  If return value of getter is constructed using generics (eg. `list`)
726     instead of signature `List<ListItem>` or `Map<ListKey, ListItem>`, wildcarded
727     `? extends ListItem` generic argument are used to allow for overriding during
728     <<uses-statement,instantation of grouping>>.
729
730
731 ==== `list` substatement
732
733 ////
734 FIXME: Add reasoning / examples for need to use ? extends, instead of directly
735 using generics.
736 ////
737
738 ==== `leaf-list` susbstatement
739
740 ////
741 FIXME: Add reasoning / examples for need to use ? extends, instead of directly
742 using generics for types, which may need instantiation
743 ////
744
745 [[uses-statement]]
746 === `uses` Statement
747
748 * `uses` statement triggers interface of parent statement to extend (implement)
749   interface of `grouping` referenced by `uses` argument.
750 * As in YANG `uses` statement triggers instatiation of data children of `grouping`
751   which will result in generation of these children as-if they were direct
752   children of parent statement
753 **  data node children are generated according to rules defined for parent statement.
754     Different rules apply based on parent type (instantiated data tree, `input`,
755     `output` or `grouping`)
756 **  interfaces generated for data children extends (implements) interfaces for
757     same children generated for referenced `grouping`
758
759 .Simple Grouping and Uses
760 ====
761 .YANG Snippet
762 [source, yang]
763 ----
764 grouping simple  {
765   container foo;
766   leaf bar { type string;}
767 }
768
769 container top {
770   uses simple;
771 }
772 ----
773 [uml, file="grouping2.png"]
774 --
775 set namespaceSeparator none
776
777 interface grp.SimpleGrouping {
778   + getBar() : String
779   + getFoo() : grp.simple.FooData
780 }
781 interface grp.simple.FooData
782 interface data.Top {
783   + getFoo() : data.top.Foo
784 }
785 interface data.top.Foo
786
787 grp.SimpleGrouping o-- grp.simple.FooData
788
789 data.Top o-- data.top.Foo
790 data.Top -|> grp.SimpleGrouping
791 data.top.Foo -|> grp.simple.FooData
792 --
793
794 NOTE: Diagram does not show all details for `data.Top` and `data.top.Foo`, which
795 are based on <<instantiated-data-tree-rules>>
796
797 ====
798
799 .Grouping with Nested Grouping
800 ====
801
802 .YANG Snippet
803 [source, yang]
804 ----
805 grouping with-inner {
806   grouping inner {
807     container cont;
808   }
809   uses inner;
810 }
811
812 container top {
813   uses with-inner;
814 }
815 ----
816
817 [uml, file="grouping3.png"]
818 --
819 set namespaceSeparator none
820
821 interface grp.withinner.inner.ContData
822 interface grp.withinner.InnerGrouping {
823   + getCont() : grp.withinner.inner.ContData
824 }
825
826
827 interface grp.withinner.ContData
828
829 interface grp.WithInnerGrouping {
830   + getCont() : grp.withinner.ContData
831 }
832
833
834 interface data.Top {
835   + getCont() : data.top.Cont
836 }
837
838 interface data.top.Cont {
839
840 }
841 data.Top o-- data.top.Cont : contains
842
843 data.Top -|> grp.WithInnerGrouping
844 data.top.Cont -|> grp.withinner.ContData
845
846 grp.WithInnerGrouping -|> grp.withinner.InnerGrouping : uses (implements)
847 grp.WithInnerGrouping o-- grp.withinner.ContData : contains
848 grp.withinner.InnerGrouping o-- grp.withinner.inner.ContData : contains
849
850 grp.withinner.ContData -|> grp.withinner.inner.ContData : is concretization of (implements)
851
852 --
853
854 NOTE: Diagram does not show all details for `data.Top`  and `data.top.Cont`, which
855 are based on <<instantiated-data-tree-rules>>
856
857 ====
858
859 [[uses-augment]]
860 ==== `augment` substatement
861
862 .Uses & Augment in instantiated Data Tree
863 ====
864 [source,yang]
865 ----
866 grouping example {
867   container nested {
868     leaf foo {
869       type string;
870     }
871   }
872 }
873
874 container top {
875   uses example {
876     augment nested {
877       container bar {
878       }
879     }
880   }
881 }
882
883 ----
884
885 [uml, file="grouping4.png"]
886 --
887 set namespaceSeparator none
888
889 interface data.Top
890 interface data.top.Nested
891 interface data.top.nested.Bar
892
893 data.Top o-- data.top.Nested
894 data.top.Nested o-- data.top.nested.Bar
895
896 interface grp.ExampleGrouping
897 interface grp.example.NestedData
898
899
900 grp.ExampleGrouping o-- grp.example.NestedData
901
902 data.Top -|> grp.ExampleGrouping
903 data.top.Nested -|> grp.example.NestedData
904 --
905
906 NOTE: Diagram does not show all details for `data.Top`, `data.top.Nested` and
907 `data.top.nested.Bar`, which are based on <<instantiated-data-tree-rules>>
908
909
910 ====
911
912
913 .Uses & Augment in grouping
914 ====
915 [source,yang]
916 ----
917 grouping example {
918   container nested {
919     leaf foo {
920       type string;
921     }
922   }
923 }
924
925 grouping top {
926   uses example {
927     augment nested {
928       container bar {
929       }
930     }
931   }
932 }
933
934 ----
935
936 [uml, file="grouping5.png"]
937 --
938 set namespaceSeparator none
939
940 interface grp.TopGrouping
941 interface grp.top.NestedData
942 interface grp.top.nested.BarData
943
944 grp.TopGrouping o-- grp.top.NestedData
945 grp.top.NestedData o-- grp.top.nested.BarData
946
947 interface grp.ExampleGrouping
948 interface grp.example.NestedData
949
950 grp.ExampleGrouping o-- grp.example.NestedData
951
952 grp.TopGrouping -|> grp.ExampleGrouping
953 grp.top.NestedData -|> grp.example.NestedData
954 --
955
956 ====
957
958 === `augment` statement
959
960 Representation of `augment` statement depends on module in which target node of
961 augment statement is defined
962
963 * <<uses-augment, augment is substatement of uses>> - data nodes are represented
964   as-if their statements were inlined in target node.
965   See <<uses-augment, uses Statement: augment Substatement>> section for details.
966 * <<augment-same-module,target node in same module as augment>> - data nodes are
967   represented as-if their statements were inlined in target.
968   See <<augment-same-module>> for details & examples.
969 * <<augment-other-module, target node in other module as augment>> - interface representing
970   augmentation is generated, child data nodes are generated by rules for
971   <<instantiated-data-node-rules>>.
972   See <<augment-other-module>> for details & examples.
973 `augment` statement targets only instantiated data nodes, so child data nodes
974 representation is always generated.
975
976 [[augment-same-module]]
977 ==== Augmentation target in same module
978
979 All data node children are generated as-if they were directly defined inside
980 target node. There are no externally observable artefacts in generated
981 representation of these nodes, which would point out that they were defined
982 using `augment` statement instead of directly inlining them in target node.
983
984 .Why augment of same module is same as inlining
985 [IMPORTANT]
986 ====
987 This rule may seems counterintuitive at first sight, but YANG defines
988 backwards compatibility in terms of effective model instead of way how model
989 is represented. `augment` statement, when targeting node in same module is not
990 externally observable and could factored out by inlining these statements.
991
992 Definition of `augment` statement in YANG also defines different behaviour when
993 target is same module and allows all features as-if this statements were
994 directly inlined.
995 ====
996
997 .Augment with target in same module
998 ====
999 .YANG module written using augmentations
1000 [source,yang]
1001 ----
1002 container top {
1003
1004 }
1005
1006 augment "/top" {
1007   container foo {
1008
1009   }
1010 }
1011 ----
1012 .Same module written without need to augment
1013 ----
1014 container top {
1015   container foo {
1016
1017   }
1018 }
1019
1020 ----
1021 .Same module written with grouping
1022 ----
1023 grouping a {
1024     container foo {
1025     }
1026 }
1027
1028 container top {
1029     uses a;
1030 }
1031
1032 ----
1033 Java representation for all variants
1034 [uml, file="augment1.png"]
1035 --
1036 set namespaceSeparator none
1037
1038 interface data.Top
1039 interface data.top.Foo
1040
1041 data.Top o- data.top.Foo
1042 --
1043
1044 ====
1045
1046 [[augment-other-module]]
1047 ==== Augmentation target in other module
1048
1049 .Augment with target in other module
1050 ====
1051 [source,yang]
1052 ----
1053 module top {
1054   ...
1055
1056   container top {
1057
1058   }
1059 }
1060
1061 module foo {
1062   ...
1063   import top { prefix top; }
1064   ...
1065   augment "/top:top" {
1066     container bar {
1067
1068     }
1069   }
1070 }
1071
1072 ----
1073
1074 [uml,file="augment2.png"]
1075 --
1076 set namespaceSeparator none
1077
1078 interface Augmentable<T>
1079 interface Augmentation<T>
1080
1081 interface top.data.Top
1082 interface foo.data.FooTop  {
1083   + getBar() : Bar
1084 }
1085
1086 interface foo.data.top.Bar
1087
1088 top.data.Top -u-|> Augmentable : T = top.data.Top
1089 foo.data.FooTop -u-|> Augmentation : T = top.data.Top
1090 top.data.Top o-- foo.data.FooTop
1091 foo.data.FooTop o-- foo.data.top.Bar
1092 --
1093
1094 ====
1095
1096 .Multiple augments with same target
1097 ====
1098 [source,yang]
1099 ----
1100 module top {
1101   ...
1102
1103   container top {
1104
1105   }
1106 }
1107
1108 module foo {
1109   ...
1110   import top { prefix top; }
1111   ...
1112   augment "/top:top" {
1113     container bar {
1114
1115     }
1116   }
1117
1118   augment "/top:top" {
1119     container baz {
1120
1121     }
1122   }
1123 }
1124
1125 ----
1126
1127 [uml,file="augment3.png"]
1128 --
1129 set namespaceSeparator none
1130
1131 interface Augmentable<T>
1132 interface Augmentation<T>
1133
1134 interface top.data.Top
1135 interface foo.data.FooTop {
1136   + getBar() : Bar
1137   + getBaz() : Baz
1138 }
1139
1140 interface foo.data.top.Bar
1141 interface foo.data.top.Baz
1142
1143 top.data.Top -u-|> Augmentable : T = top.data.Top
1144 foo.data.FooTop -u-|> Augmentation : T = top.data.Top
1145 top.data.Top o-- foo.data.FooTop
1146 foo.data.FooTop o-- foo.data.top.Bar
1147 foo.data.FooTop o-- foo.data.top.Baz
1148 --
1149
1150 ====
1151
1152 .Multiple augments with different targets
1153 ====
1154 [source,yang]
1155 ----
1156 module target {
1157   ...
1158
1159   container first {
1160
1161   }
1162
1163   container second {
1164
1165   }
1166 }
1167
1168 module foo {
1169   ...
1170   import target { prefix t; }
1171   ...
1172   augment "/t:first" {
1173     container bar {
1174
1175     }
1176   }
1177
1178   augment "/t:second" {
1179     container baz {
1180
1181     }
1182   }
1183 }
1184
1185 ----
1186
1187 [uml, file="augment4.png"]
1188 --
1189 set namespaceSeparator none
1190
1191 interface Augmentable<T>
1192 interface Augmentation<T>
1193
1194 interface target.data.First
1195 interface target.data.Second
1196
1197 interface foo.data.FooFirst {
1198   + getBar() : Bar
1199 }
1200 interface foo.data.FooSecond {
1201   + getBaz() : Baz
1202 }
1203
1204 interface foo.data.first.Bar
1205 interface foo.data.second.Baz
1206
1207 target.data.First -u-|> Augmentable : T = target.data.First
1208 target.data.Second -u-|> Augmentable : T = target.data.Second
1209
1210 foo.data.FooFirst -u-|> Augmentation : T = target.data.First
1211 foo.data.FooSecond -u-|> Augmentation : T = target.data.Second
1212
1213
1214 target.data.First o-- foo.data.FooFirst
1215 target.data.Second o-- foo.data.FooSecond
1216
1217 foo.data.FooFirst o-- foo.data.first.Bar
1218 foo.data.FooSecond o-- foo.data.second.Baz
1219 --
1220 ====
1221
1222 .Key in grouping
1223 ====
1224 [source,yang]
1225 ----
1226 grouping nodes {
1227     list node {
1228         key id;
1229         leaf id {
1230             type string;
1231         }
1232     }
1233 }
1234
1235 ----
1236 grouping key.grp.nodes.node.<nodeidentifier>
1237
1238 instantiated key.data.nodes.node.<nodeidentifier>