2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.sal.binding.generator.impl;
10 import java.util.ArrayList;
11 import java.util.Arrays;
12 import java.util.Collections;
13 import java.util.HashMap;
14 import java.util.List;
17 import java.util.WeakHashMap;
18 import java.util.concurrent.ConcurrentHashMap;
20 import org.opendaylight.yangtools.concepts.Identifiable;
21 import org.opendaylight.yangtools.yang.binding.Augmentation;
22 import org.opendaylight.yangtools.yang.binding.DataObject;
23 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
24 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
25 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
26 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
27 import org.opendaylight.yangtools.yang.common.QName;
28 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
29 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
30 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
31 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
32 import org.opendaylight.yangtools.yang.data.api.Node;
33 import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
34 import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
35 import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
36 import org.opendaylight.yangtools.yang.data.impl.codec.IdentifierCodec;
37 import org.opendaylight.yangtools.yang.data.impl.codec.InstanceIdentifierCodec;
38 import org.opendaylight.yangtools.yang.data.impl.codec.ValueWithQName;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
42 import com.google.common.collect.ImmutableList;
44 public class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
45 private static final Logger LOG = LoggerFactory.getLogger(InstanceIdentifierCodecImpl.class);
47 private final CodecRegistry codecRegistry;
49 private final Map<Class<?>, Map<List<QName>, Class<?>>> classToPreviousAugment = Collections
50 .synchronizedMap(new WeakHashMap<Class<?>, Map<List<QName>, Class<?>>>());
52 public InstanceIdentifierCodecImpl(final CodecRegistry registry) {
53 this.codecRegistry = registry;
57 public InstanceIdentifier<? extends Object> deserialize(
58 final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier input) {
59 Class<?> baType = null;
60 List<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument> biArgs = input.getPath();
61 List<QName> scannedPath = new ArrayList<>(biArgs.size());
62 List<InstanceIdentifier.PathArgument> baArgs = new ArrayList<InstanceIdentifier.PathArgument>(biArgs.size());
63 for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument biArg : biArgs) {
65 scannedPath.add(biArg.getNodeType());
66 org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument baArg = deserializePathArgument(
69 baType = baArg.getType();
71 Map<List<QName>, Class<?>> injectAugment = classToPreviousAugment.get(baType);
72 if (injectAugment != null) {
73 Class<? extends DataObject> augment = (Class<? extends DataObject>) injectAugment.get(scannedPath);
74 if (augment != null) {
75 baArgs.add(new Item(augment));
80 InstanceIdentifier ret = InstanceIdentifier.create(baArgs);
81 LOG.debug("DOM Instance Identifier {} deserialized to {}", input, ret);
86 public InstanceIdentifier<? extends Object> deserialize(
87 final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier input,
88 InstanceIdentifier<?> bindingIdentifier) {
89 return deserialize(input);
92 private org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument _deserializePathArgument(
93 final NodeIdentifier argument, final List<QName> processedPath) {
94 final Class cls = codecRegistry.getClassForPath(processedPath);
95 Item<DataObject> item = new Item<>(cls);
99 private org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument _deserializePathArgument(
100 final NodeIdentifierWithPredicates argument, final List<QName> processedPath) {
101 final Class type = codecRegistry.getClassForPath(processedPath);
102 final IdentifierCodec codec = codecRegistry
103 .<Identifiable<? extends Object>> getIdentifierCodecForIdentifiable(type);
104 CompositeNode _compositeNode = this.toCompositeNode(argument);
105 ValueWithQName<CompositeNode> deserialize = codec.deserialize(_compositeNode);
107 if (deserialize != null) {
108 value = deserialize.getValue();
110 return CodecTypeUtils.newIdentifiableItem(type, value);
113 public CompositeNode toCompositeNode(final NodeIdentifierWithPredicates predicates) {
114 Set<Map.Entry<QName, Object>> keyValues = predicates.getKeyValues().entrySet();
115 List<Node<?>> values = new ArrayList<>(keyValues.size());
116 for (Map.Entry<QName, Object> keyValue : keyValues) {
117 values.add(new SimpleNodeTOImpl<Object>(keyValue.getKey(), null, keyValue.getValue()));
119 return new CompositeNodeTOImpl(predicates.getNodeType(), null, values);
123 public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier serialize(final InstanceIdentifier<?> input) {
124 Class<?> previousAugmentation = null;
125 List<InstanceIdentifier.PathArgument> pathArgs = input.getPath();
126 QName previousQName = null;
127 List<PathArgument> components = new ArrayList<>(pathArgs.size());
128 List<QName> qnamePath = new ArrayList<>(pathArgs.size());
129 for (InstanceIdentifier.PathArgument baArg : pathArgs) {
131 if (!Augmentation.class.isAssignableFrom(baArg.getType())) {
132 org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument biArg = serializePathArgument(
133 baArg, previousQName);
134 previousQName = biArg.getNodeType();
135 components.add(biArg);
136 qnamePath.add(biArg.getNodeType());
137 ImmutableList<QName> immutableList = ImmutableList.copyOf(qnamePath);
138 codecRegistry.putPathToClass(immutableList, baArg.getType());
139 if (previousAugmentation != null) {
140 updateAugmentationInjection(baArg.getType(), immutableList, previousAugmentation);
142 previousAugmentation = null;
144 previousQName = codecRegistry.getQNameForAugmentation(baArg.getType());
145 previousAugmentation = baArg.getType();
148 org.opendaylight.yangtools.yang.data.api.InstanceIdentifier ret = new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(
150 LOG.debug("Binding Instance Identifier {} serialized to DOM InstanceIdentifier {}", input, ret);
154 public Class<? extends Object> updateAugmentationInjection(final Class<? extends DataObject> class1,
155 final ImmutableList<QName> list, final Class<?> augmentation) {
156 if (classToPreviousAugment.get(class1) == null) {
157 classToPreviousAugment.put(class1, new ConcurrentHashMap<List<QName>, Class<?>>());
159 return classToPreviousAugment.get(class1).put(list, augmentation);
162 private PathArgument _serializePathArgument(final Item<?> argument, final QName previousQname) {
163 Class<?> type = argument.getType();
164 QName qname = BindingReflections.findQName(type);
165 if (previousQname == null || (BindingReflections.isAugmentationChild(argument.getType()))) {
166 return new NodeIdentifier(qname);
168 return new NodeIdentifier(QName.create(previousQname, qname.getLocalName()));
171 private PathArgument _serializePathArgument(final IdentifiableItem argument, final QName previousQname) {
172 Map<QName, Object> predicates = new HashMap<>();
173 Class type = argument.getType();
174 IdentifierCodec<? extends Object> keyCodec = codecRegistry.getIdentifierCodecForIdentifiable(type);
175 QName qname = BindingReflections.findQName(type);
176 if (previousQname != null && !(BindingReflections.isAugmentationChild(argument.getType()))) {
177 qname = QName.create(previousQname, qname.getLocalName());
179 ValueWithQName combinedInput = new ValueWithQName(previousQname, argument.getKey());
180 CompositeNode compositeOutput = keyCodec.serialize(combinedInput);
181 for (Node<?> outputValue : compositeOutput.getValue()) {
182 predicates.put(outputValue.getNodeType(), outputValue.getValue());
184 if (previousQname == null) {
185 return new NodeIdentifierWithPredicates(qname, predicates);
187 return new NodeIdentifierWithPredicates(qname, predicates);
190 private org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument deserializePathArgument(
191 final PathArgument argument, final List<QName> processedPath) {
192 if (argument instanceof NodeIdentifier) {
193 return _deserializePathArgument((NodeIdentifier) argument, processedPath);
194 } else if (argument instanceof NodeIdentifierWithPredicates) {
195 return _deserializePathArgument((NodeIdentifierWithPredicates) argument, processedPath);
197 throw new IllegalArgumentException("Unhandled parameter types: "
198 + Arrays.<Object> asList(argument, processedPath).toString());
202 private PathArgument serializePathArgument(
203 final org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument argument,
204 final QName previousQname) {
205 if (argument instanceof IdentifiableItem) {
206 return _serializePathArgument((IdentifiableItem) argument, previousQname);
207 } else if (argument instanceof Item) {
208 return _serializePathArgument((Item<?>) argument, previousQname);
210 throw new IllegalArgumentException("Unhandled parameter types: "
211 + Arrays.<Object> asList(argument, previousQname).toString());