1 package org.opendaylight.controller.sal.binding.dom.serializer.impl
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.concurrent.ConcurrentHashMap
13 import org.opendaylight.yangtools.yang.data.api.CompositeNode
14 import org.opendaylight.yangtools.yang.binding.DataObject
15 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
16 import java.util.Map.Entry
17 import java.util.AbstractMap.SimpleEntry
18 import org.opendaylight.yangtools.yang.model.api.SchemaPath
19 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil
20 import java.util.ArrayList
21 import org.opendaylight.yangtools.yang.common.QName
22 import org.opendaylight.yangtools.yang.binding.DataContainer
23 import static com.google.common.base.Preconditions.*;
25 import org.opendaylight.yangtools.yang.data.api.Node
26 import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
27 import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
28 import org.opendaylight.yangtools.concepts.Delegator
29 import java.util.concurrent.ConcurrentMap
30 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
31 import org.opendaylight.yangtools.yang.binding.BindingCodec
32 import com.google.common.collect.HashMultimap
33 import com.google.common.util.concurrent.SettableFuture
34 import java.util.concurrent.Future
35 import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl
36 import org.opendaylight.controller.sal.binding.dom.serializer.impl.LazyGeneratedCodecRegistry
37 import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService
38 import org.slf4j.LoggerFactory
39 import org.opendaylight.controller.sal.binding.dom.serializer.api.ValueWithQName
40 import org.opendaylight.controller.sal.binding.dom.serializer.api.DataContainerCodec
41 import org.opendaylight.yangtools.binding.generator.util.Types
42 import org.osgi.framework.BundleContext
43 import java.util.Hashtable
44 import org.osgi.framework.ServiceRegistration
46 class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingService, SchemaServiceListener, AutoCloseable {
51 private static val LOG = LoggerFactory.getLogger(RuntimeGeneratedMappingServiceImpl);
54 extension TransformerGenerator binding;
57 extension LazyGeneratedCodecRegistry registry;
60 val ConcurrentMap<Type, Type> typeDefinitions = new ConcurrentHashMap();
63 val ConcurrentMap<Type, GeneratedTypeBuilder> typeToDefinition = new ConcurrentHashMap();
66 val ConcurrentMap<Type, SchemaNode> typeToSchemaNode = new ConcurrentHashMap();
68 val promisedTypeDefinitions = HashMultimap.<Type, SettableFuture<GeneratedTypeBuilder>>create;
70 val promisedSchemas = HashMultimap.<Type, SettableFuture<SchemaNode>>create;
72 ServiceRegistration<SchemaServiceListener> listenerRegistration
74 override onGlobalContextUpdated(SchemaContext arg0) {
75 recreateBindingContext(arg0);
76 registry.onGlobalContextUpdated(arg0);
79 def recreateBindingContext(SchemaContext schemaContext) {
80 val newBinding = new BindingGeneratorImpl();
81 newBinding.generateTypes(schemaContext);
83 for (entry : newBinding.moduleContexts.entrySet) {
85 registry.onModuleContextAdded(schemaContext, entry.key, entry.value);
87 //val module = entry.key;
88 val context = entry.value;
89 updateBindingFor(context.childNodes, schemaContext);
90 updateBindingFor(context.cases, schemaContext);
93 val typedefs = context.typedefs;
94 for (typedef : typedefs.values) {
95 binding.typeDefinitions.put(typedef, typedef as GeneratedType);
97 val augmentations = context.augmentations;
98 for (augmentation : augmentations) {
99 binding.typeToDefinition.put(augmentation, augmentation);
102 binding.typeToAugmentation.putAll(context.typeToAugmentation);
106 override CompositeNode toDataDom(DataObject data) {
107 toCompositeNodeImpl(data);
110 override Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> toDataDom(
111 Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry) {
112 val key = toDataDom(entry.key)
113 val data = toCompositeNodeImpl(entry.value);
114 return new SimpleEntry(key, data);
117 private def CompositeNode toCompositeNodeImpl(DataObject object) {
118 val cls = object.implementedInterface;
120 val codec = registry.getCodecForDataObject(cls) as DataContainerCodec<DataObject>;
121 val ret = codec.serialize(new ValueWithQName(null, object));
122 return ret as CompositeNode;
125 private def waitForSchema(Class<? extends DataContainer> class1) {
126 val ref = Types.typeForClass(class1);
127 getSchemaWithRetry(ref);
130 override org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom(
131 InstanceIdentifier<? extends DataObject> path) {
132 for (arg : path.path) {
133 waitForSchema(arg.type);
135 return registry.instanceIdentifierCodec.serialize(path);
138 override dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode node) {
142 val targetType = path.targetType
143 val transformer = registry.getCodecForDataObject(targetType);
144 val ret = transformer.deserialize(node)?.value as DataObject;
148 private def void updateBindingFor(Map<SchemaPath, GeneratedTypeBuilder> map, SchemaContext module) {
149 for (entry : map.entrySet) {
150 val schemaNode = SchemaContextUtil.findDataSchemaNode(module, entry.key);
151 //LOG.info("{} : {}",entry.key,entry.value.fullyQualifiedName)
152 if (schemaNode != null) {
153 typeToSchemaNode.put(entry.value, schemaNode);
154 typeToDefinition.put(entry.value, entry.value);
155 updatePromisedSchemas(entry.value, schemaNode);
160 public def void start(BundleContext ctx) {
161 binding = new TransformerGenerator(pool);
162 registry = new LazyGeneratedCodecRegistry()
163 registry.generator = binding
165 //binding.staticFieldsInitializer = registry
166 binding.listener = registry
167 binding.typeToDefinition = typeToDefinition
168 binding.typeToSchemaNode = typeToSchemaNode
169 binding.typeDefinitions = typeDefinitions
171 listenerRegistration = ctx.registerService(SchemaServiceListener,this,new Hashtable<String,String>());
175 private def getTypeDefinition(Type type) {
176 val typeDef = typeToDefinition.get(type);
177 if (typeDef !== null) {
180 return type.getTypeDefInFuture.get();
183 private def Future<GeneratedTypeBuilder> getTypeDefInFuture(Type type) {
184 val future = SettableFuture.<GeneratedTypeBuilder>create()
185 promisedTypeDefinitions.put(type, future);
189 private def void updatePromisedTypeDefinitions(GeneratedTypeBuilder builder) {
190 val futures = promisedTypeDefinitions.get(builder);
191 if (futures === null || futures.empty) {
194 for (future : futures) {
197 promisedTypeDefinitions.removeAll(builder);
200 private def getSchemaWithRetry(Type type) {
201 val typeDef = typeToSchemaNode.get(type);
202 if (typeDef !== null) {
205 return type.getSchemaInFuture.get();
208 private def Future<SchemaNode> getSchemaInFuture(Type type) {
209 val future = SettableFuture.<SchemaNode>create()
210 promisedSchemas.put(type, future);
214 private def void updatePromisedSchemas(Type builder, SchemaNode schema) {
215 val ref = new ReferencedTypeImpl(builder.packageName, builder.name);
216 val futures = promisedSchemas.get(ref);
217 if (futures === null || futures.empty) {
220 for (future : futures) {
223 promisedSchemas.removeAll(builder);
226 override close() throws Exception {
227 listenerRegistration?.unregister();