1 package org.opendaylight.controller.sal.binding.impl.connect.dom
3 import org.opendaylight.controller.sal.binding.dom.serializer.impl.TransformerGenerator
4 import javassist.ClassPool
5 import org.opendaylight.yangtools.yang.model.api.SchemaContext
6 import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener
7 import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl
9 import org.opendaylight.yangtools.sal.binding.model.api.Type
10 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder
11 import org.opendaylight.yangtools.yang.model.api.SchemaNode
12 import java.util.HashMap
13 import java.util.concurrent.ConcurrentHashMap
14 import org.opendaylight.yangtools.yang.data.api.CompositeNode
15 import org.opendaylight.yangtools.yang.binding.DataObject
16 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
17 import java.util.Map.Entry
18 import java.util.AbstractMap.SimpleEntry
19 import org.opendaylight.yangtools.yang.model.api.SchemaPath
20 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil
21 import java.util.ArrayList
22 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
23 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem
24 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
25 import org.opendaylight.yangtools.binding.generator.util.Types
26 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
27 import org.opendaylight.yangtools.yang.common.QName
28 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
29 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item
30 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier
31 import org.opendaylight.yangtools.yang.binding.DataContainer
32 import static com.google.common.base.Preconditions.*;
34 import org.opendaylight.yangtools.yang.data.api.Node
35 import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
36 import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
37 import org.opendaylight.yangtools.concepts.Delegator
38 import java.util.concurrent.ConcurrentMap
39 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
40 import org.opendaylight.yangtools.yang.binding.BindingCodec
42 class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingService, SchemaServiceListener {
47 extension TransformerGenerator binding;
49 val ConcurrentMap<Type, Type> typeDefinitions = new ConcurrentHashMap();
51 val ConcurrentMap<Class<? extends DataContainer>, TransformerWrapper> domSerializers = new ConcurrentHashMap();
54 val ConcurrentMap<Type, GeneratedTypeBuilder> typeToDefinition = new ConcurrentHashMap();
57 val ConcurrentMap<Type, SchemaNode> typeToSchemaNode = new ConcurrentHashMap();
59 override onGlobalContextUpdated(SchemaContext arg0) {
60 recreateBindingContext(arg0);
63 def recreateBindingContext(SchemaContext schemaContext) {
64 val newBinding = new BindingGeneratorImpl();
65 newBinding.generateTypes(schemaContext);
67 for (entry : newBinding.moduleContexts.entrySet) {
69 //val module = entry.key;
70 val context = entry.value;
71 updateBindingFor(context.childNodes, schemaContext);
73 val typedefs = context.typedefs;
74 for(typedef : typedefs.values) {
75 binding.typeDefinitions.put(typedef,typedef as GeneratedType);
80 override CompositeNode toDataDom(DataObject data) {
81 toCompositeNodeImpl(data);
84 override Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> toDataDom(
85 Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry) {
86 val key = toDataDomImpl(entry.key);
87 val data = toCompositeNodeImpl(entry.value);
88 return new SimpleEntry(key, data);
91 private def CompositeNode toCompositeNodeImpl(DataObject object) {
92 val cls = object.implementedInterface;
93 val transformator = resolveTransformator(cls);
94 val ret = transformator.transform(object);
98 private def resolveTransformator(Class<? extends DataContainer> cls) {
99 val serializer = domSerializers.get(cls);
100 if (serializer !== null) {
103 val transformerClass = binding.transformerFor(cls).newInstance;
104 val wrapper = new TransformerWrapper(transformerClass);
105 domSerializers.putIfAbsent(cls, wrapper);
109 private def org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDomImpl(
110 InstanceIdentifier<? extends DataObject> object) {
111 val pathArguments = object.path;
112 var Class<? extends DataObject> parent;
113 val dataDomArgs = new ArrayList<PathArgument>();
114 for (pathArgument : pathArguments) {
115 dataDomArgs.add(pathArgument.toDataDomPathArgument(parent));
116 parent = pathArgument.type;
119 return new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(dataDomArgs);
122 override org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom(
123 InstanceIdentifier<? extends DataObject> path) {
124 return toDataDomImpl(path);
127 override dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode result) {
128 return dataObjectFromDataDomImpl(path, result);
131 def DataObject dataObjectFromDataDomImpl(InstanceIdentifier<? extends DataObject> identifier, CompositeNode node) {
132 val targetType = identifier.targetType
133 val transformer = resolveTransformator(targetType);
134 val ret = transformer.deserialize(node) as DataObject;
138 def void updateBindingFor(Map<SchemaPath, GeneratedTypeBuilder> map, SchemaContext module) {
139 for (entry : map.entrySet) {
140 val schemaNode = SchemaContextUtil.findDataSchemaNode(module, entry.key);
141 typeToDefinition.put(entry.value, entry.value);
142 typeToSchemaNode.put(entry.value, schemaNode)
146 private def dispatch PathArgument toDataDomPathArgument(IdentifiableItem argument,
147 Class<? extends DataObject> parent) {
148 val Class<?> rawType = argument.type;
149 val ref = Types.typeForClass(rawType);
150 val schemaType = typeToSchemaNode.get(ref);
151 val qname = schemaType.QName
153 val Object key = argument.key;
154 val predicates = key.toPredicates(schemaType as ListSchemaNode);
156 return new NodeIdentifierWithPredicates(qname, predicates);
159 private def Map<QName, Object> toPredicates(Object identifier, ListSchemaNode node) {
160 val keyDefinitions = node.keyDefinition;
161 val map = new HashMap<QName, Object>();
162 for (keydef : keyDefinitions) {
163 val keyNode = node.getDataChildByName(keydef) as LeafSchemaNode;
164 val value = BindingMapping.getSimpleValue(identifier, keydef, keyNode.type);
165 map.put(keydef, value.value);
170 private def dispatch PathArgument toDataDomPathArgument(Item<?> argument, Class<? extends DataObject> parent) {
171 val ref = Types.typeForClass(argument.type);
172 val qname = typeToSchemaNode.get(ref).QName
173 return new NodeIdentifier(qname);
176 public def void start() {
177 pool = new ClassPool()
178 binding = new TransformerGenerator(pool);
180 binding.typeToDefinition = typeToDefinition
181 binding.typeToSchemaNode = typeToSchemaNode
182 binding.typeDefinitions = typeDefinitions
187 class TransformerWrapper implements // //
188 Delegator<BindingCodec<Map<QName, Object>, Object>> {
191 val BindingCodec<Map<QName, Object>, Object> delegate;
193 new(BindingCodec<Map<QName, Object>, Object> delegate) {
194 _delegate = delegate;
197 def CompositeNode transform(DataObject input) {
198 val ret = delegate.serialize(input);
199 val node = toNode(ret)
200 return node as CompositeNode;
203 def deserialize(CompositeNode node) {
207 val Map mapCapture = node
208 return delegate.deserialize(mapCapture as Map<QName,Object>);
211 static def Node<?> toNode(Map map) {
212 val nodeMap = map as Map<QName,Object>;
213 checkArgument(map.size == 1);
214 val elem = nodeMap.entrySet.iterator.next;
215 val qname = elem.key;
216 val value = elem.value;
217 toNodeImpl(qname, value);
220 static def dispatch Node<?> toNodeImpl(QName name, List objects) {
221 val values = new ArrayList<Node<?>>(objects.size);
222 for (obj : objects) {
223 values.add(toNode(obj as Map));
225 return new CompositeNodeTOImpl(name, null, values);
228 static def dispatch Node<?> toNodeImpl(QName name, Map<QName, Object> object) {
229 throw new UnsupportedOperationException("Unsupported node hierarchy.");
232 static def dispatch Node<?> toNodeImpl(QName name, Object object) {
233 return new SimpleNodeTOImpl(name, null, object);