Merge "Cleanup root pom "name"."
[controller.git] / opendaylight / md-sal / sal-common-impl / src / main / java / org / opendaylight / controller / md / sal / common / impl / util / compat / DataNormalizer.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
12 import java.util.AbstractMap;
13 import java.util.ArrayList;
14 import java.util.Iterator;
15 import java.util.Map;
16
17 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
20 import org.opendaylight.yangtools.yang.data.api.Node;
21 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
22 import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
23 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
24 import org.opendaylight.yangtools.yang.data.api.schema.MixinNode;
25 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
26 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
27 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
28 import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
29 import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
30 import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
31 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
32
33 import com.google.common.base.Preconditions;
34 import com.google.common.base.Predicates;
35 import com.google.common.collect.FluentIterable;
36 import com.google.common.collect.ImmutableList;
37 import com.google.common.collect.Iterables;
38
39 /**
40  * @deprecated This class provides compatibility between {@link CompositeNode} and {@link NormalizedNode}.
41  *             Users of this class should use {@link NormalizedNode}s directly.
42  */
43 @Deprecated
44 public class DataNormalizer {
45
46     private final DataNormalizationOperation<?> operation;
47
48     public DataNormalizer(final SchemaContext ctx) {
49         operation = DataNormalizationOperation.from(ctx);
50     }
51
52     public YangInstanceIdentifier toNormalized(final YangInstanceIdentifier legacy) {
53         ImmutableList.Builder<PathArgument> normalizedArgs = ImmutableList.builder();
54
55         DataNormalizationOperation<?> currentOp = operation;
56         Iterator<PathArgument> arguments = legacy.getPathArguments().iterator();
57
58         try {
59             while (arguments.hasNext()) {
60                 PathArgument legacyArg = arguments.next();
61                 currentOp = currentOp.getChild(legacyArg);
62                 checkArgument(currentOp != null,
63                         "Legacy Instance Identifier %s is not correct. Normalized Instance Identifier so far %s",
64                         legacy, normalizedArgs.build());
65                 while (currentOp.isMixin()) {
66                     normalizedArgs.add(currentOp.getIdentifier());
67                     currentOp = currentOp.getChild(legacyArg.getNodeType());
68                 }
69                 normalizedArgs.add(legacyArg);
70             }
71         } catch (DataNormalizationException e) {
72             throw new IllegalArgumentException(String.format("Failed to normalize path %s", legacy), e);
73         }
74
75         return YangInstanceIdentifier.create(normalizedArgs.build());
76     }
77
78     public DataNormalizationOperation<?> getOperation(final YangInstanceIdentifier legacy) throws DataNormalizationException {
79         DataNormalizationOperation<?> currentOp = operation;
80         Iterator<PathArgument> arguments = legacy.getPathArguments().iterator();
81
82         while (arguments.hasNext()) {
83             currentOp = currentOp.getChild(arguments.next());
84         }
85         return currentOp;
86     }
87
88     public Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> toNormalized(
89             final Map.Entry<YangInstanceIdentifier, CompositeNode> legacy) {
90         return toNormalized(legacy.getKey(), legacy.getValue());
91     }
92
93     public Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> toNormalized(final YangInstanceIdentifier legacyPath,
94             final CompositeNode legacyData) {
95
96         YangInstanceIdentifier normalizedPath = toNormalized(legacyPath);
97
98         DataNormalizationOperation<?> currentOp = operation;
99         for (PathArgument arg : normalizedPath.getPathArguments()) {
100             try {
101                 currentOp = currentOp.getChild(arg);
102             } catch (DataNormalizationException e) {
103                 throw new IllegalArgumentException(String.format("Failed to validate normalized path %s",
104                         normalizedPath), e);
105             }
106         }
107         Preconditions.checkArgument(currentOp != null,
108                 "Instance Identifier %s does not reference correct schema Node.", normalizedPath);
109         return new AbstractMap.SimpleEntry<YangInstanceIdentifier, NormalizedNode<?, ?>>(normalizedPath,
110                 currentOp.normalize(legacyData));
111     }
112
113     public YangInstanceIdentifier toLegacy(final YangInstanceIdentifier normalized) throws DataNormalizationException {
114         ImmutableList.Builder<PathArgument> legacyArgs = ImmutableList.builder();
115         DataNormalizationOperation<?> currentOp = operation;
116         for (PathArgument normalizedArg : normalized.getPathArguments()) {
117             currentOp = currentOp.getChild(normalizedArg);
118             if (!currentOp.isMixin()) {
119                 legacyArgs.add(normalizedArg);
120             }
121         }
122         return YangInstanceIdentifier.create(legacyArgs.build());
123     }
124
125     public CompositeNode toLegacy(final YangInstanceIdentifier normalizedPath, final NormalizedNode<?, ?> normalizedData) {
126         // Preconditions.checkArgument(normalizedData instanceof
127         // DataContainerNode<?>,"Node object %s, %s should be of type DataContainerNode",normalizedPath,normalizedData);
128         if (normalizedData instanceof DataContainerNode<?>) {
129             return toLegacyFromDataContainer((DataContainerNode<?>) normalizedData);
130         } else if (normalizedData instanceof AnyXmlNode) {
131             Node<?> value = ((AnyXmlNode) normalizedData).getValue();
132             return value instanceof CompositeNode ? (CompositeNode) value : null;
133         }
134         return null;
135     }
136
137     public static Node<?> toLegacy(final NormalizedNode<?, ?> node) {
138         if (node instanceof MixinNode) {
139             /**
140              * Direct reading of MixinNodes is not supported, since it is not
141              * possible in legacy APIs create pointer to Mixin Nodes.
142              *
143              */
144             return null;
145         }
146
147         if (node instanceof DataContainerNode<?>) {
148             return toLegacyFromDataContainer((DataContainerNode<?>) node);
149         } else if (node instanceof AnyXmlNode) {
150             return ((AnyXmlNode) node).getValue();
151         }
152         return toLegacySimple(node);
153
154     }
155
156     private static SimpleNode<?> toLegacySimple(final NormalizedNode<?, ?> node) {
157         return new SimpleNodeTOImpl<Object>(node.getNodeType(), null, node.getValue());
158     }
159
160     @SuppressWarnings({ "unchecked", "rawtypes" })
161     private static CompositeNode toLegacyFromDataContainer(final DataContainerNode<?> node) {
162         CompositeNodeBuilder<ImmutableCompositeNode> builder = ImmutableCompositeNode.builder();
163         builder.setQName(node.getNodeType());
164         for (NormalizedNode<?, ?> child : node.getValue()) {
165             if (child instanceof MixinNode && child instanceof NormalizedNodeContainer<?, ?, ?>) {
166                 builder.addAll(toLegacyNodesFromMixin((NormalizedNodeContainer) child));
167             } else if (child instanceof UnkeyedListNode) {
168                 builder.addAll(toLegacyNodesFromUnkeyedList((UnkeyedListNode) child));
169             } else {
170                 addToBuilder(builder, toLegacy(child));
171             }
172         }
173         return builder.toInstance();
174     }
175
176     private static Iterable<? extends Node<?>> toLegacyNodesFromUnkeyedList(final UnkeyedListNode mixin) {
177         ArrayList<Node<?>> ret = new ArrayList<>();
178         for (NormalizedNode<?, ?> child : mixin.getValue()) {
179             ret.add(toLegacy(child));
180         }
181         return FluentIterable.from(ret).filter(Predicates.notNull());
182     }
183
184     private static void addToBuilder(final CompositeNodeBuilder<ImmutableCompositeNode> builder, final Node<?> legacy) {
185         if (legacy != null) {
186             builder.add(legacy);
187         }
188     }
189
190     @SuppressWarnings({ "rawtypes", "unchecked" })
191     private static Iterable<Node<?>> toLegacyNodesFromMixin(
192             final NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>> mixin) {
193         ArrayList<Node<?>> ret = new ArrayList<>();
194         for (NormalizedNode<?, ?> child : mixin.getValue()) {
195             if (child instanceof MixinNode && child instanceof NormalizedNodeContainer<?, ?, ?>) {
196                 Iterables.addAll(ret, toLegacyNodesFromMixin((NormalizedNodeContainer) child));
197             } else {
198                 ret.add(toLegacy(child));
199             }
200         }
201         return FluentIterable.from(ret).filter(Predicates.notNull());
202     }
203
204     public DataNormalizationOperation<?> getRootOperation() {
205         return operation;
206     }
207
208 }