Trigger a GC once initial configuration has been pushed
[controller.git] / opendaylight / md-sal / sal-common-impl / src / main / java / org / opendaylight / controller / md / sal / common / impl / util / compat / DataNormalizationOperation.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.md.sal.common.impl.util.compat;
9
10 import static com.google.common.base.Preconditions.checkArgument;
11 import static com.google.common.base.Preconditions.checkNotNull;
12
13 import java.util.Collections;
14 import java.util.HashSet;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Map.Entry;
18 import java.util.Set;
19 import java.util.concurrent.ConcurrentHashMap;
20
21 import org.opendaylight.yangtools.concepts.Identifiable;
22 import org.opendaylight.yangtools.yang.common.QName;
23 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
24 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
25 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
26 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
27 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue;
28 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
29 import org.opendaylight.yangtools.yang.data.api.Node;
30 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
31 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
32 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
33 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
34 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
35 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
36 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
37 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
38 import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
39 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
40 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
41 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
42 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
43 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
44 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
45 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
46 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
47
48 import com.google.common.collect.FluentIterable;
49 import com.google.common.collect.ImmutableMap;
50 import com.google.common.collect.ImmutableSet;
51
52 public abstract class DataNormalizationOperation<T extends PathArgument> implements Identifiable<T> {
53
54     private final T identifier;
55
56     @Override
57     public T getIdentifier() {
58         return identifier;
59     };
60
61     protected DataNormalizationOperation(final T identifier) {
62         super();
63         this.identifier = identifier;
64     }
65
66     public boolean isMixin() {
67         return false;
68     }
69
70
71     public boolean isKeyedEntry() {
72         return false;
73     }
74
75     protected Set<QName> getQNameIdentifiers() {
76         return Collections.singleton(identifier.getNodeType());
77     }
78
79     public abstract DataNormalizationOperation<?> getChild(final PathArgument child) throws DataNormalizationException;
80
81     public abstract DataNormalizationOperation<?> getChild(QName child) throws DataNormalizationException;
82
83     public abstract NormalizedNode<?, ?> normalize(Node<?> legacyData);
84
85     private static abstract class SimpleTypeNormalization<T extends PathArgument> extends DataNormalizationOperation<T> {
86
87         protected SimpleTypeNormalization(final T identifier) {
88             super(identifier);
89         }
90
91         @Override
92         public NormalizedNode<?, ?> normalize(final Node<?> legacyData) {
93             checkArgument(legacyData != null);
94             checkArgument(legacyData instanceof SimpleNode<?>);
95             return normalizeImpl((SimpleNode<?>) legacyData);
96         }
97
98         protected abstract NormalizedNode<?, ?> normalizeImpl(SimpleNode<?> node);
99
100         @Override
101         public DataNormalizationOperation<?> getChild(final PathArgument child) {
102             return null;
103         }
104
105         @Override
106         public DataNormalizationOperation<?> getChild(final QName child) {
107             return null;
108         }
109
110         @Override
111         public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
112             return null;
113         }
114
115     }
116
117     private static final class LeafNormalization extends SimpleTypeNormalization<NodeIdentifier> {
118
119         protected LeafNormalization(final NodeIdentifier identifier) {
120             super(identifier);
121         }
122
123         @Override
124         protected NormalizedNode<?, ?> normalizeImpl(final SimpleNode<?> node) {
125             return ImmutableNodes.leafNode(node.getNodeType(), node.getValue());
126         }
127
128     }
129
130     private static final class LeafListEntryNormalization extends SimpleTypeNormalization<NodeWithValue> {
131
132         public LeafListEntryNormalization(final LeafListSchemaNode potential) {
133             super(new NodeWithValue(potential.getQName(), null));
134         }
135
136         @Override
137         protected NormalizedNode<?, ?> normalizeImpl(final SimpleNode<?> node) {
138             NodeWithValue nodeId = new NodeWithValue(node.getNodeType(), node.getValue());
139             return Builders.leafSetEntryBuilder().withNodeIdentifier(nodeId).withValue(node.getValue()).build();
140         }
141
142
143         @Override
144         public boolean isKeyedEntry() {
145             return true;
146         }
147     }
148
149     private static abstract class CompositeNodeNormalizationOperation<T extends PathArgument> extends
150             DataNormalizationOperation<T> {
151
152         protected CompositeNodeNormalizationOperation(final T identifier) {
153             super(identifier);
154         }
155
156         @SuppressWarnings({ "rawtypes", "unchecked" })
157         @Override
158         public final NormalizedNode<?, ?> normalize(final Node<?> legacyData) {
159             checkArgument(legacyData != null);
160             if (!isMixin() && getIdentifier().getNodeType() != null) {
161                 checkArgument(getIdentifier().getNodeType().equals(legacyData.getNodeType()),
162                         "Node QName must be %s was %s", getIdentifier().getNodeType(), legacyData.getNodeType());
163             }
164             checkArgument(legacyData instanceof CompositeNode, "Node %s should be composite", legacyData);
165             CompositeNode compositeNode = (CompositeNode) legacyData;
166             NormalizedNodeContainerBuilder builder = createBuilder(compositeNode);
167
168             Set<DataNormalizationOperation<?>> usedMixins = new HashSet<>();
169             for (Node<?> childLegacy : compositeNode.getValue()) {
170                 final DataNormalizationOperation childOp;
171
172                 try {
173                     childOp = getChild(childLegacy.getNodeType());
174                 } catch (DataNormalizationException e) {
175                     throw new IllegalArgumentException(String.format("Failed to normalize data %s", compositeNode.getValue()), e);
176                 }
177
178                 // We skip unknown nodes if this node is mixin since
179                 // it's nodes and parent nodes are interleaved
180                 if (childOp == null && isMixin()) {
181                     continue;
182                 }
183
184                 checkArgument(childOp != null, "Node %s is not allowed inside %s", childLegacy.getNodeType(),
185                         getIdentifier());
186                 if (childOp.isMixin()) {
187                     if (usedMixins.contains(childOp)) {
188                         // We already run / processed that mixin, so to avoid
189                         // duplicity we are skipping next nodes.
190                         continue;
191                     }
192                     builder.addChild(childOp.normalize(compositeNode));
193                     usedMixins.add(childOp);
194                 } else {
195                     builder.addChild(childOp.normalize(childLegacy));
196                 }
197             }
198             return builder.build();
199         }
200
201         @SuppressWarnings("rawtypes")
202         protected abstract NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode);
203
204     }
205
206     private static abstract class DataContainerNormalizationOperation<T extends PathArgument> extends
207             CompositeNodeNormalizationOperation<T> {
208
209         private final DataNodeContainer schema;
210         private final Map<QName, DataNormalizationOperation<?>> byQName;
211         private final Map<PathArgument, DataNormalizationOperation<?>> byArg;
212
213         protected DataContainerNormalizationOperation(final T identifier, final DataNodeContainer schema) {
214             super(identifier);
215             this.schema = schema;
216             this.byArg = new ConcurrentHashMap<>();
217             this.byQName = new ConcurrentHashMap<>();
218         }
219
220         @Override
221         public DataNormalizationOperation<?> getChild(final PathArgument child) throws DataNormalizationException {
222             DataNormalizationOperation<?> potential = byArg.get(child);
223             if (potential != null) {
224                 return potential;
225             }
226             potential = fromSchema(schema, child);
227             return register(potential);
228         }
229
230         @Override
231         public DataNormalizationOperation<?> getChild(final QName child) throws DataNormalizationException {
232             DataNormalizationOperation<?> potential = byQName.get(child);
233             if (potential != null) {
234                 return potential;
235             }
236             potential = fromSchemaAndPathArgument(schema, child);
237             return register(potential);
238         }
239
240         private DataNormalizationOperation<?> register(final DataNormalizationOperation<?> potential) {
241             if (potential != null) {
242                 byArg.put(potential.getIdentifier(), potential);
243                 for (QName qName : potential.getQNameIdentifiers()) {
244                     byQName.put(qName, potential);
245                 }
246             }
247             return potential;
248         }
249
250     }
251
252     private static final class ListItemNormalization extends
253             DataContainerNormalizationOperation<NodeIdentifierWithPredicates> {
254
255         private final List<QName> keyDefinition;
256
257         protected ListItemNormalization(final NodeIdentifierWithPredicates identifier, final ListSchemaNode schema) {
258             super(identifier, schema);
259             keyDefinition = schema.getKeyDefinition();
260         }
261
262         @Override
263         protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
264             ImmutableMap.Builder<QName, Object> keys = ImmutableMap.builder();
265             for (QName key : keyDefinition) {
266
267                 SimpleNode<?> valueNode = checkNotNull(compositeNode.getFirstSimpleByName(key),
268                         "List node %s MUST contain leaf %s with value.", getIdentifier().getNodeType(), key);
269                 keys.put(key, valueNode.getValue());
270             }
271
272             return Builders.mapEntryBuilder().withNodeIdentifier(
273                     new NodeIdentifierWithPredicates(getIdentifier().getNodeType(), keys.build()));
274         }
275
276         @Override
277         public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
278             DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> builder = Builders
279                     .mapEntryBuilder().withNodeIdentifier((NodeIdentifierWithPredicates) currentArg);
280             for (Entry<QName, Object> keyValue : ((NodeIdentifierWithPredicates) currentArg).getKeyValues().entrySet()) {
281                 builder.addChild(Builders.leafBuilder()
282                         //
283                         .withNodeIdentifier(new NodeIdentifier(keyValue.getKey())).withValue(keyValue.getValue())
284                         .build());
285             }
286             return builder.build();
287         }
288
289
290         @Override
291         public boolean isKeyedEntry() {
292             return true;
293         }
294     }
295
296     private static final class UnkeyedListItemNormalization extends DataContainerNormalizationOperation<NodeIdentifier> {
297
298         protected UnkeyedListItemNormalization(final ListSchemaNode schema) {
299             super(new NodeIdentifier(schema.getQName()), schema);
300         }
301
302         @Override
303         protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
304             return Builders.unkeyedListEntryBuilder().withNodeIdentifier(getIdentifier());
305         }
306
307         @Override
308         public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
309             return Builders.unkeyedListEntryBuilder().withNodeIdentifier((NodeIdentifier) currentArg).build();
310         }
311
312     }
313
314     private static final class ContainerNormalization extends DataContainerNormalizationOperation<NodeIdentifier> {
315
316         protected ContainerNormalization(final ContainerSchemaNode schema) {
317             super(new NodeIdentifier(schema.getQName()), schema);
318         }
319
320         @Override
321         protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
322             return Builders.containerBuilder().withNodeIdentifier(getIdentifier());
323         }
324
325         @Override
326         public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
327             return Builders.containerBuilder().withNodeIdentifier((NodeIdentifier) currentArg).build();
328         }
329
330     }
331
332     private static abstract class MixinNormalizationOp<T extends PathArgument> extends
333             CompositeNodeNormalizationOperation<T> {
334
335         protected MixinNormalizationOp(final T identifier) {
336             super(identifier);
337         }
338
339         @Override
340         public final boolean isMixin() {
341             return true;
342         }
343
344     }
345
346
347     private static final class OrderedLeafListMixinNormalization extends UnorderedLeafListMixinNormalization {
348
349
350         public OrderedLeafListMixinNormalization(final LeafListSchemaNode potential) {
351             super(potential);
352         }
353
354         @Override
355         protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
356             return Builders.orderedLeafSetBuilder().withNodeIdentifier(getIdentifier());
357         }
358
359         @Override
360         public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
361             return Builders.orderedLeafSetBuilder().withNodeIdentifier(getIdentifier()).build();
362         }
363     }
364
365     private static class UnorderedLeafListMixinNormalization extends MixinNormalizationOp<NodeIdentifier> {
366
367         private final DataNormalizationOperation<?> innerOp;
368
369         public UnorderedLeafListMixinNormalization(final LeafListSchemaNode potential) {
370             super(new NodeIdentifier(potential.getQName()));
371             innerOp = new LeafListEntryNormalization(potential);
372         }
373
374         @Override
375         protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
376             return Builders.leafSetBuilder().withNodeIdentifier(getIdentifier());
377         }
378
379         @Override
380         public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
381             return Builders.leafSetBuilder().withNodeIdentifier(getIdentifier()).build();
382         }
383
384         @Override
385         public DataNormalizationOperation<?> getChild(final PathArgument child) {
386             if (child instanceof NodeWithValue) {
387                 return innerOp;
388             }
389             return null;
390         }
391
392         @Override
393         public DataNormalizationOperation<?> getChild(final QName child) {
394             if (getIdentifier().getNodeType().equals(child)) {
395                 return innerOp;
396             }
397             return null;
398         }
399     }
400
401     private static final class AugmentationNormalization extends MixinNormalizationOp<AugmentationIdentifier> {
402
403         private final Map<QName, DataNormalizationOperation<?>> byQName;
404         private final Map<PathArgument, DataNormalizationOperation<?>> byArg;
405
406         public AugmentationNormalization(final AugmentationSchema augmentation, final DataNodeContainer schema) {
407             super(augmentationIdentifierFrom(augmentation));
408
409             ImmutableMap.Builder<QName, DataNormalizationOperation<?>> byQNameBuilder = ImmutableMap.builder();
410             ImmutableMap.Builder<PathArgument, DataNormalizationOperation<?>> byArgBuilder = ImmutableMap.builder();
411
412             for (DataSchemaNode augNode : augmentation.getChildNodes()) {
413                 DataSchemaNode resolvedNode = schema.getDataChildByName(augNode.getQName());
414                 DataNormalizationOperation<?> resolvedOp = fromDataSchemaNode(resolvedNode);
415                 byArgBuilder.put(resolvedOp.getIdentifier(), resolvedOp);
416                 for (QName resQName : resolvedOp.getQNameIdentifiers()) {
417                     byQNameBuilder.put(resQName, resolvedOp);
418                 }
419             }
420             byQName = byQNameBuilder.build();
421             byArg = byArgBuilder.build();
422
423         }
424
425         @Override
426         public DataNormalizationOperation<?> getChild(final PathArgument child) {
427             return byArg.get(child);
428         }
429
430         @Override
431         public DataNormalizationOperation<?> getChild(final QName child) {
432             return byQName.get(child);
433         }
434
435         @Override
436         protected Set<QName> getQNameIdentifiers() {
437             return getIdentifier().getPossibleChildNames();
438         }
439
440         @SuppressWarnings("rawtypes")
441         @Override
442         protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
443             return Builders.augmentationBuilder().withNodeIdentifier(getIdentifier());
444         }
445
446         @Override
447         public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
448             return Builders.augmentationBuilder().withNodeIdentifier(getIdentifier()).build();
449         }
450
451     }
452
453     private static class UnorderedMapMixinNormalization extends MixinNormalizationOp<NodeIdentifier> {
454
455         private final ListItemNormalization innerNode;
456
457         public UnorderedMapMixinNormalization(final ListSchemaNode list) {
458             super(new NodeIdentifier(list.getQName()));
459             this.innerNode = new ListItemNormalization(new NodeIdentifierWithPredicates(list.getQName(),
460                     Collections.<QName, Object> emptyMap()), list);
461         }
462
463         @SuppressWarnings("rawtypes")
464         @Override
465         protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
466             return Builders.mapBuilder().withNodeIdentifier(getIdentifier());
467         }
468
469         @Override
470         public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
471             return Builders.mapBuilder().withNodeIdentifier(getIdentifier()).build();
472         }
473
474         @Override
475         public DataNormalizationOperation<?> getChild(final PathArgument child) {
476             if (child.getNodeType().equals(getIdentifier().getNodeType())) {
477                 return innerNode;
478             }
479             return null;
480         }
481
482         @Override
483         public DataNormalizationOperation<?> getChild(final QName child) {
484             if (getIdentifier().getNodeType().equals(child)) {
485                 return innerNode;
486             }
487             return null;
488         }
489
490     }
491
492
493     private static class UnkeyedListMixinNormalization extends MixinNormalizationOp<NodeIdentifier> {
494
495         private final UnkeyedListItemNormalization innerNode;
496
497         public UnkeyedListMixinNormalization(final ListSchemaNode list) {
498             super(new NodeIdentifier(list.getQName()));
499             this.innerNode = new UnkeyedListItemNormalization(list);
500         }
501
502         @SuppressWarnings("rawtypes")
503         @Override
504         protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
505             return Builders.unkeyedListBuilder().withNodeIdentifier(getIdentifier());
506         }
507
508         @Override
509         public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
510             return Builders.unkeyedListBuilder().withNodeIdentifier(getIdentifier()).build();
511         }
512
513         @Override
514         public DataNormalizationOperation<?> getChild(final PathArgument child) {
515             if (child.getNodeType().equals(getIdentifier().getNodeType())) {
516                 return innerNode;
517             }
518             return null;
519         }
520
521         @Override
522         public DataNormalizationOperation<?> getChild(final QName child) {
523             if (getIdentifier().getNodeType().equals(child)) {
524                 return innerNode;
525             }
526             return null;
527         }
528
529     }
530
531     private static final class OrderedMapMixinNormalization extends UnorderedMapMixinNormalization {
532
533         public OrderedMapMixinNormalization(final ListSchemaNode list) {
534             super(list);
535         }
536
537         @SuppressWarnings("rawtypes")
538         @Override
539         protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
540             return Builders.orderedMapBuilder().withNodeIdentifier(getIdentifier());
541         }
542
543         @Override
544         public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
545             return Builders.orderedMapBuilder().withNodeIdentifier(getIdentifier()).build();
546         }
547
548     }
549
550     private static class ChoiceNodeNormalization extends MixinNormalizationOp<NodeIdentifier> {
551
552         private final ImmutableMap<QName, DataNormalizationOperation<?>> byQName;
553         private final ImmutableMap<PathArgument, DataNormalizationOperation<?>> byArg;
554
555         protected ChoiceNodeNormalization(final org.opendaylight.yangtools.yang.model.api.ChoiceNode schema) {
556             super(new NodeIdentifier(schema.getQName()));
557             ImmutableMap.Builder<QName, DataNormalizationOperation<?>> byQNameBuilder = ImmutableMap.builder();
558             ImmutableMap.Builder<PathArgument, DataNormalizationOperation<?>> byArgBuilder = ImmutableMap.builder();
559
560             for (ChoiceCaseNode caze : schema.getCases()) {
561                 for (DataSchemaNode cazeChild : caze.getChildNodes()) {
562                     DataNormalizationOperation<?> childOp = fromDataSchemaNode(cazeChild);
563                     byArgBuilder.put(childOp.getIdentifier(), childOp);
564                     for (QName qname : childOp.getQNameIdentifiers()) {
565                         byQNameBuilder.put(qname, childOp);
566                     }
567                 }
568             }
569             byQName = byQNameBuilder.build();
570             byArg = byArgBuilder.build();
571         }
572
573         @Override
574         public DataNormalizationOperation<?> getChild(final PathArgument child) {
575             return byArg.get(child);
576         }
577
578         @Override
579         public DataNormalizationOperation<?> getChild(final QName child) {
580             return byQName.get(child);
581         }
582
583         @Override
584         protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
585             return Builders.choiceBuilder().withNodeIdentifier(getIdentifier());
586         }
587
588         @Override
589         public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
590             return Builders.choiceBuilder().withNodeIdentifier(getIdentifier()).build();
591         }
592     }
593
594     private static DataNormalizationOperation<?> fromSchemaAndPathArgument(final DataNodeContainer schema,
595             final QName child) throws DataNormalizationException {
596         DataSchemaNode potential = schema.getDataChildByName(child);
597         if (potential == null) {
598             Iterable<org.opendaylight.yangtools.yang.model.api.ChoiceNode> choices = FluentIterable.from(
599                     schema.getChildNodes()).filter(org.opendaylight.yangtools.yang.model.api.ChoiceNode.class);
600             potential = findChoice(choices, child);
601         }
602
603         if (potential == null) {
604             throw new DataNormalizationException(String.format("Supplied QName %s is not valid according to schema %s, potential children nodes: %s", child, schema,schema.getChildNodes()));
605         }
606
607         if ((schema instanceof DataSchemaNode) && !((DataSchemaNode) schema).isAugmenting() && potential.isAugmenting()) {
608             return fromAugmentation(schema, (AugmentationTarget) schema, potential);
609         }
610         return fromDataSchemaNode(potential);
611     }
612
613     private static org.opendaylight.yangtools.yang.model.api.ChoiceNode findChoice(
614             final Iterable<org.opendaylight.yangtools.yang.model.api.ChoiceNode> choices, final QName child) {
615         org.opendaylight.yangtools.yang.model.api.ChoiceNode foundChoice = null;
616         choiceLoop: for (org.opendaylight.yangtools.yang.model.api.ChoiceNode choice : choices) {
617             for (ChoiceCaseNode caze : choice.getCases()) {
618                 if (caze.getDataChildByName(child) != null) {
619                     foundChoice = choice;
620                     break choiceLoop;
621                 }
622             }
623         }
624         return foundChoice;
625     }
626
627     public static AugmentationIdentifier augmentationIdentifierFrom(final AugmentationSchema augmentation) {
628         ImmutableSet.Builder<QName> potentialChildren = ImmutableSet.builder();
629         for (DataSchemaNode child : augmentation.getChildNodes()) {
630             potentialChildren.add(child.getQName());
631         }
632         return new AugmentationIdentifier(null, potentialChildren.build());
633     }
634
635     private static AugmentationNormalization fromAugmentation(final DataNodeContainer schema,
636             final AugmentationTarget augments, final DataSchemaNode potential) {
637         AugmentationSchema augmentation = null;
638         for (AugmentationSchema aug : augments.getAvailableAugmentations()) {
639             DataSchemaNode child = aug.getDataChildByName(potential.getQName());
640             if (child != null) {
641                 augmentation = aug;
642                 break;
643             }
644
645         }
646         if (augmentation != null) {
647             return new AugmentationNormalization(augmentation, schema);
648         } else {
649             return null;
650         }
651     }
652
653     private static DataNormalizationOperation<?> fromSchema(final DataNodeContainer schema, final PathArgument child) throws DataNormalizationException {
654         if (child instanceof AugmentationIdentifier) {
655             return fromSchemaAndPathArgument(schema, ((AugmentationIdentifier) child).getPossibleChildNames()
656                     .iterator().next());
657         }
658         return fromSchemaAndPathArgument(schema, child.getNodeType());
659     }
660
661     public static DataNormalizationOperation<?> fromDataSchemaNode(final DataSchemaNode potential) {
662         if (potential instanceof ContainerSchemaNode) {
663             return new ContainerNormalization((ContainerSchemaNode) potential);
664         } else if (potential instanceof ListSchemaNode) {
665
666             return fromListSchemaNode((ListSchemaNode) potential);
667         } else if (potential instanceof LeafSchemaNode) {
668             return new LeafNormalization(new NodeIdentifier(potential.getQName()));
669         } else if (potential instanceof org.opendaylight.yangtools.yang.model.api.ChoiceNode) {
670             return new ChoiceNodeNormalization((org.opendaylight.yangtools.yang.model.api.ChoiceNode) potential);
671         } else if (potential instanceof LeafListSchemaNode) {
672             return fromLeafListSchemaNode((LeafListSchemaNode) potential);
673         }
674         return null;
675     }
676
677     private static DataNormalizationOperation<?> fromListSchemaNode(final ListSchemaNode potential) {
678         List<QName> keyDefinition = potential.getKeyDefinition();
679         if(keyDefinition == null || keyDefinition.isEmpty()) {
680             return new UnkeyedListMixinNormalization(potential);
681         }
682         if(potential.isUserOrdered()) {
683             return new OrderedMapMixinNormalization(potential);
684         }
685         return new UnorderedMapMixinNormalization(potential);
686     }
687
688     private static DataNormalizationOperation<?> fromLeafListSchemaNode(final LeafListSchemaNode potential) {
689         if(potential.isUserOrdered()) {
690             return new OrderedLeafListMixinNormalization(potential);
691         }
692         return new UnorderedLeafListMixinNormalization(potential);
693     }
694
695
696     public static DataNormalizationOperation<?> from(final SchemaContext ctx) {
697         return new ContainerNormalization(ctx);
698     }
699
700     public abstract NormalizedNode<?, ?> createDefault(PathArgument currentArg);
701 }