Merge "Global cleanup of restconf client dependencies"
[yangtools.git] / code-generator / binding-generator-impl / src / main / java / org / opendaylight / yangtools / sal / binding / generator / impl / InstanceIdentifierCodecImpl.xtend
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.yangtools.sal.binding.generator.impl
9
10 import com.google.common.collect.ImmutableList
11 import java.util.ArrayList
12 import java.util.Collections
13 import java.util.HashMap
14 import java.util.List
15 import java.util.Map
16 import java.util.WeakHashMap
17 import java.util.concurrent.ConcurrentHashMap
18 import org.opendaylight.yangtools.yang.binding.Augmentation
19 import org.opendaylight.yangtools.yang.binding.DataObject
20 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
21 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem
22 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item
23 import org.opendaylight.yangtools.yang.binding.util.BindingReflections
24 import org.opendaylight.yangtools.yang.common.QName
25 import org.opendaylight.yangtools.yang.data.api.CompositeNode
26 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier
27 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
28 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
29 import org.opendaylight.yangtools.yang.data.api.Node
30 import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
31 import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
32 import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry
33 import org.opendaylight.yangtools.yang.data.impl.codec.IdentifierCodec
34 import org.opendaylight.yangtools.yang.data.impl.codec.InstanceIdentifierCodec
35 import org.opendaylight.yangtools.yang.data.impl.codec.ValueWithQName
36 import org.slf4j.LoggerFactory
37
38 class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
39
40     private static val LOG = LoggerFactory.getLogger(InstanceIdentifierCodecImpl);
41     val CodecRegistry codecRegistry;
42
43     val Map<Class<?>, Map<List<QName>, Class<?>>> classToPreviousAugment = Collections.synchronizedMap(new WeakHashMap);
44
45     public new(CodecRegistry registry) {
46         codecRegistry = registry;
47     }
48
49
50     override deserialize(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier input) {
51         var Class<?> baType = null
52         val biArgs = input.path
53         val scannedPath = new ArrayList<QName>(biArgs.size);
54         val baArgs = new ArrayList<InstanceIdentifier.PathArgument>(biArgs.size)
55         for(biArg : biArgs) {
56             scannedPath.add(biArg.nodeType);
57             val baArg = deserializePathArgument(biArg,scannedPath)
58             baType = baArg?.type
59             val injectAugment = classToPreviousAugment.get(baType);
60             if(injectAugment != null) {
61                 val augment = injectAugment.get(scannedPath) as Class<? extends DataObject>;
62                 if(augment != null) {
63                     baArgs.add(new Item(augment));
64                 }
65             }
66             baArgs.add(baArg)
67         }
68         val ret = new InstanceIdentifier(baArgs,baType as Class<? extends DataObject>);
69         LOG.debug("DOM Instance Identifier {} deserialized to {}",input,ret);
70         return ret;
71     }
72
73     private def dispatch InstanceIdentifier.PathArgument deserializePathArgument(NodeIdentifier argument,List<QName> processedPath) {
74         val Class cls = codecRegistry.getClassForPath(processedPath);
75         return new Item(cls);
76     }
77
78
79     private def dispatch InstanceIdentifier.PathArgument deserializePathArgument(NodeIdentifierWithPredicates argument,List<QName> processedPath) {
80         val Class type = codecRegistry.getClassForPath(processedPath);
81         val IdentifierCodec codec = codecRegistry.getIdentifierCodecForIdentifiable(type);
82         val value = codec.deserialize(argument.toCompositeNode())?.value;
83         return CodecTypeUtils.newIdentifiableItem(type,value);
84     }
85
86     def CompositeNode toCompositeNode(NodeIdentifierWithPredicates predicates) {
87         val keyValues = predicates.keyValues.entrySet;
88         val values = new ArrayList<Node<?>>(keyValues.size)
89         for(keyValue : keyValues) {
90             values.add(new SimpleNodeTOImpl(keyValue.key,null,keyValue.value))
91         }
92         return new CompositeNodeTOImpl(predicates.nodeType,null,values);
93     }
94
95     override serialize(InstanceIdentifier<?> input) {
96         var Class<?> previousAugmentation = null
97         val pathArgs = input.path as List<InstanceIdentifier.PathArgument>
98         var QName previousQName = null;
99         val components = new ArrayList<PathArgument>(pathArgs.size);
100         val qnamePath = new ArrayList<QName>(pathArgs.size);
101         for(baArg : pathArgs) {
102
103             if(!Augmentation.isAssignableFrom(baArg.type)) {
104                 val biArg = serializePathArgument(baArg,previousQName);
105                 previousQName = biArg.nodeType;
106                 components.add(biArg);
107                 qnamePath.add(biArg.nodeType);
108                 val immutableList = ImmutableList.copyOf(qnamePath);
109                 codecRegistry.putPathToClass(immutableList,baArg.type);
110                 if(previousAugmentation !== null) {
111                     updateAugmentationInjection(baArg.type,immutableList,previousAugmentation)
112                 }
113
114                 previousAugmentation = null;
115             } else {
116                 previousQName = codecRegistry.getQNameForAugmentation(baArg.type as Class<?>);
117                 previousAugmentation = baArg.type;
118             }
119         }
120         val ret = new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(components);
121         LOG.debug("Binding Instance Identifier {} serialized to DOM InstanceIdentifier {}",input,ret);
122         return ret;
123     }
124
125     def updateAugmentationInjection(Class<? extends DataObject> class1, ImmutableList<QName> list, Class<?> augmentation) {
126         if(classToPreviousAugment.get(class1) == null) {
127             classToPreviousAugment.put(class1,new ConcurrentHashMap());
128         }
129         classToPreviousAugment.get(class1).put(list,augmentation);
130     }
131
132     private def dispatch PathArgument serializePathArgument(Item<?> argument, QName previousQname) {
133         val type = argument.type;
134         val qname = BindingReflections.findQName(type);
135         if(previousQname == null || (BindingReflections.isAugmentationChild(argument.type))) {
136             return new NodeIdentifier(qname);
137         }
138         return new NodeIdentifier(QName.create(previousQname,qname.localName));
139     }
140
141     @SuppressWarnings("rawtypes")
142     private def dispatch PathArgument serializePathArgument(IdentifiableItem argument, QName previousQname) {
143         val Map<QName,Object> predicates = new HashMap();
144         val type = argument.type;
145         val keyCodec = codecRegistry.getIdentifierCodecForIdentifiable(type);
146         var QName qname = BindingReflections.findQName(type);
147         if(previousQname != null && !(BindingReflections.isAugmentationChild(argument.type))) {
148             qname = QName.create(previousQname,qname.localName);
149         }
150         val combinedInput =  new ValueWithQName(previousQname,argument.key)
151         val compositeOutput = keyCodec.serialize(combinedInput as ValueWithQName);
152         for(outputValue :compositeOutput.value) {
153             predicates.put(outputValue.nodeType,outputValue.value);
154         }
155         if(previousQname == null) {
156             return new NodeIdentifierWithPredicates(qname,predicates);
157         }
158         return new NodeIdentifierWithPredicates(qname,predicates);
159     }
160 }