Serialization to Json improvement
[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
26 class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
27     
28     private static val LOG = LoggerFactory.getLogger(InstanceIdentifierCodecImpl);
29     val CodecRegistry codecRegistry;
30     
31     val Map<Class<?>,QName> classToQName = new WeakHashMap;
32     
33     
34     public new(CodecRegistry registry) {
35         codecRegistry = registry;
36     }
37     
38     
39     override deserialize(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier input) {
40         var Class<?> baType = null
41         val biArgs = input.path
42         val scannedPath = new ArrayList<QName>(biArgs.size);
43         val baArgs = new ArrayList<org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument>(biArgs.size)
44         for(biArg : biArgs) {
45             scannedPath.add(biArg.nodeType);
46             val baArg = deserializePathArgument(biArg,scannedPath)
47             baArgs.add(baArg)
48             baType = baArg?.type
49         }
50         val ret = new InstanceIdentifier(baArgs,baType as Class<? extends DataObject>);
51         return ret;
52     }
53     
54     private def dispatch org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument deserializePathArgument(NodeIdentifier argument,List<QName> processedPath) {
55         val Class cls = codecRegistry.getClassForPath(processedPath);
56         return new Item(cls);
57     }
58     
59     
60     private def dispatch org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument deserializePathArgument(NodeIdentifierWithPredicates argument,List<QName> processedPath) {
61         val Class type = codecRegistry.getClassForPath(processedPath);
62         val IdentifierCodec codec = codecRegistry.getIdentifierCodecForIdentifiable(type);
63         val value = codec.deserialize(argument.toCompositeNode())?.value;
64         return CodecTypeUtils.newIdentifiableItem(type,value);
65     }
66     
67     def CompositeNode toCompositeNode(NodeIdentifierWithPredicates predicates) {
68         val keyValues = predicates.keyValues.entrySet;
69         val values = new ArrayList<Node<?>>(keyValues.size)
70         for(keyValue : keyValues) {
71             values.add(new SimpleNodeTOImpl(keyValue.key,null,keyValue.value))
72         }
73         return new CompositeNodeTOImpl(predicates.nodeType,null,values);
74     }
75     
76     override serialize(InstanceIdentifier input) {
77         val pathArgs = input.path as List<org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument>
78         var QName previousQName = null;
79         val components = new ArrayList<PathArgument>(pathArgs.size);
80         for(baArg : pathArgs) { 
81             codecRegistry.bindingClassEncountered(baArg.type);
82             val biArg = serializePathArgument(baArg,previousQName);
83             previousQName = biArg.nodeType;
84             components.add(biArg);
85         }
86         return new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(components);
87     }
88     
89     private def dispatch PathArgument serializePathArgument(Item argument, QName previousQname) {
90         val type = argument.type;
91         val qname = resolveQname(type);
92         if(previousQname == null) {
93             return new NodeIdentifier(qname);
94         }
95         return new NodeIdentifier(QName.create(previousQname,qname.localName));
96     }
97     
98     private def dispatch PathArgument serializePathArgument(IdentifiableItem argument, QName previousQname) {
99         val Map<QName,Object> predicates = new HashMap();
100         val type = argument.type;
101         val keyCodec = codecRegistry.getIdentifierCodecForIdentifiable(type);
102         val qname = resolveQname(type);
103         val combinedInput =  new ValueWithQName(previousQname,argument.key)
104         val compositeOutput = keyCodec.serialize(combinedInput as ValueWithQName);
105         for(outputValue :compositeOutput.value) {
106             predicates.put(outputValue.nodeType,outputValue.value);
107         }
108         if(previousQname == null) {
109             return new NodeIdentifierWithPredicates(qname,predicates);
110         }
111         return new NodeIdentifierWithPredicates(QName.create(previousQname,qname.localName),predicates);
112     }
113     
114     def resolveQname(Class class1) {
115         val qname = classToQName.get(class1);
116         if(qname !== null) {
117             return qname;
118         }
119         val qnameField = class1.getField("QNAME");
120         val qnameValue = qnameField.get(null) as QName;
121         classToQName.put(class1,qnameValue);
122     }
123 }