Merge "Fixed for bug : 1171 - issue while creating subnet"
[controller.git] / opendaylight / md-sal / sal-binding-broker / src / main / java / org / opendaylight / controller / md / sal / binding / impl / BindingToNormalizedNodeCodec.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.binding.impl;
9
10 import java.lang.reflect.Method;
11 import java.util.AbstractMap.SimpleEntry;
12 import java.util.Collection;
13 import java.util.HashSet;
14 import java.util.Iterator;
15 import java.util.Map.Entry;
16 import java.util.Set;
17
18 import javax.annotation.Nullable;
19
20 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException;
21 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationOperation;
22 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
23 import org.opendaylight.yangtools.yang.binding.Augmentation;
24 import org.opendaylight.yangtools.yang.binding.BindingMapping;
25 import org.opendaylight.yangtools.yang.binding.DataObject;
26 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
27 import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
28 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
29 import org.opendaylight.yangtools.yang.common.QName;
30 import org.opendaylight.yangtools.yang.common.QNameModule;
31 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
32 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
33 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
34 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
35 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
36 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
37 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
38 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
39 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
40 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
41 import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
42 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
43 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
44 import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
45 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
46 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
47 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50
51 import com.google.common.base.Function;
52 import com.google.common.base.Optional;
53 import com.google.common.base.Preconditions;
54 import com.google.common.base.Predicate;
55 import com.google.common.collect.ImmutableList;
56 import com.google.common.collect.Iterables;
57
58 public class BindingToNormalizedNodeCodec implements SchemaContextListener {
59
60     private static final Logger LOG = LoggerFactory.getLogger(BindingToNormalizedNodeCodec.class);
61
62     private final BindingIndependentMappingService bindingToLegacy;
63     private DataNormalizer legacyToNormalized;
64
65     public BindingToNormalizedNodeCodec(final BindingIndependentMappingService mappingService) {
66         super();
67         this.bindingToLegacy = mappingService;
68     }
69
70     public org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier toNormalized(
71             final InstanceIdentifier<? extends DataObject> binding) {
72
73         // Used instance-identifier codec do not support serialization of last
74         // path
75         // argument if it is Augmentation (behaviour expected by old datastore)
76         // in this case, we explicitly check if last argument is augmentation
77         // to process it separately
78         if (isAugmentationIdentifier(binding)) {
79             return toNormalizedAugmented(binding);
80         }
81         return toNormalizedImpl(binding);
82     }
83
84     public Entry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, NormalizedNode<?, ?>> toNormalizedNode(
85             final InstanceIdentifier<? extends DataObject> bindingPath, final DataObject bindingObject) {
86         return toNormalizedNode(toBindingEntry(bindingPath, bindingObject));
87
88     }
89
90     public Entry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, NormalizedNode<?, ?>> toNormalizedNode(
91             final Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject> binding) {
92         Entry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, CompositeNode> legacyEntry = bindingToLegacy
93                 .toDataDom(binding);
94         Entry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, NormalizedNode<?, ?>> normalizedEntry = legacyToNormalized
95                 .toNormalized(legacyEntry);
96         LOG.trace("Serialization of {}, Legacy Representation: {}, Normalized Representation: {}", binding,
97                 legacyEntry, normalizedEntry);
98         if (isAugmentation(binding.getKey().getTargetType())) {
99
100             for (DataContainerChild<? extends PathArgument, ?> child : ((DataContainerNode<?>) normalizedEntry
101                     .getValue()).getValue()) {
102                 if (child instanceof AugmentationNode) {
103                     ImmutableList<PathArgument> childArgs = ImmutableList.<PathArgument> builder()
104                             .addAll(normalizedEntry.getKey().getPathArguments()).add(child.getIdentifier()).build();
105                     org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier childPath = org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier
106                             .create(childArgs);
107                     return toDOMEntry(childPath, child);
108                 }
109             }
110
111         }
112         return normalizedEntry;
113
114     }
115
116     /**
117      *
118      * Returns a Binding-Aware instance identifier from normalized
119      * instance-identifier if it is possible to create representation.
120      *
121      * Returns Optional.absent for cases where target is mixin node except
122      * augmentation.
123      *
124      */
125     public Optional<InstanceIdentifier<? extends DataObject>> toBinding(
126             final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized)
127                     throws DeserializationException {
128
129         PathArgument lastArgument = Iterables.getLast(normalized.getPathArguments());
130         // Used instance-identifier codec do not support serialization of last
131         // path
132         // argument if it is AugmentationIdentifier (behaviour expected by old
133         // datastore)
134         // in this case, we explicitly check if last argument is augmentation
135         // to process it separately
136         if (lastArgument instanceof AugmentationIdentifier) {
137             return toBindingAugmented(normalized);
138         }
139         return toBindingImpl(normalized);
140     }
141
142     private Optional<InstanceIdentifier<? extends DataObject>> toBindingAugmented(
143             final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized)
144                     throws DeserializationException {
145         Optional<InstanceIdentifier<? extends DataObject>> potential = toBindingImpl(normalized);
146         // Shorthand check, if codec already supports deserialization
147         // of AugmentationIdentifier we will return
148         if (potential.isPresent() && isAugmentationIdentifier(potential.get())) {
149             return potential;
150         }
151
152         int normalizedCount = getAugmentationCount(normalized);
153         AugmentationIdentifier lastArgument = (AugmentationIdentifier) Iterables.getLast(normalized.getPathArguments());
154
155         // Here we employ small trick - Binding-aware Codec injects an pointer
156         // to augmentation class
157         // if child is referenced - so we will reference child and then shorten
158         // path.
159         LOG.trace("Looking for candidates to match {}", normalized);
160         for (QName child : lastArgument.getPossibleChildNames()) {
161             org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier childPath = normalized.node(child);
162             try {
163                 if (isNotRepresentable(childPath)) {
164                     LOG.trace("Path {} is not BI-representable, skipping it", childPath);
165                     continue;
166                 }
167             } catch (DataNormalizationException e) {
168                 LOG.warn("Failed to denormalize path {}, skipping it", childPath, e);
169                 continue;
170             }
171
172             Optional<InstanceIdentifier<? extends DataObject>> baId = toBindingImpl(childPath);
173             if (!baId.isPresent()) {
174                 LOG.debug("No binding-aware identifier found for path {}, skipping it", childPath);
175                 continue;
176             }
177
178             InstanceIdentifier<? extends DataObject> potentialPath = shortenToLastAugment(baId.get());
179             int potentialAugmentCount = getAugmentationCount(potentialPath);
180             if (potentialAugmentCount == normalizedCount) {
181                 LOG.trace("Found matching path {}", potentialPath);
182                 return Optional.<InstanceIdentifier<? extends DataObject>> of(potentialPath);
183             }
184
185             LOG.trace("Skipping mis-matched potential path {}", potentialPath);
186         }
187
188         LOG.trace("Failed to find augmentation matching {}", normalized);
189         return Optional.absent();
190     }
191
192     private Optional<InstanceIdentifier<? extends DataObject>> toBindingImpl(
193             final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized)
194                     throws DeserializationException {
195         org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier legacyPath;
196
197         try {
198             if (isNotRepresentable(normalized)) {
199                 return Optional.absent();
200             }
201             legacyPath = legacyToNormalized.toLegacy(normalized);
202         } catch (DataNormalizationException e) {
203             throw new IllegalStateException("Could not denormalize path.", e);
204         }
205         LOG.trace("InstanceIdentifier Path Deserialization: Legacy representation {}, Normalized representation: {}",
206                 legacyPath, normalized);
207         return Optional.<InstanceIdentifier<? extends DataObject>> of(bindingToLegacy.fromDataDom(legacyPath));
208     }
209
210     private boolean isNotRepresentable(final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized)
211             throws DataNormalizationException {
212         DataNormalizationOperation<?> op = findNormalizationOperation(normalized);
213         if (op.isMixin() && op.getIdentifier() instanceof NodeIdentifier) {
214             return true;
215         }
216         if (op.isLeaf()) {
217             return true;
218         }
219         return false;
220     }
221
222     private DataNormalizationOperation<?> findNormalizationOperation(
223             final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized)
224                     throws DataNormalizationException {
225         DataNormalizationOperation<?> current = legacyToNormalized.getRootOperation();
226         for (PathArgument arg : normalized.getPathArguments()) {
227             current = current.getChild(arg);
228         }
229         return current;
230     }
231
232     private static final Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject> toBindingEntry(
233             final org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject> key,
234             final DataObject value) {
235         return new SimpleEntry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject>(
236                 key, value);
237     }
238
239     private static final Entry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, NormalizedNode<?, ?>> toDOMEntry(
240             final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier key, final NormalizedNode<?, ?> value) {
241         return new SimpleEntry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, NormalizedNode<?, ?>>(key,
242                 value);
243     }
244
245     public DataObject toBinding(final InstanceIdentifier<?> path, final NormalizedNode<?, ?> normalizedNode)
246             throws DeserializationException {
247         CompositeNode legacy = null;
248         if (isAugmentationIdentifier(path) && normalizedNode instanceof AugmentationNode) {
249             QName augIdentifier = BindingReflections.findQName(path.getTargetType());
250             ContainerNode virtualNode = Builders.containerBuilder() //
251                     .withNodeIdentifier(new NodeIdentifier(augIdentifier)) //
252                     .withChild((DataContainerChild<?, ?>) normalizedNode) //
253                     .build();
254             legacy = (CompositeNode) DataNormalizer.toLegacy(virtualNode);
255         } else {
256             legacy = (CompositeNode) DataNormalizer.toLegacy(normalizedNode);
257         }
258
259         return bindingToLegacy.dataObjectFromDataDom(path, legacy);
260     }
261
262     public DataNormalizer getDataNormalizer() {
263         return legacyToNormalized;
264     }
265
266     public Optional<Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject>> toBinding(
267             final Entry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, ? extends NormalizedNode<?, ?>> normalized)
268                     throws DeserializationException {
269         Optional<InstanceIdentifier<? extends DataObject>> potentialPath = toBinding(normalized.getKey());
270         if (potentialPath.isPresent()) {
271             InstanceIdentifier<? extends DataObject> bindingPath = potentialPath.get();
272             DataObject bindingData = toBinding(bindingPath, normalized.getValue());
273             if (bindingData == null) {
274                 LOG.warn("Failed to deserialize {} to Binding format. Binding path is: {}", normalized, bindingPath);
275             }
276             return Optional.of(toBindingEntry(bindingPath, bindingData));
277         } else {
278             return Optional.absent();
279         }
280     }
281
282     @Override
283     public void onGlobalContextUpdated(final SchemaContext arg0) {
284         legacyToNormalized = new DataNormalizer(arg0);
285     }
286
287     private org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier toNormalizedAugmented(
288             final InstanceIdentifier<?> augPath) {
289         org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier processed = toNormalizedImpl(augPath);
290         // If used instance identifier codec added supports for deserialization
291         // of last AugmentationIdentifier we will just reuse it
292         if (isAugmentationIdentifier(processed)) {
293             return processed;
294         }
295         Optional<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier> additionalSerialized;
296         additionalSerialized = toNormalizedAugmentedUsingChildContainers(augPath, processed);
297
298         if (additionalSerialized.isPresent()) {
299             return additionalSerialized.get();
300         }
301         additionalSerialized = toNormalizedAugmentedUsingChildLeafs(augPath, processed);
302         if (additionalSerialized.isPresent()) {
303             return additionalSerialized.get();
304         }
305         throw new IllegalStateException("Unabled to construct augmentation identfier for " + augPath);
306     }
307
308     /**
309      * Tries to find correct augmentation identifier using children leafs
310      *
311      * This method uses normalized Instance Identifier of parent node to fetch
312      * schema and {@link BindingReflections#getModuleInfo(Class)} to learn about
313      * augmentation namespace, specificly, in which module it was defined.
314      *
315      * Then it uses it to filter all available augmentations for parent by
316      * module. After that it walks augmentations in particular module and
317      * pick-up first which at least one leaf name matches supplied augmentation.
318      * We could do this safely since YANG explicitly states that no any existing
319      * augmentations must differ in leaf fully qualified names.
320      *
321      *
322      * @param augPath
323      *            Binding Aware Path which ends with augment
324      * @param parentPath
325      *            Processed path
326      * @return
327      */
328     private Optional<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier> toNormalizedAugmentedUsingChildLeafs(
329             final InstanceIdentifier<?> augPath,
330             final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier parentPath) {
331         try {
332             DataNormalizationOperation<?> parentOp = legacyToNormalized.getOperation(parentPath);
333             if(!parentOp.getDataSchemaNode().isPresent()) {
334                 return Optional.absent();
335             }
336             DataSchemaNode parentSchema = parentOp.getDataSchemaNode().get();
337             if (parentSchema instanceof AugmentationTarget) {
338                 Set<AugmentationSchema> augmentations = ((AugmentationTarget) parentSchema).getAvailableAugmentations();
339                 LOG.info("Augmentations for {}, {}", augPath, augmentations);
340                 Optional<AugmentationSchema> schema = findAugmentation(augPath.getTargetType(), augmentations);
341                 if (schema.isPresent()) {
342                     AugmentationIdentifier augmentationIdentifier = DataNormalizationOperation
343                             .augmentationIdentifierFrom(schema.get());
344                     return Optional.of(parentPath.node(augmentationIdentifier));
345                 }
346             }
347         } catch (DataNormalizationException e) {
348             throw new IllegalArgumentException(e);
349         }
350         return Optional.absent();
351     }
352
353     /**
354      * Creates instance identifier for augmentation child, tries to serialize it
355      * Instance Identifier is then shortened to last augmentation.
356      *
357      * This is for situations, where underlying codec is implementing hydrogen
358      * style DOM APIs (which did not supported {@link AugmentationIdentifier}.)
359      *
360      * @param augPath
361      * @param parentPath
362      *            Path to parent node
363      * @return
364      */
365     @SuppressWarnings("rawtypes")
366     private Optional<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier> toNormalizedAugmentedUsingChildContainers(
367             final InstanceIdentifier<?> augPath,
368             final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier parentPath) {
369         for (Class augChild : BindingReflections.getChildrenClasses(augPath.getTargetType())) {
370             @SuppressWarnings("unchecked")
371             InstanceIdentifier<?> childPath = augPath.child(augChild);
372             org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized = toNormalizedImpl(childPath);
373             org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier potentialDiscovered = shortenToLastAugmentation(
374                     normalized, parentPath);
375             if (potentialDiscovered != null) {
376                 return Optional.of(potentialDiscovered);
377             }
378         }
379         return Optional.absent();
380     }
381
382     private Optional<AugmentationSchema> findAugmentation(final Class<?> targetType,
383             final Set<AugmentationSchema> augmentations) {
384         YangModuleInfo moduleInfo;
385         try {
386             moduleInfo = BindingReflections.getModuleInfo(targetType);
387         } catch (Exception e) {
388             throw new IllegalStateException(e);
389         }
390         Iterable<AugmentationSchema> filtered = filteredByModuleInfo(augmentations,
391                 BindingReflections.getModuleQName(moduleInfo).getModule());
392         filtered.toString();
393         Set<String> targetTypeGetters = getYangModeledGetters(targetType);
394         for (AugmentationSchema schema : filtered) {
395             for (DataSchemaNode child : schema.getChildNodes()) {
396                 String getterName = "get" + BindingMapping.getClassName(child.getQName());
397                 if (targetTypeGetters.contains(getterName)) {
398                     return Optional.of(schema);
399                 }
400             }
401         }
402         return Optional.absent();
403     }
404
405     private static Iterable<AugmentationSchema> filteredByModuleInfo(final Iterable<AugmentationSchema> augmentations,
406             final QNameModule module) {
407         return Iterables.filter(augmentations, new Predicate<AugmentationSchema>() {
408             @Override
409             public boolean apply(final AugmentationSchema schema) {
410                 final Collection<DataSchemaNode> childNodes = schema.getChildNodes();
411                 return !childNodes.isEmpty() && module.equals(Iterables.get(childNodes, 0).getQName().getModule());
412             }
413         });
414     }
415
416     public static final Set<String> getYangModeledGetters(final Class<?> targetType) {
417         HashSet<String> ret = new HashSet<String>();
418         for (Method method : targetType.getMethods()) {
419             if (isYangModeledGetter(method)) {
420                 ret.add(method.getName());
421             }
422         }
423         return ret;
424     }
425
426     /**
427      *
428      * Returns true if supplied method represent getter for YANG modeled value
429      *
430      * @param method
431      *            Method to be tested
432      * @return true if method represent getter for YANG Modeled value.
433      */
434     private static final boolean isYangModeledGetter(final Method method) {
435         return !method.getName().equals("getClass") && !method.getName().equals("getImplementedInterface")
436                 && method.getName().startsWith("get") && method.getParameterTypes().length == 0;
437     }
438
439     private org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier shortenToLastAugmentation(
440             final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized,
441             final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier parentPath) {
442         int parentSize = Iterables.size(parentPath.getPathArguments());
443         int position = 0;
444         int foundPosition = -1;
445         for (PathArgument arg : normalized.getPathArguments()) {
446             position++;
447             if (arg instanceof AugmentationIdentifier) {
448                 foundPosition = position;
449             }
450         }
451         if (foundPosition > 0 && foundPosition > parentSize) {
452             Iterable<PathArgument> shortened = Iterables.limit(normalized.getPathArguments(), foundPosition);
453             return org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.create(shortened);
454         }
455         return null;
456     }
457
458     private InstanceIdentifier<? extends DataObject> shortenToLastAugment(
459             final InstanceIdentifier<? extends DataObject> binding) {
460         int position = 0;
461         int foundPosition = -1;
462         for (org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument arg : binding.getPathArguments()) {
463             position++;
464             if (isAugmentation(arg.getType())) {
465                 foundPosition = position;
466             }
467         }
468         return InstanceIdentifier.create(Iterables.limit(binding.getPathArguments(), foundPosition));
469     }
470
471     private org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier toNormalizedImpl(
472             final InstanceIdentifier<? extends DataObject> binding) {
473         final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier legacyPath = bindingToLegacy
474                 .toDataDom(binding);
475         final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized = legacyToNormalized
476                 .toNormalized(legacyPath);
477         return normalized;
478     }
479
480     private static boolean isAugmentation(final Class<? extends DataObject> type) {
481         return Augmentation.class.isAssignableFrom(type);
482     }
483
484     private static boolean isAugmentationIdentifier(final InstanceIdentifier<?> potential) {
485         return Augmentation.class.isAssignableFrom(potential.getTargetType());
486     }
487
488     private boolean isAugmentationIdentifier(final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier processed) {
489         return Iterables.getLast(processed.getPathArguments()) instanceof AugmentationIdentifier;
490     }
491
492     private static int getAugmentationCount(final InstanceIdentifier<?> potential) {
493         int count = 0;
494         for (org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument arg : potential.getPathArguments()) {
495             if (isAugmentation(arg.getType())) {
496                 count++;
497             }
498
499         }
500         return count;
501     }
502
503     private static int getAugmentationCount(final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier potential) {
504         int count = 0;
505         for (PathArgument arg : potential.getPathArguments()) {
506             if (arg instanceof AugmentationIdentifier) {
507                 count++;
508             }
509         }
510         return count;
511     }
512
513     @SuppressWarnings({ "rawtypes", "unchecked" })
514     public <T extends DataObject> Function<Optional<NormalizedNode<?, ?>>, Optional<T>>  deserializeFunction(final InstanceIdentifier<T> path) {
515         return new DeserializeFunction(this, path);
516     }
517
518     private static class DeserializeFunction<T extends DataObject> implements Function<Optional<NormalizedNode<?, ?>>, Optional<T>> {
519
520         private final BindingToNormalizedNodeCodec codec;
521         private final InstanceIdentifier<?> path;
522
523         public DeserializeFunction(final BindingToNormalizedNodeCodec codec, final InstanceIdentifier<?> path) {
524             super();
525             this.codec = Preconditions.checkNotNull(codec, "Codec must not be null");
526             this.path = Preconditions.checkNotNull(path, "Path must not be null");
527         }
528
529         @SuppressWarnings("rawtypes")
530         @Nullable
531         @Override
532         public Optional apply(@Nullable final Optional<NormalizedNode<?, ?>> normalizedNode) {
533             if (normalizedNode.isPresent()) {
534                 final DataObject dataObject;
535                 try {
536                     dataObject = codec.toBinding(path, normalizedNode.get());
537                 } catch (DeserializationException e) {
538                     LOG.warn("Failed to create dataobject from node {}", normalizedNode.get(), e);
539                     throw new IllegalStateException("Failed to create dataobject", e);
540                 }
541
542                 if (dataObject != null) {
543                     return Optional.of(dataObject);
544                 }
545             }
546             return Optional.absent();
547         }
548     }
549
550     /**
551      * Returns an default object according to YANG schema for supplied path.
552      *
553      * @param path DOM Path
554      * @return Node with defaults set on.
555      */
556     public NormalizedNode<?, ?> getDefaultNodeFor(final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier path) {
557         Iterator<PathArgument> iterator = path.getPathArguments().iterator();
558         DataNormalizationOperation<?> currentOp = legacyToNormalized.getRootOperation();
559         while (iterator.hasNext()) {
560             PathArgument currentArg = iterator.next();
561             try {
562                 currentOp = currentOp.getChild(currentArg);
563             } catch (DataNormalizationException e) {
564                 throw new IllegalArgumentException(String.format("Invalid child encountered in path %s", path), e);
565             }
566         }
567         return currentOp.createDefault(path.getLastPathArgument());
568     }
569 }