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 org.opendaylight.yangtools.yang.binding.DataContainer
21 import java.util.concurrent.ConcurrentMap
22 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
23 import com.google.common.collect.HashMultimap
24 import com.google.common.util.concurrent.SettableFuture
25 import java.util.concurrent.Future
26 import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl
27 import org.opendaylight.controller.sal.binding.dom.serializer.impl.LazyGeneratedCodecRegistry
28 import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService
29 import org.slf4j.LoggerFactory
30 import org.opendaylight.controller.sal.binding.dom.serializer.api.ValueWithQName
31 import org.opendaylight.controller.sal.binding.dom.serializer.api.DataContainerCodec
32 import org.opendaylight.yangtools.binding.generator.util.Types
33 import org.osgi.framework.BundleContext
34 import java.util.Hashtable
35 import org.osgi.framework.ServiceRegistration
36 import org.opendaylight.controller.sal.binding.impl.connect.dom.DeserializationException
37 import java.util.concurrent.Callable
39 class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingService, SchemaServiceListener, AutoCloseable {
44 private static val LOG = LoggerFactory.getLogger(RuntimeGeneratedMappingServiceImpl);
47 extension TransformerGenerator binding;
50 extension LazyGeneratedCodecRegistry registry;
53 val ConcurrentMap<Type, Type> typeDefinitions = new ConcurrentHashMap();
56 val ConcurrentMap<Type, GeneratedTypeBuilder> typeToDefinition = new ConcurrentHashMap();
59 val ConcurrentMap<Type, SchemaNode> typeToSchemaNode = new ConcurrentHashMap();
61 val promisedTypeDefinitions = HashMultimap.<Type, SettableFuture<GeneratedTypeBuilder>>create;
63 val promisedSchemas = HashMultimap.<Type, SettableFuture<SchemaNode>>create;
65 ServiceRegistration<SchemaServiceListener> listenerRegistration
67 override onGlobalContextUpdated(SchemaContext arg0) {
68 recreateBindingContext(arg0);
69 registry.onGlobalContextUpdated(arg0);
72 def recreateBindingContext(SchemaContext schemaContext) {
73 val newBinding = new BindingGeneratorImpl();
74 newBinding.generateTypes(schemaContext);
76 for (entry : newBinding.moduleContexts.entrySet) {
78 registry.onModuleContextAdded(schemaContext, entry.key, entry.value);
80 //val module = entry.key;
81 val context = entry.value;
82 updateBindingFor(context.childNodes, schemaContext);
83 updateBindingFor(context.cases, schemaContext);
85 val typedefs = context.typedefs;
86 for (typedef : typedefs.values) {
87 binding.typeDefinitions.put(typedef, typedef as GeneratedType);
89 val augmentations = context.augmentations;
90 for (augmentation : augmentations) {
91 binding.typeToDefinition.put(augmentation, augmentation);
94 binding.typeToAugmentation.putAll(context.typeToAugmentation);
98 override CompositeNode toDataDom(DataObject data) {
99 toCompositeNodeImpl(data);
102 override Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> toDataDom(
103 Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry) {
104 val key = toDataDom(entry.key)
105 val data = toCompositeNodeImpl(entry.value);
106 return new SimpleEntry(key, data);
109 private def CompositeNode toCompositeNodeImpl(DataObject object) {
110 val cls = object.implementedInterface;
112 val codec = registry.getCodecForDataObject(cls) as DataContainerCodec<DataObject>;
113 val ret = codec.serialize(new ValueWithQName(null, object));
114 return ret as CompositeNode;
117 private def waitForSchema(Class<? extends DataContainer> class1) {
118 val ref = Types.typeForClass(class1);
119 getSchemaWithRetry(ref);
122 override org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom(
123 InstanceIdentifier<? extends DataObject> path) {
124 for (arg : path.path) {
125 waitForSchema(arg.type);
127 return registry.instanceIdentifierCodec.serialize(path);
130 override dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode node) {
131 return tryDeserialization[ |
135 val targetType = path.targetType
136 val transformer = registry.getCodecForDataObject(targetType);
137 val ret = transformer.deserialize(node)?.value as DataObject;
142 override fromDataDom(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry) {
143 return tryDeserialization[ |
144 registry.instanceIdentifierCodec.deserialize(entry);
148 private static def <T> T tryDeserialization(Callable<T> deserializationBlock) throws DeserializationException {
150 deserializationBlock.call()
151 } catch (Exception e) {
152 // FIXME: Make this block providing more information.
153 throw new DeserializationException(e);
157 private def void updateBindingFor(Map<SchemaPath, GeneratedTypeBuilder> map, SchemaContext module) {
158 for (entry : map.entrySet) {
159 val schemaNode = SchemaContextUtil.findDataSchemaNode(module, entry.key);
161 //LOG.info("{} : {}",entry.key,entry.value.fullyQualifiedName)
162 if (schemaNode != null) {
163 typeToSchemaNode.put(entry.value, schemaNode);
164 typeToDefinition.put(entry.value, entry.value);
165 updatePromisedSchemas(entry.value, schemaNode);
170 public def void start(BundleContext ctx) {
171 binding = new TransformerGenerator(pool);
172 registry = new LazyGeneratedCodecRegistry()
173 registry.generator = binding
175 //binding.staticFieldsInitializer = registry
176 binding.listener = registry
177 binding.typeToDefinition = typeToDefinition
178 binding.typeToSchemaNode = typeToSchemaNode
179 binding.typeDefinitions = typeDefinitions
181 listenerRegistration = ctx.registerService(SchemaServiceListener, this, new Hashtable<String, String>());
185 private def getTypeDefinition(Type type) {
186 val typeDef = typeToDefinition.get(type);
187 if (typeDef !== null) {
190 return type.getTypeDefInFuture.get();
193 private def Future<GeneratedTypeBuilder> getTypeDefInFuture(Type type) {
194 val future = SettableFuture.<GeneratedTypeBuilder>create()
195 promisedTypeDefinitions.put(type, future);
199 private def void updatePromisedTypeDefinitions(GeneratedTypeBuilder builder) {
200 val futures = promisedTypeDefinitions.get(builder);
201 if (futures === null || futures.empty) {
204 for (future : futures) {
207 promisedTypeDefinitions.removeAll(builder);
210 private def getSchemaWithRetry(Type type) {
211 val typeDef = typeToSchemaNode.get(type);
212 if (typeDef !== null) {
215 return type.getSchemaInFuture.get();
218 private def Future<SchemaNode> getSchemaInFuture(Type type) {
219 val future = SettableFuture.<SchemaNode>create()
220 promisedSchemas.put(type, future);
224 private def void updatePromisedSchemas(Type builder, SchemaNode schema) {
225 val ref = new ReferencedTypeImpl(builder.packageName, builder.name);
226 val futures = promisedSchemas.get(ref);
227 if (futures === null || futures.empty) {
230 for (future : futures) {
233 promisedSchemas.removeAll(builder);
236 override close() throws Exception {
237 listenerRegistration?.unregister();