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%2Fimpl%2Fconnect%2Fdom%2FBindingMapping.xtend;fp=opendaylight%2Fmd-sal%2Fsal-binding-broker%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fsal%2Fbinding%2Fimpl%2Fconnect%2Fdom%2FBindingMapping.xtend;h=9a6330ea0f1ff999ff329bde76e2d8ca71f86c03;hb=d2f2d5a34ccd0a715ab6ea7c1f5ac61f16f6e6cc;hp=0000000000000000000000000000000000000000;hpb=87246fdb069fad43135b623971bdf6ebe7df828a;p=controller.git diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingMapping.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingMapping.xtend new file mode 100644 index 0000000000..9a6330ea0f --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingMapping.xtend @@ -0,0 +1,402 @@ +package org.opendaylight.controller.sal.binding.impl.connect.dom + +import org.opendaylight.yangtools.yang.common.QName +import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleContext +import java.util.List +import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder +import org.opendaylight.yangtools.sal.binding.model.api.Type +import org.opendaylight.yangtools.yang.model.api.SchemaNode +import java.util.Map +import org.opendaylight.yangtools.yang.model.api.SchemaPath +import org.opendaylight.yangtools.yang.model.api.SchemaContext +import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil +import org.opendaylight.yangtools.binding.generator.util.Types +import java.util.HashMap +import org.opendaylight.yangtools.yang.data.api.CompositeNode +import org.opendaylight.yangtools.yang.binding.DataContainer +import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl +import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty +import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType +import java.util.Collections +import java.util.ArrayList +import org.opendaylight.yangtools.yang.data.api.Node +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode +import org.opendaylight.yangtools.yang.model.api.DataNodeContainer +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode +import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode +import org.opendaylight.yangtools.yang.model.api.ChoiceNode +import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode +import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl +import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl +import org.opendaylight.yangtools.yang.model.api.NotificationDefinition +import org.opendaylight.yangtools.yang.model.api.TypeDefinition +import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition +import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier +import org.opendaylight.yangtools.yang.binding.DataObject +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates +import org.opendaylight.yangtools.yang.model.util.ExtendedType +import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject +import com.google.common.collect.FluentIterable +import org.opendaylight.yangtools.yang.data.api.SimpleNode +import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil +import org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils +import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition + +class BindingMapping { + + val Map typeToDefinition = new HashMap(); + val Map typeToSchemaNode = new HashMap(); + + def QName getSchemaNode(Class cls) { + val ref = Types.typeForClass(cls); + return typeToSchemaNode.get(ref)?.QName; + } + + def void updateBinding(SchemaContext schemaContext, ModuleContext moduleBindingContext) { + updateBindingFor(moduleBindingContext.childNodes, schemaContext); + + } + + def org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom( + InstanceIdentifier obj) { + val pathArguments = obj.path; + var Class parent; + val dataDomArgs = new ArrayList(); + for (pathArgument : pathArguments) { + dataDomArgs.add(pathArgument.toDataDomPathArgument(parent)); + parent = pathArgument.type; + } + + return new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(dataDomArgs); + } + + + + def DataObject dataObjectFromDataDom(InstanceIdentifier identifier, CompositeNode node) { + if (node == null) { + return null; + } + val targetClass = identifier.targetType; + val classLoader = targetClass.classLoader; + val ref = Types.typeForClass(targetClass); + val targetType = typeToDefinition.get(ref); + val targetSchema = typeToSchemaNode.get(ref); + return node.toDataObject(classLoader, targetType.toInstance, targetSchema); + + } + + def dispatch PathArgument toDataDomPathArgument(IdentifiableItem argument, Class parent) { + val Class rawType = argument.type; + val ref = Types.typeForClass(rawType); + val schemaType = typeToSchemaNode.get(ref); + val qname = schemaType.QName + + val Object key = argument.key; + val predicates = key.toPredicates(schemaType as ListSchemaNode); + + return new NodeIdentifierWithPredicates(qname, predicates); + } + + def dispatch PathArgument toDataDomPathArgument(Item argument, Class parent) { + val ref = Types.typeForClass(argument.type); + val qname = typeToSchemaNode.get(ref).QName + return new NodeIdentifier(qname); + } + + def Map toPredicates(Object identifier, ListSchemaNode node) { + val keyDefinitions = node.keyDefinition; + val map = new HashMap(); + for (keydef : keyDefinitions) { + val keyNode = node.getDataChildByName(keydef) as LeafSchemaNode; + val value = identifier.getSimpleValue(keydef, keyNode.type); + map.put(keydef, value.value); + } + return map; + } + + def void updateBindingFor(Map map, SchemaContext module) { + for (entry : map.entrySet) { + val schemaNode = SchemaContextUtil.findDataSchemaNode(module, entry.key); + typeToDefinition.put(entry.value, entry.value); + typeToSchemaNode.put(entry.value, schemaNode) + } + } + + def CompositeNode toCompositeNode(DataContainer data) { + val type = data.implementedInterface; + val typeRef = Types.typeForClass(type); + val schemaNode = typeToSchemaNode.get(typeRef); + val generatedType = typeToDefinition.get(typeRef); + + return data.toDataDom(schemaNode, generatedType); + } + + private def dispatch CompositeNode toDataDom(DataContainer data, ContainerSchemaNode node, + GeneratedTypeBuilder builder) { + val subnodes = data.toDataDomComponents(node); + return new CompositeNodeTOImpl(node.QName, null, subnodes); + } + + private def dispatch CompositeNode toDataDom(DataContainer data, NotificationDefinition node, + GeneratedTypeBuilder builder) { + val subnodes = data.toDataDomComponents(node); + return new CompositeNodeTOImpl(node.QName, null, subnodes); + } + + private def dispatch CompositeNode toDataDom(DataContainer data, ListSchemaNode node, + GeneratedTypeBuilder builder) { + val subnodes = data.toDataDomComponents(node); + return new CompositeNodeTOImpl(node.QName, null, subnodes); + } + + private def List> toDataDomComponents(DataContainer data, DataNodeContainer node) { + val subnodes = new ArrayList>(); + for (childNode : node.childNodes) { + val value = childNode.dataDomFromParent(data); + if (value !== null) { + subnodes.addAll(value); + } + } + return subnodes; + } + + private def List> dataDomFromParent(DataSchemaNode node, DataContainer container) { + if (node.augmenting) { + return Collections.emptyList(); + } + return dataDomFromParentImpl(node, container); + } + + private def dispatch List> dataDomFromParentImpl(LeafSchemaNode node, DataContainer container) { + val value = container.getSimpleValue(node.QName, node.type); + if (value !== null) { + return Collections.>singletonList(value); + } + return Collections.emptyList(); + } + + private def dispatch List> dataDomFromParentImpl(LeafListSchemaNode node, DataContainer container) { + val values = container.getSimpleValues(node); + if (values !== null) { + //val it = new ArrayList>(); + //for (value : values) { + //} + + } + return Collections.emptyList(); + } + + def getSimpleValues(DataContainer container, LeafListSchemaNode node) { + return Collections.emptyList(); + } + + private def dispatch List> dataDomFromParentImpl(ListSchemaNode node, DataContainer container) { + val qname = node.QName; + val values = container.getValue(qname, List) as List; + if (values === null) { + return Collections.emptyList; + } + val it = new ArrayList>(); + for (value : values) { + add(value.toCompositeNode()); + } + + return it; + } + + private def dispatch List> dataDomFromParentImpl(ChoiceNode node, DataContainer container) { + } + + private def dispatch List> serializeValueImpl(List list, GeneratedTypeBuilder builder, + ListSchemaNode node) { + val it = new ArrayList>(); + for (value : list) { + + val serVal = value.serializeValueImpl(builder, node); + if (serVal !== null) { + addAll(serVal); + } + } + return it; + } + + private def dispatch Node getSimpleValue(Object container, QName name, ExtendedType type) { + getSimpleValue(container, name, type.baseType); + } + + private def dispatch Node getSimpleValue(Object container, QName name, StringTypeDefinition type) { + val value = container.getValue(name, String); + if(value === null) return null; + return new SimpleNodeTOImpl(name, null, value); + } + + private def dispatch Node getSimpleValue(Object container, QName name, TypeDefinition type) { + val value = container.getValue(name, Object); + if(value === null) return null; + return new SimpleNodeTOImpl(name, null, value); + } + + private def dispatch Node getSimpleValue(Object container, QName name, BooleanTypeDefinition type) { + val value = container.getValue(name, Boolean); + if(value === null) return null; + return new SimpleNodeTOImpl(name, null, value); + } + + private def dispatch Node getSimpleValue(Object container, QName name, BinaryTypeDefinition type) { + val Object value = container.getValue(name, Object); //Constants.BYTES_CLASS); + if(value === null) return null; + return new SimpleNodeTOImpl(name, null, value); + } + + private def T getValue(Object object, QName node, Class type) { + val methodName = BindingGeneratorImpl.getterMethodName(node.localName, Types.typeForClass(type)); + var clz = object.class; + if (object instanceof DataContainer) { + clz = (object as DataContainer).implementedInterface; + } + val method = clz.getMethod(methodName); + if (method === null) { + return null; + } + val value = method.invoke(object); + if (value === null) { + return null; + } + if (type.isAssignableFrom(value.class)) { + return value as T; + } + return value.getEncapsulatedValue(type); + } + + private def T getEncapsulatedValue(Object value, Class type) { + val method = value.class.getMethod("getValue"); + if (method !== null && type.isAssignableFrom(method.returnType)) { + return method.invoke(value) as T; + } + return null; + } + + private def dispatch List> serializeValueImpl(DataContainer data, GeneratedTypeBuilder builder, + SchemaNode node) { + return Collections.>singletonList(data.toDataDom(node, builder)); + } + + private def dispatch List> serializeValueImpl(Object object, GeneratedTypeBuilder builder, + SchemaNode node) { + } + + def DataObject toDataObject(CompositeNode node, ClassLoader loader, GeneratedType type, SchemaNode schema) { + + // Nasty reflection hack (for now) + val builderClass = loader.loadClass(type.builderFQN); + val builder = builderClass.newInstance; + val buildMethod = builderClass.getMethod("build"); + + node.fillDataObject(builder, loader, type, schema); + + return buildMethod.invoke(builder) as DataObject; + } + + def dispatch void fillDataObject(CompositeNode node, Object builder, ClassLoader loader, GeneratedType type, + ListSchemaNode schema) { + + if (schema.keyDefinition !== null && !schema.keyDefinition.empty) { + + val value = node.keyToBindingKey(loader, type, schema); + builder.setProperty("key", value); + } + } + + def dispatch void fillDataObject(CompositeNode node, Object builder, ClassLoader loader, GeneratedType type, + ContainerSchemaNode schema) { + } + + + def Object keyToBindingKey(CompositeNode node, ClassLoader loader, GeneratedType type, ListSchemaNode schema) { + val keyClass = loader.loadClass(type.keyFQN); + val constructor = keyClass.constructors.get(0); + val keyType = type.keyTypeProperties; + val args = new ArrayList(); + for (key : schema.keyDefinition) { + val keyProperty = keyType.get(BindingGeneratorUtil.parseToClassName(key.localName)); + val domKeyValue = node.getFirstSimpleByName(key); + val keyValue = domKeyValue.deserializeSimpleValue(loader, keyProperty.returnType, + schema.getDataChildByName(key)); + args.add(keyValue); + } + return ClassLoaderUtils.construct(constructor, args); + } + + def dispatch Object deserializeSimpleValue(SimpleNode node, ClassLoader loader, Type type, + LeafSchemaNode node2) { + deserializeSimpleValueImpl(node, loader, type, node2.type); + } + + def dispatch Object deserializeSimpleValue(SimpleNode node, ClassLoader loader, Type type, + LeafListSchemaNode node2) { + deserializeSimpleValueImpl(node, loader, type, node2.type); + } + + def dispatch Object deserializeSimpleValueImpl(SimpleNode node, ClassLoader loader, Type type, + ExtendedType definition) { + deserializeSimpleValueImpl(node, loader, type, definition.baseType); + } + + def dispatch Object deserializeSimpleValueImpl(SimpleNode node, ClassLoader loader, Type type, + StringTypeDefinition definition) { + if (type instanceof GeneratedTransferObject) { + val cls = loader.getClassForType(type); + val const = cls.getConstructor(String); + val str = String.valueOf(node.value); + return const.newInstance(str); + } + return node.value; + } + + def Class getClassForType(ClassLoader loader, Type type) { + loader.loadClass(type.fullyQualifiedName); + } + + def dispatch Object deserializeSimpleValueImpl(SimpleNode node, ClassLoader loader, Type type, + TypeDefinition definition) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + def Map getKeyTypeProperties(GeneratedType type) { + val method = FluentIterable.from(type.methodDefinitions).findFirst[name == "getKey"] + val key = method.returnType as GeneratedTransferObject; + val ret = new HashMap(); + for (prop : key.properties) { + ret.put(prop.name, prop); + } + return ret; + } + + def void setProperty(Object object, String property, Object value) { + val cls = object.class; + val valMethod = cls.getMethod("set" + property.toFirstUpper, value.class); + if (valMethod != null) + valMethod.invoke(object, value); + } + + def String getBuilderFQN(Type type) '''«type.fullyQualifiedName»Builder''' + + def String getKeyFQN(Type type) '''«type.fullyQualifiedName»Key''' + +} + +@Data +class PropertyCapture { + + @Property + val Type returnType; + @Property + val String name; + +}