Added functionality to store capability info.
[controller.git] / opendaylight / md-sal / sal-binding-broker / src / main / java / org / opendaylight / controller / sal / binding / dom / serializer / impl / InstanceIdentifierCodecImpl.xtend
1 package org.opendaylight.controller.sal.binding.dom.serializer.impl
2
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
9 import java.util.Map
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
18 import java.util.List
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
30 class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
31     
32     private static val LOG = LoggerFactory.getLogger(InstanceIdentifierCodecImpl);
33     val CodecRegistry codecRegistry;
34     
35     val Map<Class<?>,QName> classToQName = new WeakHashMap;
36     val Map<Class<?>, Map<List<QName>, Class<?>>> classToPreviousAugment = new WeakHashMap;
37     
38     public new(CodecRegistry registry) {
39         codecRegistry = registry;
40     }
41     
42     
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)
48         for(biArg : biArgs) {
49             scannedPath.add(biArg.nodeType);
50             val baArg = deserializePathArgument(biArg,scannedPath)
51             baType = baArg?.type
52             val injectAugment = classToPreviousAugment.get(baType);
53             if(injectAugment != null) {
54                 val augment = injectAugment.get(scannedPath) as Class<? extends DataObject>;
55                 if(augment != null) {
56                     baArgs.add(new Item(augment));
57                 }
58             }
59             baArgs.add(baArg)
60         }
61         val ret = new InstanceIdentifier(baArgs,baType as Class<? extends DataObject>);
62         return ret;
63     }
64     
65     private def dispatch org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument deserializePathArgument(NodeIdentifier argument,List<QName> processedPath) {
66         val Class cls = codecRegistry.getClassForPath(processedPath);
67         return new Item(cls);
68     }
69     
70     
71     private def dispatch org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument deserializePathArgument(NodeIdentifierWithPredicates argument,List<QName> processedPath) {
72         val Class type = codecRegistry.getClassForPath(processedPath);
73         val IdentifierCodec codec = codecRegistry.getIdentifierCodecForIdentifiable(type);
74         val value = codec.deserialize(argument.toCompositeNode())?.value;
75         return CodecTypeUtils.newIdentifiableItem(type,value);
76     }
77     
78     def CompositeNode toCompositeNode(NodeIdentifierWithPredicates predicates) {
79         val keyValues = predicates.keyValues.entrySet;
80         val values = new ArrayList<Node<?>>(keyValues.size)
81         for(keyValue : keyValues) {
82             values.add(new SimpleNodeTOImpl(keyValue.key,null,keyValue.value))
83         }
84         return new CompositeNodeTOImpl(predicates.nodeType,null,values);
85     }
86     
87     override serialize(InstanceIdentifier input) {
88         var Class<?> previousAugmentation = null
89         val pathArgs = input.path as List<org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument>
90         var QName previousQName = null;
91         val components = new ArrayList<PathArgument>(pathArgs.size);
92         val qnamePath = new ArrayList<QName>(pathArgs.size);
93         for(baArg : pathArgs) { 
94             
95             if(!Augmentation.isAssignableFrom(baArg.type)) {
96                 
97                 val biArg = serializePathArgument(baArg,previousQName);
98                 previousQName = biArg.nodeType;
99                 components.add(biArg);
100                 qnamePath.add(biArg.nodeType);
101                 val immutableList = ImmutableList.copyOf(qnamePath);
102                 codecRegistry.putPathToClass(immutableList,baArg.type);
103                 if(previousAugmentation !== null) {
104                     updateAugmentationInjection(baArg.type,immutableList,previousAugmentation)
105                 }
106                 
107                 previousAugmentation = null;
108             } else {
109                 previousQName = resolveQname(baArg.type);
110                 previousAugmentation = baArg.type;
111             }
112         }
113         return new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(components);
114     }
115     
116     def updateAugmentationInjection(Class<? extends DataObject> class1, ImmutableList<QName> list, Class<?> augmentation) {
117         if(classToPreviousAugment.get(class1) == null) {
118             classToPreviousAugment.put(class1,new ConcurrentHashMap());
119         }
120         classToPreviousAugment.get(class1).put(list,augmentation);
121     }
122     
123     private def dispatch PathArgument serializePathArgument(Item argument, QName previousQname) {
124         val type = argument.type;
125         val qname = resolveQname(type);
126         if(previousQname == null) {
127             return new NodeIdentifier(qname);
128         }
129         return new NodeIdentifier(QName.create(previousQname,qname.localName));
130     }
131     
132     @SuppressWarnings("rawtypes")
133     private def dispatch PathArgument serializePathArgument(IdentifiableItem argument, QName previousQname) {
134         val Map<QName,Object> predicates = new HashMap();
135         val type = argument.type;
136         val keyCodec = codecRegistry.getIdentifierCodecForIdentifiable(type);
137         val qname = resolveQname(type);
138         val combinedInput =  new ValueWithQName(previousQname,argument.key)
139         val compositeOutput = keyCodec.serialize(combinedInput as ValueWithQName);
140         for(outputValue :compositeOutput.value) {
141             predicates.put(outputValue.nodeType,outputValue.value);
142         }
143         if(previousQname == null) {
144             return new NodeIdentifierWithPredicates(qname,predicates);
145         }
146         return new NodeIdentifierWithPredicates(QName.create(previousQname,qname.localName),predicates);
147     }
148     
149     def resolveQname(Class<?> class1) {
150         val qname = classToQName.get(class1);
151         if(qname !== null) {
152             return qname;
153         }
154         val qnameField = class1.getField("QNAME");
155         val qnameValue = qnameField.get(null) as QName;
156         classToQName.put(class1,qnameValue);
157         return qnameValue;
158     }
159 }