2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.sal.binding.generator.impl
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
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
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
38 class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
40 private static val LOG = LoggerFactory.getLogger(InstanceIdentifierCodecImpl);
41 val CodecRegistry codecRegistry;
43 val Map<Class<?>, Map<List<QName>, Class<?>>> classToPreviousAugment = new WeakHashMap;
45 public new(CodecRegistry registry) {
46 codecRegistry = registry;
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<org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument>(biArgs.size)
56 scannedPath.add(biArg.nodeType);
57 val baArg = deserializePathArgument(biArg,scannedPath)
59 val injectAugment = classToPreviousAugment.get(baType);
60 if(injectAugment != null) {
61 val augment = injectAugment.get(scannedPath) as Class<? extends DataObject>;
63 baArgs.add(new Item(augment));
68 val ret = new InstanceIdentifier(baArgs,baType as Class<? extends DataObject>);
69 LOG.debug("DOM Instance Identifier {} deserialized to {}",input,ret);
73 private def dispatch org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument deserializePathArgument(NodeIdentifier argument,List<QName> processedPath) {
74 val Class cls = codecRegistry.getClassForPath(processedPath);
79 private def dispatch org.opendaylight.yangtools.yang.binding.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);
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))
92 return new CompositeNodeTOImpl(predicates.nodeType,null,values);
95 override serialize(InstanceIdentifier input) {
96 var Class<?> previousAugmentation = null
97 val pathArgs = input.path as List<org.opendaylight.yangtools.yang.binding.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) {
103 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)
115 previousAugmentation = null;
117 previousQName = codecRegistry.getQNameForAugmentation(baArg.type as Class);
118 previousAugmentation = baArg.type;
121 val ret = new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(components);
122 LOG.debug("Binding Instance Identifier {} serialized to DOM InstanceIdentifier {}",input,ret);
126 def updateAugmentationInjection(Class<? extends DataObject> class1, ImmutableList<QName> list, Class<?> augmentation) {
127 if(classToPreviousAugment.get(class1) == null) {
128 classToPreviousAugment.put(class1,new ConcurrentHashMap());
130 classToPreviousAugment.get(class1).put(list,augmentation);
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) {
137 return new NodeIdentifier(qname);
139 return new NodeIdentifier(QName.create(previousQname,qname.localName));
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 val qname = BindingReflections.findQName(type);
148 val combinedInput = new ValueWithQName(previousQname,argument.key)
149 val compositeOutput = keyCodec.serialize(combinedInput as ValueWithQName);
150 for(outputValue :compositeOutput.value) {
151 predicates.put(outputValue.nodeType,outputValue.value);
153 if(previousQname == null) {
154 return new NodeIdentifierWithPredicates(qname,predicates);
156 return new NodeIdentifierWithPredicates(QName.create(previousQname,qname.localName),predicates);