X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-binding-broker%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fsal%2Fbinding%2Fdom%2Fserializer%2Fimpl%2FRuntimeGeneratedMappingServiceImpl.xtend;h=13975cad4c807abc636870f99fbea2a921e4a312;hb=616a88111ea9603f0d6f93c7462e6dab39644fcf;hp=4614c60ca12e2f8ee14f9c73b6b93f4894d63c93;hpb=d490a11b531a724b9f46ca931b2c98e9527dde7f;p=controller.git diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/RuntimeGeneratedMappingServiceImpl.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/RuntimeGeneratedMappingServiceImpl.xtend index 4614c60ca1..13975cad4c 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/RuntimeGeneratedMappingServiceImpl.xtend +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/RuntimeGeneratedMappingServiceImpl.xtend @@ -17,18 +17,9 @@ import java.util.Map.Entry import java.util.AbstractMap.SimpleEntry import org.opendaylight.yangtools.yang.model.api.SchemaPath import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil -import java.util.ArrayList -import org.opendaylight.yangtools.yang.common.QName import org.opendaylight.yangtools.yang.binding.DataContainer -import static com.google.common.base.Preconditions.*; -import java.util.List -import org.opendaylight.yangtools.yang.data.api.Node -import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl -import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl -import org.opendaylight.yangtools.concepts.Delegator import java.util.concurrent.ConcurrentMap import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType -import org.opendaylight.yangtools.yang.binding.BindingCodec import com.google.common.collect.HashMultimap import com.google.common.util.concurrent.SettableFuture import java.util.concurrent.Future @@ -39,8 +30,21 @@ import org.slf4j.LoggerFactory import org.opendaylight.controller.sal.binding.dom.serializer.api.ValueWithQName import org.opendaylight.controller.sal.binding.dom.serializer.api.DataContainerCodec import org.opendaylight.yangtools.binding.generator.util.Types +import org.osgi.framework.BundleContext +import java.util.Hashtable +import org.osgi.framework.ServiceRegistration +import org.opendaylight.controller.sal.binding.impl.connect.dom.DeserializationException +import java.util.concurrent.Callable +import org.opendaylight.yangtools.yang.binding.Augmentation +import org.opendaylight.controller.sal.binding.impl.util.YangSchemaUtils +import org.opendaylight.controller.sal.binding.dom.serializer.api.AugmentationCodec +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates +import java.util.ArrayList +import org.opendaylight.yangtools.yang.data.api.Node +import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl +import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl -class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingService, SchemaServiceListener { +class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingService, SchemaServiceListener, AutoCloseable { @Property ClassPool pool; @@ -66,6 +70,8 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer val promisedSchemas = HashMultimap.>create; + ServiceRegistration listenerRegistration + override onGlobalContextUpdated(SchemaContext arg0) { recreateBindingContext(arg0); registry.onGlobalContextUpdated(arg0); @@ -78,22 +84,30 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer for (entry : newBinding.moduleContexts.entrySet) { registry.onModuleContextAdded(schemaContext, entry.key, entry.value); - + binding.pathToType.putAll(entry.value.childNodes) //val module = entry.key; val context = entry.value; updateBindingFor(context.childNodes, schemaContext); updateBindingFor(context.cases, schemaContext); - val typedefs = context.typedefs; - for (typedef : typedefs.values) { - binding.typeDefinitions.put(typedef, typedef as GeneratedType); + for (typedef : typedefs.entrySet) { + val typeRef = new ReferencedTypeImpl(typedef.value.packageName,typedef.value.name) + binding.typeDefinitions.put(typeRef, typedef.value as GeneratedType); + val schemaNode = YangSchemaUtils.findTypeDefinition(schemaContext,typedef.key); + if(schemaNode != null) { + + binding.typeToSchemaNode.put(typeRef,schemaNode); + } else { + LOG.error("Type definition for {} is not available",typedef.value); + } + } val augmentations = context.augmentations; for (augmentation : augmentations) { binding.typeToDefinition.put(augmentation, augmentation); } - + binding.typeToAugmentation.putAll(context.typeToAugmentation); } } @@ -104,9 +118,21 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer override Entry toDataDom( Entry, DataObject> entry) { + + try { val key = toDataDom(entry.key) - val data = toCompositeNodeImpl(entry.value); + var CompositeNode data; + if(Augmentation.isAssignableFrom(entry.key.targetType)) { + data = toCompositeNodeImpl(key,entry.value); + } else { + data = toCompositeNodeImpl(entry.value); + } return new SimpleEntry(key, data); + + } catch (Exception e) { + LOG.error("Error during serialization for {}.", entry.key,e); + throw e; + } } private def CompositeNode toCompositeNodeImpl(DataObject object) { @@ -116,8 +142,35 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer val ret = codec.serialize(new ValueWithQName(null, object)); return ret as CompositeNode; } + + + private def CompositeNode toCompositeNodeImpl(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier identifier,DataObject object) { + + //val cls = object.implementedInterface; + //waitForSchema(cls); + val last = identifier.path.last; + val codec = registry.getCodecForAugmentation(object.implementedInterface as Class) as AugmentationCodec; + val ret = codec.serialize(new ValueWithQName(last.nodeType, object)); + if(last instanceof NodeIdentifierWithPredicates) { + val predicates = last as NodeIdentifierWithPredicates; + val newNodes = new ArrayList>(predicates.keyValues.size); + for(predicate : predicates.keyValues.entrySet) { + newNodes.add(new SimpleNodeTOImpl(predicate.key,null,predicate.value)); + } + newNodes.addAll(ret.children); + return new CompositeNodeTOImpl(last.nodeType,null,newNodes); + } + return ret as CompositeNode; + } - private def waitForSchema(Class class1) { + private def void waitForSchema(Class class1) { + if(Augmentation.isAssignableFrom(class1)) { + /* FIXME: We should wait also for augmentations. Currently YANGTools does not provide correct + * mapping between java Augmentation classes and augmentations. + */ + return; + } + val ref = Types.typeForClass(class1); getSchemaWithRetry(ref); } @@ -131,28 +184,50 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer } override dataObjectFromDataDom(InstanceIdentifier path, CompositeNode node) { - if (node == null) { - return null; + return tryDeserialization[ | + if (node == null) { + return null; + } + val targetType = path.targetType + val transformer = registry.getCodecForDataObject(targetType); + val ret = transformer.deserialize(node)?.value as DataObject; + return ret; + ] + } + + override fromDataDom(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry) { + return tryDeserialization[ | + registry.instanceIdentifierCodec.deserialize(entry); + ] + } + + private static def T tryDeserialization(Callable deserializationBlock) throws DeserializationException { + try { + deserializationBlock.call() + } catch (Exception e) { + + // FIXME: Make this block providing more information. + throw new DeserializationException(e); } - val targetType = path.targetType - val transformer = registry.getCodecForDataObject(targetType); - val ret = transformer.deserialize(node)?.value as DataObject; - return ret; } private def void updateBindingFor(Map map, SchemaContext module) { + for (entry : map.entrySet) { val schemaNode = SchemaContextUtil.findDataSchemaNode(module, entry.key); + //LOG.info("{} : {}",entry.key,entry.value.fullyQualifiedName) + val typeRef = new ReferencedTypeImpl(entry.value.packageName,entry.value.name) + typeToDefinition.put(typeRef, entry.value); if (schemaNode != null) { - typeToSchemaNode.put(entry.value, schemaNode); - typeToDefinition.put(entry.value, entry.value); - updatePromisedSchemas(entry.value, schemaNode); + typeToSchemaNode.put(typeRef, schemaNode); + updatePromisedSchemas(typeRef, schemaNode); } + } } - public def void start() { + public def void start(BundleContext ctx) { binding = new TransformerGenerator(pool); registry = new LazyGeneratedCodecRegistry() registry.generator = binding @@ -162,7 +237,9 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer binding.typeToDefinition = typeToDefinition binding.typeToSchemaNode = typeToSchemaNode binding.typeDefinitions = typeDefinitions - + if (ctx !== null) { + listenerRegistration = ctx.registerService(SchemaServiceListener, this, new Hashtable()); + } } private def getTypeDefinition(Type type) { @@ -195,6 +272,7 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer if (typeDef !== null) { return typeDef; } + LOG.info("Thread blocked waiting for schema for: {}",type.fullyQualifiedName) return type.getSchemaInFuture.get(); } @@ -215,4 +293,9 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer } promisedSchemas.removeAll(builder); } + + override close() throws Exception { + listenerRegistration?.unregister(); + } + }