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