1 package org.opendaylight.controller.sal.binding.dom.serializer.impl
3 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
4 import org.opendaylight.controller.sal.binding.dom.serializer.api.CodecRegistry
5 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
6 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem
7 import org.opendaylight.yangtools.yang.common.QName
8 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item
10 import java.util.WeakHashMap
11 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier
12 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
13 import java.util.ArrayList
14 import org.opendaylight.controller.sal.binding.dom.serializer.api.InstanceIdentifierCodec
15 import org.opendaylight.controller.sal.binding.dom.serializer.api.ValueWithQName
16 import java.util.HashMap
17 import org.slf4j.LoggerFactory
19 import org.opendaylight.yangtools.yang.binding.DataObject
20 import org.opendaylight.controller.sal.binding.dom.serializer.api.IdentifierCodec
21 import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
22 import org.opendaylight.yangtools.yang.data.api.Node
23 import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
24 import org.opendaylight.yangtools.yang.data.api.CompositeNode
25 import org.opendaylight.yangtools.yang.binding.Augmentable
26 import com.google.common.collect.ImmutableList
27 import org.opendaylight.yangtools.yang.binding.Augmentation
28 import java.util.concurrent.ConcurrentHashMap
29 import org.opendaylight.yangtools.yang.binding.util.BindingReflections
31 class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
33 private static val LOG = LoggerFactory.getLogger(InstanceIdentifierCodecImpl);
34 val CodecRegistry codecRegistry;
36 val Map<Class<?>, Map<List<QName>, Class<?>>> classToPreviousAugment = new WeakHashMap;
38 public new(CodecRegistry registry) {
39 codecRegistry = registry;
43 override deserialize(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier input) {
44 var Class<?> baType = null
45 val biArgs = input.path
46 val scannedPath = new ArrayList<QName>(biArgs.size);
47 val baArgs = new ArrayList<org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument>(biArgs.size)
49 scannedPath.add(biArg.nodeType);
50 val baArg = deserializePathArgument(biArg,scannedPath)
52 val injectAugment = classToPreviousAugment.get(baType);
53 if(injectAugment != null) {
54 val augment = injectAugment.get(scannedPath) as Class<? extends DataObject>;
56 baArgs.add(new Item(augment));
61 val ret = new InstanceIdentifier(baArgs,baType as Class<? extends DataObject>);
62 LOG.debug("DOM Instance Identifier {} deserialized to {}",input,ret);
66 private def dispatch org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument deserializePathArgument(NodeIdentifier argument,List<QName> processedPath) {
67 val Class cls = codecRegistry.getClassForPath(processedPath);
72 private def dispatch org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument deserializePathArgument(NodeIdentifierWithPredicates argument,List<QName> processedPath) {
73 val Class type = codecRegistry.getClassForPath(processedPath);
74 val IdentifierCodec codec = codecRegistry.getIdentifierCodecForIdentifiable(type);
75 val value = codec.deserialize(argument.toCompositeNode())?.value;
76 return CodecTypeUtils.newIdentifiableItem(type,value);
79 def CompositeNode toCompositeNode(NodeIdentifierWithPredicates predicates) {
80 val keyValues = predicates.keyValues.entrySet;
81 val values = new ArrayList<Node<?>>(keyValues.size)
82 for(keyValue : keyValues) {
83 values.add(new SimpleNodeTOImpl(keyValue.key,null,keyValue.value))
85 return new CompositeNodeTOImpl(predicates.nodeType,null,values);
88 override serialize(InstanceIdentifier input) {
89 var Class<?> previousAugmentation = null
90 val pathArgs = input.path as List<org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument>
91 var QName previousQName = null;
92 val components = new ArrayList<PathArgument>(pathArgs.size);
93 val qnamePath = new ArrayList<QName>(pathArgs.size);
94 for(baArg : pathArgs) {
96 if(!Augmentation.isAssignableFrom(baArg.type)) {
98 val biArg = serializePathArgument(baArg,previousQName);
99 previousQName = biArg.nodeType;
100 components.add(biArg);
101 qnamePath.add(biArg.nodeType);
102 val immutableList = ImmutableList.copyOf(qnamePath);
103 codecRegistry.putPathToClass(immutableList,baArg.type);
104 if(previousAugmentation !== null) {
105 updateAugmentationInjection(baArg.type,immutableList,previousAugmentation)
108 previousAugmentation = null;
110 previousQName = codecRegistry.getQNameForAugmentation(baArg.type as Class);
111 previousAugmentation = baArg.type;
114 val ret = new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(components);
115 LOG.debug("Binding Instance Identifier {} serialized to DOM InstanceIdentifier {}",input,ret);
119 def updateAugmentationInjection(Class<? extends DataObject> class1, ImmutableList<QName> list, Class<?> augmentation) {
120 if(classToPreviousAugment.get(class1) == null) {
121 classToPreviousAugment.put(class1,new ConcurrentHashMap());
123 classToPreviousAugment.get(class1).put(list,augmentation);
126 private def dispatch PathArgument serializePathArgument(Item argument, QName previousQname) {
127 val type = argument.type;
128 val qname = BindingReflections.findQName(type);
129 if(previousQname == null) {
130 return new NodeIdentifier(qname);
132 return new NodeIdentifier(QName.create(previousQname,qname.localName));
135 @SuppressWarnings("rawtypes")
136 private def dispatch PathArgument serializePathArgument(IdentifiableItem argument, QName previousQname) {
137 val Map<QName,Object> predicates = new HashMap();
138 val type = argument.type;
139 val keyCodec = codecRegistry.getIdentifierCodecForIdentifiable(type);
140 val qname = BindingReflections.findQName(type);
141 val combinedInput = new ValueWithQName(previousQname,argument.key)
142 val compositeOutput = keyCodec.serialize(combinedInput as ValueWithQName);
143 for(outputValue :compositeOutput.value) {
144 predicates.put(outputValue.nodeType,outputValue.value);
146 if(previousQname == null) {
147 return new NodeIdentifierWithPredicates(qname,predicates);
149 return new NodeIdentifierWithPredicates(QName.create(previousQname,qname.localName),predicates);