import java.util.Set
import java.util.HashMap
import org.opendaylight.controller.sal.binding.spi.RpcRoutingTable
-import static org.opendaylight.controller.sal.binding.codegen.impl.XtendHelper.*
import org.opendaylight.yangtools.yang.binding.DataContainer
import org.opendaylight.yangtools.yang.binding.RpcImplementation
Class<C> cls) {
return new RpcRoutingTableImpl<>(cls);
}
-
- public static String foo() {
- return "Foo";
- }
}
import javassist.NotFoundException
import javassist.LoaderClassPath
import javassist.ClassClassPath
+import java.util.concurrent.locks.Lock
+import java.util.concurrent.locks.ReentrantLock
class JavassistUtils {
ClassPool classPool
+
+ @Property
+ val Lock lock = new ReentrantLock();
new(ClassPool pool) {
classPool = pool;
}
def CtClass createClass(String fqn, ClassGenerator cls) {
+
val target = classPool.makeClass(fqn);
cls.process(target);
return target;
}
def CtClass createClass(String fqn, CtClass superInterface, ClassGenerator cls) {
+
val target = classPool.makeClass(fqn);
target.implementsType(superInterface);
cls.process(target);
addField(field);
return field;
}
+
+ def CtField staticField(CtClass it, String name, Class<?> returnValue) {
+ val field = new CtField(returnValue.asCtClass, name, it);
+ field.modifiers = Modifier.PUBLIC + Modifier.STATIC
+ addField(field);
+ return field;
+ }
def get(ClassPool pool, Class<?> cls) {
try {
--- /dev/null
+package org.opendaylight.controller.sal.binding.dom.serializer.api;
+
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+
+public interface AugmentationCodec<A extends Augmentation<?>> extends DomCodec<A> {
+
+
+ @Override
+ public CompositeNode serialize(ValueWithQName<A> input);
+
+ @Override
+ public ValueWithQName<A> deserialize(Node<?> input);
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.dom.serializer.api;
+
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+
+public interface ChoiceCaseCodec<C extends DataContainer> extends DataContainerCodec<C> {
+
+ @Override
+ public CompositeNode serialize(ValueWithQName<C> input);
+
+ @Override
+ public ValueWithQName<C> deserialize(Node<?> input);
+
+ public boolean isAcceptable(Node<?> input);
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.dom.serializer.api;
+
+import org.opendaylight.yangtools.yang.data.api.Node;
+
+public interface ChoiceCodec<C> extends DomCodec<C> {
+
+ @Override
+ public Node<?> serialize(ValueWithQName<C> input);
+
+ @Override
+ public ValueWithQName<C> deserialize(Node<?> input);
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.dom.serializer.api;
+
+import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+
+import java.util.List;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.controller.sal.binding.dom.serializer.api.IdentifierCodec;
+
+
+public interface CodecRegistry {
+
+ InstanceIdentifierCodec getInstanceIdentifierCodec();
+
+ <T extends DataContainer> DataContainerCodec<T> getCodecForDataObject(Class<T> object);
+
+ <T extends Identifiable<?>> IdentifierCodec<?> getIdentifierCodecForIdentifiable(Class<T> object);
+
+ <T extends Identifier<?>> IdentifierCodec<T> getCodecForIdentifier(Class<T> object);
+
+ <T extends Augmentation<?>> AugmentationCodec<T> getCodecForAugmentation(Class<T> object);
+
+ Class<?> getClassForPath(List<QName> names);
+
+ IdentifierCodec<?> getKeyCodecForPath(List<QName> names);
+
+
+ void bindingClassEncountered(Class<?> cls);
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.dom.serializer.api;
+
+import org.opendaylight.yangtools.yang.binding.BindingCodec;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+
+public interface DataContainerCodec<T extends DataContainer> extends DomCodec<T> {
+
+
+ @Override
+ public ValueWithQName<T> deserialize(Node<?> input);
+
+ @Override
+ public CompositeNode serialize(ValueWithQName<T> input);
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.dom.serializer.api;
+
+import org.opendaylight.yangtools.yang.binding.BindingCodec;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.Node;
+
+public interface DomCodec<I> extends BindingCodec<Node<?>, ValueWithQName<I>>{
+
+
+ @Override
+ public Node<?> serialize(ValueWithQName<I> input);
+
+
+ @Override
+ public ValueWithQName<I> deserialize(Node<?> input);
+
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.dom.serializer.api;
+
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+
+public interface IdentifierCodec<I extends Identifier<?>> extends DomCodec<I> {
+
+ @Override
+ public ValueWithQName<I> deserialize(Node<?> input);
+
+ @Override
+ public CompositeNode serialize(ValueWithQName<I> input);
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.dom.serializer.api;
+
+import org.opendaylight.yangtools.yang.binding.BindingCodec;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public interface InstanceIdentifierCodec extends BindingCodec<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier,InstanceIdentifier<?>> {
+
+ @Override
+ public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier serialize(InstanceIdentifier<?> input);
+
+ @Override
+ public InstanceIdentifier<?> deserialize(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier input);
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.dom.serializer.api;
+
+import java.util.Map.Entry;
+
+import org.opendaylight.yangtools.yang.common.QName;
+
+public class ValueWithQName<V> implements Entry<QName, V>{
+
+ final QName qname;
+ final V value;
+
+ public ValueWithQName(QName qname, V value) {
+ super();
+ this.qname = qname;
+ this.value = value;
+ }
+
+ public QName getQname() {
+ return qname;
+ }
+
+ public V getValue() {
+ return value;
+ }
+
+ @Override
+ public QName getKey() {
+ return qname;
+ }
+
+ @Override
+ public V setValue(V value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((qname == null) ? 0 : qname.hashCode());
+ result = prime * result + ((value == null) ? 0 : value.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ @SuppressWarnings("rawtypes")
+ ValueWithQName other = (ValueWithQName) obj;
+ if (qname == null) {
+ if (other.qname != null)
+ return false;
+ } else if (!qname.equals(other.qname))
+ return false;
+ if (value == null) {
+ if (other.value != null) {
+ return false;
+ }
+ } else if (!value.equals(other.value)) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.dom.serializer.impl;
+
+public interface BindingClassListener {
+
+ void onBindingClassCaptured(Class<?> cls);
+
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.dom.serializer.impl;
+
+import java.lang.reflect.Field;
+import java.util.Map;
+
+import org.opendaylight.controller.sal.binding.dom.serializer.api.InstanceIdentifierCodec;
+import org.opendaylight.yangtools.yang.binding.BindingCodec;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+
+public class CodecMapping {
+
+ public static final String INSTANCE_IDENTIFIER_CODEC = "INSTANCE_IDENTIFIER_CODEC";
+ public static final String CLASS_TO_CASE_MAP = "CLASS_TO_CASE";
+ public static final String COMPOSITE_TO_CASE = "COMPOSITE_TO_CASE";
+ public static final String AUGMENTATION_CODEC = "AUGMENTATION_CODEC";
+
+ public static void setIdentifierCodec(Class obj,InstanceIdentifierCodec codec) {
+ Field instanceIdField;
+ try {
+ instanceIdField = obj.getField(INSTANCE_IDENTIFIER_CODEC);
+ instanceIdField.set(null, codec);
+ } catch (NoSuchFieldException e) {
+ // NOOP
+ } catch (SecurityException e) {
+ // NOOP
+ } catch (IllegalAccessException e) {
+ // NOOp
+ }
+ }
+
+ public static void setClassToCaseMap(Class<? extends BindingCodec> codec,
+ Map<Class,BindingCodec> classToCaseRawCodec) {
+ Field instanceIdField;
+ try {
+ instanceIdField = codec.getField(CLASS_TO_CASE_MAP);
+ instanceIdField.set(null, classToCaseRawCodec);
+ } catch (NoSuchFieldException e) {
+ // NOOP
+ } catch (SecurityException e) {
+ // NOOP
+ } catch (IllegalAccessException e) {
+ // NOOp
+ }
+
+
+ }
+
+ public static void setCompositeNodeToCaseMap(Class<? extends BindingCodec> codec,
+ Map<CompositeNode,BindingCodec> compositeToCase) {
+ Field instanceIdField;
+ try {
+ instanceIdField = codec.getField(COMPOSITE_TO_CASE);
+ instanceIdField.set(null, compositeToCase);
+ } catch (NoSuchFieldException e) {
+ // NOOP
+ } catch (SecurityException e) {
+ // NOOP
+ } catch (IllegalAccessException e) {
+ // NOOp
+ }
+ }
+
+ public static void setAugmentationCodec(Class<? extends BindingCodec<Map<QName, Object>, Object>> dataCodec,
+ BindingCodec augmentableCodec) {
+ Field instanceIdField;
+ try {
+ instanceIdField = dataCodec.getField(AUGMENTATION_CODEC);
+ instanceIdField.set(null, augmentableCodec);
+ } catch (NoSuchFieldException e) {
+ // NOOP
+ } catch (SecurityException e) {
+ // NOOP
+ } catch (IllegalAccessException e) {
+ // NOOp
+ }
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.dom.serializer.impl;
+
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+
+public class CodecTypeUtils {
+
+ @SuppressWarnings({"unchecked","rawtypes"})
+ public static IdentifiableItem<?, ?> newIdentifiableItem(Class<?> type, Object key) {
+ Class<? extends Identifiable<?>> identifiableType = (Class<? extends Identifiable<?>>) type;
+ Identifier<? extends Identifiable<?>> identifier = (Identifier<? extends Identifiable<?>>) key;
+ return new IdentifiableItem(identifiableType,identifier);
+ }
+
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.dom.serializer.impl;
+
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.binding.BindingCodec;
+import org.opendaylight.yangtools.yang.common.QName;
+
+public interface GeneratorListener {
+
+
+
+ void onCodecCreated(Class<?> codec);
+ void onValueCodecCreated(Class<?> valueClass,Class<?> valueCodec);
+ void onChoiceCodecCreated(Class<?> choiceClass,Class<? extends BindingCodec<Map<QName, Object>,Object>> choiceCodec);
+ void onCaseCodecCreated(Class<?> choiceClass,Class<? extends BindingCodec<Map<QName, Object>,Object>> choiceCodec);
+ public abstract void onDataContainerCodecCreated(Class<?> dataClass, Class<? extends BindingCodec<Map<QName, Object>,Object>> dataCodec);
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.dom.serializer.impl
+
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.controller.sal.binding.dom.serializer.api.CodecRegistry
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem
+import org.opendaylight.yangtools.yang.common.QName
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item
+import java.util.Map
+import java.util.WeakHashMap
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
+import java.util.ArrayList
+import org.opendaylight.controller.sal.binding.dom.serializer.api.InstanceIdentifierCodec
+import org.opendaylight.controller.sal.binding.dom.serializer.api.ValueWithQName
+import java.util.HashMap
+import org.slf4j.LoggerFactory
+import java.util.List
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.controller.sal.binding.dom.serializer.api.IdentifierCodec
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
+import org.opendaylight.yangtools.yang.data.api.Node
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+
+class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
+
+ private static val LOG = LoggerFactory.getLogger(InstanceIdentifierCodecImpl);
+ val CodecRegistry codecRegistry;
+
+ val Map<Class<?>,QName> classToQName = new WeakHashMap;
+
+
+ public new(CodecRegistry registry) {
+ codecRegistry = registry;
+ }
+
+
+ override deserialize(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier input) {
+ var Class<?> baType = null
+ val biArgs = input.path
+ val scannedPath = new ArrayList<QName>(biArgs.size);
+ val baArgs = new ArrayList<org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument>(biArgs.size)
+ for(biArg : biArgs) {
+ scannedPath.add(biArg.nodeType);
+ val baArg = deserializePathArgument(biArg,scannedPath)
+ baArgs.add(baArg)
+ baType = baArg?.type
+ }
+ val ret = new InstanceIdentifier(baArgs,baType as Class<? extends DataObject>);
+ return ret;
+ }
+
+ private def dispatch org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument deserializePathArgument(NodeIdentifier argument,List<QName> processedPath) {
+ val Class cls = codecRegistry.getClassForPath(processedPath);
+ return new Item(cls);
+ }
+
+
+ private def dispatch org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument deserializePathArgument(NodeIdentifierWithPredicates argument,List<QName> processedPath) {
+ val Class type = codecRegistry.getClassForPath(processedPath);
+ val IdentifierCodec codec = codecRegistry.getIdentifierCodecForIdentifiable(type);
+ val value = codec.deserialize(argument.toCompositeNode())?.value;
+ return CodecTypeUtils.newIdentifiableItem(type,value);
+ }
+
+ def CompositeNode toCompositeNode(NodeIdentifierWithPredicates predicates) {
+ val keyValues = predicates.keyValues.entrySet;
+ val values = new ArrayList<Node<?>>(keyValues.size)
+ for(keyValue : keyValues) {
+ values.add(new SimpleNodeTOImpl(keyValue.key,null,keyValue.value))
+ }
+ return new CompositeNodeTOImpl(predicates.nodeType,null,values);
+ }
+
+ override serialize(InstanceIdentifier input) {
+ val pathArgs = input.path as List<org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument>
+ var QName previousQName = null;
+ val components = new ArrayList<PathArgument>(pathArgs.size);
+ for(baArg : pathArgs) {
+ codecRegistry.bindingClassEncountered(baArg.type);
+ val biArg = serializePathArgument(baArg,previousQName);
+ previousQName = biArg.nodeType;
+ components.add(biArg);
+ }
+ return new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(components);
+ }
+
+ private def dispatch PathArgument serializePathArgument(Item argument, QName previousQname) {
+ val type = argument.type;
+ val qname = resolveQname(type);
+ if(previousQname == null) {
+ return new NodeIdentifier(qname);
+ }
+ return new NodeIdentifier(QName.create(previousQname,qname.localName));
+ }
+
+ private def dispatch PathArgument serializePathArgument(IdentifiableItem argument, QName previousQname) {
+ val Map<QName,Object> predicates = new HashMap();
+ val type = argument.type;
+ val keyCodec = codecRegistry.getIdentifierCodecForIdentifiable(type);
+ val qname = resolveQname(type);
+ val combinedInput = new ValueWithQName(previousQname,argument.key)
+ val compositeOutput = keyCodec.serialize(combinedInput as ValueWithQName);
+ for(outputValue :compositeOutput.value) {
+ predicates.put(outputValue.nodeType,outputValue.value);
+ }
+ if(previousQname == null) {
+ return new NodeIdentifierWithPredicates(qname,predicates);
+ }
+ return new NodeIdentifierWithPredicates(QName.create(previousQname,qname.localName),predicates);
+ }
+
+ def resolveQname(Class class1) {
+ val qname = classToQName.get(class1);
+ if(qname !== null) {
+ return qname;
+ }
+ val qnameField = class1.getField("QNAME");
+ val qnameValue = qnameField.get(null) as QName;
+ classToQName.put(class1,qnameValue);
+ }
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.sal.binding.dom.serializer.impl
+
+import org.opendaylight.yangtools.yang.data.api.Node
+import java.util.Map
+import org.opendaylight.yangtools.yang.common.QName
+import java.util.List
+import java.util.ArrayList
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
+import com.google.common.base.Preconditions
+
+class IntermediateMapping {
+
+
+
+ static def Node<?> toNode(Map map) {
+ val nodeMap = map as Map<QName,Object>;
+ Preconditions.checkArgument(map.size == 1);
+ val elem = nodeMap.entrySet.iterator.next;
+ val qname = elem.key;
+ val value = elem.value;
+ toNodeImpl(qname, value);
+ }
+
+ static def dispatch Node<?> toNodeImpl(QName name, List<?> objects) {
+ val values = new ArrayList<Node<?>>(objects.size);
+ for (obj : objects) {
+ values.add(toNode(obj as Map));
+ }
+ return new CompositeNodeTOImpl(name, null, values);
+ }
+
+ static def dispatch Node<?> toNodeImpl(QName name, Map<QName, Object> object) {
+ throw new UnsupportedOperationException("Unsupported node hierarchy.");
+ }
+
+ static def dispatch Node<?> toNodeImpl(QName name, Object object) {
+ return new SimpleNodeTOImpl(name, null, object);
+ }
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.sal.binding.dom.serializer.impl;
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Field;
+import java.util.AbstractMap.SimpleEntry;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+import org.opendaylight.controller.sal.binding.dom.serializer.api.AugmentationCodec;
+import org.opendaylight.controller.sal.binding.dom.serializer.api.ChoiceCaseCodec;
+import org.opendaylight.controller.sal.binding.dom.serializer.api.ChoiceCodec;
+import org.opendaylight.controller.sal.binding.dom.serializer.api.CodecRegistry;
+import org.opendaylight.controller.sal.binding.dom.serializer.api.DataContainerCodec;
+import org.opendaylight.controller.sal.binding.dom.serializer.api.DomCodec;
+import org.opendaylight.controller.sal.binding.dom.serializer.api.IdentifierCodec;
+import org.opendaylight.controller.sal.binding.dom.serializer.api.InstanceIdentifierCodec;
+import org.opendaylight.controller.sal.binding.dom.serializer.api.ValueWithQName;
+import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener;
+import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl;
+import org.opendaylight.yangtools.binding.generator.util.Types;
+import org.opendaylight.yangtools.concepts.Delegator;
+import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Augmentable;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.BindingCodec;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static com.google.common.base.Preconditions.*;
+import static org.opendaylight.controller.sal.binding.dom.serializer.impl.IntermediateMapping.*;
+
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleContext;
+import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
+
+public class LazyGeneratedCodecRegistry implements //
+ CodecRegistry, //
+ SchemaServiceListener, //
+ GeneratorListener {
+
+ private final static Logger LOG = LoggerFactory.getLogger(LazyGeneratedCodecRegistry.class);
+ private final static LateMixinCodec NOT_READY_CODEC = new LateMixinCodec();
+
+ private final InstanceIdentifierCodec instanceIdentifierCodec = new InstanceIdentifierCodecImpl(this);
+
+ private TransformerGenerator generator;
+
+ // Concrete class to codecs
+ private Map<Class<?>, DataContainerCodec<?>> containerCodecs = new WeakHashMap<>();
+ private Map<Class<?>, IdentifierCodec<?>> identifierCodecs = new WeakHashMap<>();
+ private Map<Class<?>, ChoiceCodecImpl<?>> choiceCodecs = new WeakHashMap<>();
+ private Map<Class<?>, ChoiceCaseCodecImpl<?>> caseCodecs = new WeakHashMap<>();
+ private Map<Class<?>, AugmentableCompositeCodec> augmentableCodecs = new WeakHashMap<>();
+
+ /** Binding type to encountered classes mapping **/
+ @SuppressWarnings("rawtypes")
+ Map<Type, WeakReference<Class>> typeToClass = new ConcurrentHashMap<>();
+
+ @SuppressWarnings("rawtypes")
+ private ConcurrentMap<Type, ChoiceCaseCodecImpl> typeToCaseNodes = new ConcurrentHashMap<>();
+
+ private CaseClassMapFacade classToCaseRawCodec = new CaseClassMapFacade();
+
+ Map<SchemaPath, GeneratedTypeBuilder> pathToType = new ConcurrentHashMap<>();
+
+ private SchemaContext currentSchema;
+
+ public TransformerGenerator getGenerator() {
+ return generator;
+ }
+
+ public void setGenerator(TransformerGenerator generator) {
+ this.generator = generator;
+ }
+
+ @Override
+ public InstanceIdentifierCodec getInstanceIdentifierCodec() {
+ return instanceIdentifierCodec;
+ }
+
+ @Override
+ public <T extends Augmentation<?>> AugmentationCodec<T> getCodecForAugmentation(Class<T> object) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Class<?> getClassForPath(List<QName> names) {
+ DataSchemaNode node = getSchemaNode(names);
+ SchemaPath path = node.getPath();
+ GeneratedTypeBuilder type = pathToType.get(path);
+ ReferencedTypeImpl typeref = new ReferencedTypeImpl(type.getPackageName(), type.getName());
+ @SuppressWarnings("rawtypes")
+ WeakReference<Class> weakRef = typeToClass.get(typeref);
+ return weakRef.get();
+ }
+
+ @Override
+ public IdentifierCodec<?> getKeyCodecForPath(List<QName> names) {
+ @SuppressWarnings("unchecked")
+ Class<? extends Identifiable<?>> cls = (Class<? extends Identifiable<?>>) getClassForPath(names);
+ return getIdentifierCodecForIdentifiable(cls);
+ }
+
+ @Override
+ public <T extends DataContainer> DataContainerCodec<T> getCodecForDataObject(Class<T> type) {
+ @SuppressWarnings("unchecked")
+ DataContainerCodec<T> ret = (DataContainerCodec<T>) containerCodecs.get(type);
+ if (ret != null) {
+ return ret;
+ }
+ Class<? extends BindingCodec<Map<QName, Object>, Object>> newType = generator.transformerFor(type);
+ BindingCodec<Map<QName, Object>, Object> rawCodec = newInstanceOf(newType);
+ DataContainerCodecImpl<T> newWrapper = new DataContainerCodecImpl<>(rawCodec);
+ containerCodecs.put(type, newWrapper);
+ return newWrapper;
+ }
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ public void bindingClassEncountered(Class cls) {
+ ConcreteType typeRef = Types.typeForClass(cls);
+ WeakReference<Class> weakRef = new WeakReference<>(cls);
+ typeToClass.put(typeRef, weakRef);
+ }
+
+ private DataSchemaNode getSchemaNode(List<QName> path) {
+ QName firstNode = path.get(0);
+ DataNodeContainer previous = currentSchema.findModuleByNamespaceAndRevision(firstNode.getNamespace(),
+ firstNode.getRevision());
+ Iterator<QName> iterator = path.iterator();
+ while (iterator.hasNext()) {
+ QName arg = iterator.next();
+ DataSchemaNode currentNode = previous.getDataChildByName(arg);
+ if (currentNode == null && previous instanceof DataNodeContainer) {
+ currentNode = searchInChoices(previous, arg);
+ }
+ if (currentNode instanceof DataNodeContainer) {
+ previous = (DataNodeContainer) currentNode;
+ } else if (currentNode instanceof LeafSchemaNode || currentNode instanceof LeafListSchemaNode) {
+ checkState(!iterator.hasNext(), "Path tries to nest inside leaf node.");
+ return currentNode;
+ }
+ }
+ return (DataSchemaNode) previous;
+ }
+
+ private DataSchemaNode searchInChoices(DataNodeContainer node, QName arg) {
+ Set<DataSchemaNode> children = node.getChildNodes();
+ for (DataSchemaNode child : children) {
+ if (child instanceof ChoiceNode) {
+ ChoiceNode choiceNode = (ChoiceNode) child;
+ DataSchemaNode potential = searchInCases(choiceNode, arg);
+ if (potential != null) {
+ return potential;
+ }
+ }
+ }
+ return null;
+ }
+
+ private DataSchemaNode searchInCases(ChoiceNode choiceNode, QName arg) {
+ Set<ChoiceCaseNode> cases = choiceNode.getCases();
+ for (ChoiceCaseNode caseNode : cases) {
+ DataSchemaNode node = caseNode.getDataChildByName(arg);
+ if (node != null) {
+ return node;
+ }
+ }
+ return null;
+ }
+
+ private <T> T newInstanceOf(Class<?> newType) {
+ try {
+ @SuppressWarnings("unchecked")
+ T ret = (T) newType.newInstance();
+ return ret;
+ } catch (InstantiationException e) {
+ throw new IllegalStateException(e);
+ } catch (IllegalAccessException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public <T extends Identifiable<?>> IdentifierCodec<?> getIdentifierCodecForIdentifiable(Class<T> type) {
+ IdentifierCodec<?> obj = identifierCodecs.get(type);
+ if (obj != null) {
+ return obj;
+ }
+ Class<? extends BindingCodec<Map<QName, Object>, Object>> newCodec = generator
+ .keyTransformerForIdentifiable(type);
+ BindingCodec<Map<QName, Object>, Object> newInstance;
+ newInstance = newInstanceOf(newCodec);
+ IdentifierCodecImpl<?> newWrapper = new IdentifierCodecImpl<>(newInstance);
+ identifierCodecs.put(type, newWrapper);
+ return newWrapper;
+ }
+
+ @Override
+ public void onCodecCreated(Class<?> cls) {
+ CodecMapping.setIdentifierCodec(cls, instanceIdentifierCodec);
+ }
+
+ @Override
+ public <T extends Identifier<?>> IdentifierCodec<T> getCodecForIdentifier(Class<T> object) {
+ @SuppressWarnings("unchecked")
+ IdentifierCodec<T> obj = (IdentifierCodec<T>) identifierCodecs.get(object);
+ if (obj != null) {
+ return obj;
+ }
+ Class<? extends BindingCodec<Map<QName, Object>, Object>> newCodec = generator
+ .keyTransformerForIdentifier(object);
+ BindingCodec<Map<QName, Object>, Object> newInstance;
+ newInstance = newInstanceOf(newCodec);
+ IdentifierCodecImpl<T> newWrapper = new IdentifierCodecImpl<>(newInstance);
+ identifierCodecs.put(object, newWrapper);
+ return newWrapper;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public ChoiceCaseCodecImpl getCaseCodecFor(Class caseClass) {
+ ChoiceCaseCodecImpl<?> potential = caseCodecs.get(caseClass);
+ if (potential != null) {
+ return potential;
+ }
+ ConcreteType typeref = Types.typeForClass(caseClass);
+ ChoiceCaseCodecImpl caseCodec = typeToCaseNodes.get(typeref);
+
+ @SuppressWarnings("unchecked")
+ Class<? extends BindingCodec> newCodec = generator.caseCodecFor(caseClass, caseCodec.schema);
+ BindingCodec newInstance = newInstanceOf(newCodec);
+ caseCodec.setDelegate(newInstance);
+ caseCodecs.put(caseClass, caseCodec);
+
+ for (Entry<Class<?>, ChoiceCodecImpl<?>> choice : choiceCodecs.entrySet()) {
+ if (choice.getKey().isAssignableFrom(caseClass)) {
+ choice.getValue().cases.put(caseClass, caseCodec);
+ }
+ }
+ return caseCodec;
+ }
+
+ public void onModuleContextAdded(SchemaContext schemaContext, Module module, ModuleContext context) {
+ pathToType.putAll(context.getChildNodes());
+
+ captureCases(context.getCases(), schemaContext);
+ }
+
+ private void captureCases(Map<SchemaPath, GeneratedTypeBuilder> cases, SchemaContext module) {
+ for (Entry<SchemaPath, GeneratedTypeBuilder> caseNode : cases.entrySet()) {
+ ReferencedTypeImpl typeref = new ReferencedTypeImpl(caseNode.getValue().getPackageName(), caseNode
+ .getValue().getName());
+ ChoiceCaseNode node = (ChoiceCaseNode) SchemaContextUtil.findDataSchemaNode(module, caseNode.getKey());
+ @SuppressWarnings("rawtypes")
+ ChoiceCaseCodecImpl value = new ChoiceCaseCodecImpl(node);
+ typeToCaseNodes.putIfAbsent(typeref, value);
+ }
+ }
+
+ @Override
+ public void onGlobalContextUpdated(SchemaContext context) {
+ currentSchema = context;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
+ public void onChoiceCodecCreated(Class<?> choiceClass,
+ Class<? extends BindingCodec<Map<QName, Object>, Object>> choiceCodec) {
+ ChoiceCodec<?> oldCodec = choiceCodecs.get(choiceClass);
+ checkState(oldCodec == null);
+ BindingCodec<Map<QName, Object>, Object> delegate = newInstanceOf(choiceCodec);
+ ChoiceCodecImpl<?> newCodec = new ChoiceCodecImpl(delegate);
+ choiceCodecs.put(choiceClass, newCodec);
+ CodecMapping.setClassToCaseMap(choiceCodec, (Map<Class, BindingCodec>) classToCaseRawCodec);
+ CodecMapping.setCompositeNodeToCaseMap(choiceCodec, newCodec.getCompositeToCase());
+
+ }
+
+ @Override
+ public void onValueCodecCreated(Class<?> valueClass, Class<?> valueCodec) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void onCaseCodecCreated(Class<?> choiceClass,
+ Class<? extends BindingCodec<Map<QName, Object>, Object>> choiceCodec) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void onDataContainerCodecCreated(Class<?> dataClass,
+ Class<? extends BindingCodec<Map<QName, Object>, Object>> dataCodec) {
+ if (Augmentable.class.isAssignableFrom(dataClass)) {
+ AugmentableCompositeCodec augmentableCodec = getAugmentableCodec(dataClass);
+ CodecMapping.setAugmentationCodec(dataCodec, augmentableCodec);
+ }
+
+ }
+
+ private AugmentableCompositeCodec getAugmentableCodec(Class<?> dataClass) {
+ AugmentableCompositeCodec ret = augmentableCodecs.get(dataClass);
+ if (ret != null) {
+ return ret;
+ }
+ ret = new AugmentableCompositeCodec(dataClass);
+ augmentableCodecs.put(dataClass, ret);
+ return ret;
+ }
+
+ private static abstract class IntermediateCodec<T> implements //
+ DomCodec<T>, Delegator<BindingCodec<Map<QName, Object>, Object>> {
+
+ private final BindingCodec<Map<QName, Object>, Object> delegate;
+
+ @Override
+ public BindingCodec<Map<QName, Object>, Object> getDelegate() {
+ return delegate;
+ }
+
+ public IntermediateCodec(BindingCodec<Map<QName, Object>, Object> delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public Node<?> serialize(ValueWithQName<T> input) {
+ Map<QName, Object> intermediateOutput = delegate.serialize(input);
+ return toNode(intermediateOutput);
+ }
+ }
+
+ private static class IdentifierCodecImpl<T extends Identifier<?>> //
+ extends IntermediateCodec<T> //
+ implements IdentifierCodec<T> {
+
+ public IdentifierCodecImpl(BindingCodec<Map<QName, Object>, Object> delegate) {
+ super(delegate);
+ }
+
+ @Override
+ public ValueWithQName<T> deserialize(Node<?> input) {
+ QName qname = input.getNodeType();
+ @SuppressWarnings("unchecked")
+ T value = (T) getDelegate().deserialize((Map<QName, Object>) input);
+ return new ValueWithQName<T>(qname, value);
+ }
+
+ @Override
+ public CompositeNode serialize(ValueWithQName<T> input) {
+ return (CompositeNode) super.serialize(input);
+ }
+ }
+
+ private static class DataContainerCodecImpl<T extends DataContainer> //
+ extends IntermediateCodec<T> //
+ implements DataContainerCodec<T> {
+
+ public DataContainerCodecImpl(BindingCodec<Map<QName, Object>, Object> delegate) {
+ super(delegate);
+ }
+
+ @Override
+ public ValueWithQName<T> deserialize(Node<?> input) {
+ if (input == null) {
+ return null;
+ }
+ QName qname = input.getNodeType();
+ @SuppressWarnings("unchecked")
+ T value = (T) getDelegate().deserialize((Map<QName, Object>) input);
+ return new ValueWithQName<T>(qname, value);
+ }
+
+ @Override
+ public CompositeNode serialize(ValueWithQName<T> input) {
+ return (CompositeNode) super.serialize(input);
+ }
+ }
+
+ @SuppressWarnings("rawtypes")
+ private static class ChoiceCaseCodecImpl<T extends DataContainer> implements ChoiceCaseCodec<T>, //
+ Delegator<BindingCodec> {
+ private final boolean augmenting;
+ private BindingCodec delegate;
+
+ private final Set<String> validNames;
+ private final Set<QName> validQNames;
+ private ChoiceCaseNode schema;
+
+ public ChoiceCaseCodecImpl(ChoiceCaseNode caseNode) {
+ this.delegate = NOT_READY_CODEC;
+ this.schema = caseNode;
+ validNames = new HashSet<>();
+ validQNames = new HashSet<>();
+ for (DataSchemaNode node : caseNode.getChildNodes()) {
+ QName qname = node.getQName();
+ validQNames.add(qname);
+ validNames.add(qname.getLocalName());
+ }
+ augmenting = caseNode.isAugmenting();
+ }
+
+ @Override
+ public ValueWithQName<T> deserialize(Node<?> input) {
+ throw new UnsupportedOperationException("Direct invocation of this codec is not allowed.");
+ }
+
+ @Override
+ public CompositeNode serialize(ValueWithQName<T> input) {
+ throw new UnsupportedOperationException("Direct invocation of this codec is not allowed.");
+ }
+
+ public BindingCodec getDelegate() {
+ return delegate;
+ }
+
+ public void setDelegate(BindingCodec delegate) {
+ this.delegate = delegate;
+ }
+
+ public ChoiceCaseNode getSchema() {
+ return schema;
+ }
+
+ @Override
+ public boolean isAcceptable(Node<?> input) {
+ if (false == (input instanceof CompositeNode)) {
+ if (augmenting) {
+ return checkAugmenting((CompositeNode) input);
+ } else {
+ return checkLocal((CompositeNode) input);
+ }
+ }
+ return false;
+ }
+
+ private boolean checkLocal(CompositeNode input) {
+ QName parent = input.getNodeType();
+ for (Node<?> childNode : input.getChildren()) {
+ QName child = childNode.getNodeType();
+ if (false == Objects.equals(parent.getNamespace(), child.getNamespace())) {
+ continue;
+ }
+ if (false == Objects.equals(parent.getRevision(), child.getRevision())) {
+ continue;
+ }
+ if (validNames.contains(child.getLocalName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean checkAugmenting(CompositeNode input) {
+ for (Node<?> child : input.getChildren()) {
+ if (validQNames.contains(child.getNodeType())) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ private static class ChoiceCodecImpl<T> implements ChoiceCodec<T> {
+
+ private final BindingCodec<Map<QName, Object>, Object> delegate;
+
+ @SuppressWarnings("rawtypes")
+ private final Map<Class, ChoiceCaseCodecImpl<?>> cases = new WeakHashMap<>();
+
+ private final CaseCompositeNodeMapFacade CompositeToCase;
+
+ public ChoiceCodecImpl(BindingCodec<Map<QName, Object>, Object> delegate) {
+ this.delegate = delegate;
+ this.CompositeToCase = new CaseCompositeNodeMapFacade(cases);
+ }
+
+ @Override
+ public ValueWithQName<T> deserialize(Node<?> input) {
+ throw new UnsupportedOperationException("Direct invocation of this codec is not allowed.");
+ }
+
+ @Override
+ public Node<?> serialize(ValueWithQName<T> input) {
+ throw new UnsupportedOperationException("Direct invocation of this codec is not allowed.");
+ }
+
+ public CaseCompositeNodeMapFacade getCompositeToCase() {
+ return CompositeToCase;
+ }
+
+ public Map<Class, ChoiceCaseCodecImpl<?>> getCases() {
+ return cases;
+ }
+
+ public BindingCodec<Map<QName, Object>, Object> getDelegate() {
+ return delegate;
+ }
+
+ }
+
+ @SuppressWarnings("rawtypes")
+ private class CaseClassMapFacade extends MapFacadeBase {
+
+ @Override
+ public Set<java.util.Map.Entry<Class, BindingCodec<Object, Object>>> entrySet() {
+ return null;
+ }
+
+ @Override
+ public BindingCodec get(Object key) {
+ if (key instanceof Class) {
+ Class cls = (Class) key;
+ bindingClassEncountered(cls);
+ ChoiceCaseCodecImpl caseCodec = getCaseCodecFor(cls);
+ return caseCodec.getDelegate();
+ }
+ return null;
+ }
+ }
+
+ @SuppressWarnings("rawtypes")
+ private static class CaseCompositeNodeMapFacade extends MapFacadeBase<CompositeNode> {
+
+ final Map<Class, ChoiceCaseCodecImpl<?>> choiceCases;
+
+ public CaseCompositeNodeMapFacade(Map<Class, ChoiceCaseCodecImpl<?>> choiceCases) {
+ this.choiceCases = choiceCases;
+ }
+
+ @Override
+ public Set<java.util.Map.Entry<CompositeNode, BindingCodec>> entrySet() {
+ return null;
+ }
+
+ @Override
+ public BindingCodec get(Object key) {
+ if (false == (key instanceof CompositeNode)) {
+ return null;
+ }
+ for (java.util.Map.Entry<Class, ChoiceCaseCodecImpl<?>> entry : choiceCases.entrySet()) {
+ ChoiceCaseCodecImpl<?> codec = entry.getValue();
+ if (codec.isAcceptable((CompositeNode) key)) {
+ return codec.getDelegate();
+ }
+ }
+ return null;
+ }
+ }
+
+ /**
+ * This map is used as only facade for {@link BindingCodec} in different
+ * classloaders to retrieve codec dynamicly based on provided key.
+ *
+ * @param <T>
+ * Key type
+ */
+ @SuppressWarnings("rawtypes")
+ private static abstract class MapFacadeBase<T> implements Map<T, BindingCodec> {
+
+ @Override
+ public boolean containsKey(Object key) {
+ return get(key) != null;
+ }
+
+ @Override
+ public void clear() {
+ throw notModifiable();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return super.equals(obj);
+ }
+
+ @Override
+ public BindingCodec remove(Object key) {
+ return null;
+ }
+
+ @Override
+ public int size() {
+ return 0;
+ }
+
+ @Override
+ public Collection<BindingCodec> values() {
+ return null;
+ }
+
+ private UnsupportedOperationException notModifiable() {
+ return new UnsupportedOperationException("Not externally modifiable.");
+ }
+
+ @Override
+ public BindingCodec<Map<QName, Object>, Object> put(T key, BindingCodec value) {
+ throw notModifiable();
+ }
+
+ @Override
+ public void putAll(Map<? extends T, ? extends BindingCodec> m) {
+ throw notModifiable();
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return false;
+ }
+
+ @Override
+ public Set<T> keySet() {
+ return null;
+ }
+
+ @Override
+ public Set<java.util.Map.Entry<T, BindingCodec>> entrySet() {
+ return null;
+ }
+
+ @Override
+ public boolean containsValue(Object value) {
+ return false;
+ }
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ private class AugmentableCompositeCodec implements BindingCodec {
+
+ private final Class augmentableType;
+
+ Map<Class, BindingCodec> rawAugmentationCodecs = new WeakHashMap<>();
+
+ public AugmentableCompositeCodec(Class type) {
+ checkArgument(Augmentable.class.isAssignableFrom(type));
+ augmentableType = type;
+ }
+
+ @Override
+ public Object serialize(Object input) {
+ if (input instanceof Augmentable<?>) {
+
+ Map<Class, Augmentation> augmentations = getAugmentations(input);
+ return serializeImpl(augmentations);
+ }
+ return null;
+ }
+
+ private Map<Class, Augmentation> getAugmentations(Object input) {
+ Field augmentationField;
+ try {
+ augmentationField = input.getClass().getDeclaredField("augmentation");
+ augmentationField.setAccessible(true);
+ Map<Class, Augmentation> augMap = (Map<Class, Augmentation>) augmentationField.get(input);
+ return augMap;
+ } catch (NoSuchFieldException e) {
+
+ } catch (SecurityException e) {
+
+ } catch (IllegalArgumentException e) {
+
+ } catch (IllegalAccessException e) {
+
+ }
+ return Collections.emptyMap();
+ }
+
+ private List serializeImpl(Map<Class, Augmentation> input) {
+ List ret = new ArrayList<>();
+ for (Entry<Class, Augmentation> entry : input.entrySet()) {
+ BindingCodec codec = getRawCodecForAugmentation(entry.getKey());
+ List output = (List) codec.serialize(new ValueWithQName(null, entry.getValue()));
+ ret.addAll(output);
+ }
+ return ret;
+ }
+
+ private BindingCodec getRawCodecForAugmentation(Class key) {
+ BindingCodec ret = rawAugmentationCodecs.get(key);
+ if (ret != null) {
+ return ret;
+ }
+ try {
+ Class<? extends BindingCodec> retClass = generator.augmentationTransformerFor(key);
+ ret = retClass.newInstance();
+ rawAugmentationCodecs.put(key, ret);
+ return ret;
+ } catch (InstantiationException e) {
+
+ } catch (IllegalAccessException e) {
+
+ }
+ return null;
+ }
+
+ @Override
+ public Map<Class, Augmentation> deserialize(Object input) {
+ Map<Class, Augmentation> ret = new HashMap<>();
+ if (input instanceof CompositeNode) {
+ for (Entry<Class, BindingCodec> codec : rawAugmentationCodecs.entrySet()) {
+ Augmentation value = (Augmentation) codec.getValue().deserialize(input);
+ if (value != null) {
+ ret.put(codec.getKey(), value);
+ }
+ }
+ }
+ return ret;
+ }
+
+ public Map<Class, BindingCodec> getRawAugmentationCodecs() {
+ return rawAugmentationCodecs;
+ }
+
+ public void setRawAugmentationCodecs(Map<Class, BindingCodec> rawAugmentationCodecs) {
+ this.rawAugmentationCodecs = rawAugmentationCodecs;
+ }
+
+ public Class getAugmentableType() {
+ return augmentableType;
+ }
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ private static class LateMixinCodec implements BindingCodec, Delegator<BindingCodec> {
+
+ private BindingCodec delegate;
+
+ @Override
+ public BindingCodec getDelegate() {
+ if (delegate == null) {
+ throw new IllegalStateException("Codec not initialized yet.");
+ }
+ return delegate;
+ }
+
+ @Override
+ public Object deserialize(Object input) {
+ return getDelegate().deserialize(input);
+ }
+
+ @Override
+ public Object serialize(Object input) {
+ return getDelegate().serialize(input);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.sal.binding.dom.serializer.impl
+
+import org.opendaylight.controller.sal.binding.dom.serializer.impl.TransformerGenerator
+import javassist.ClassPool
+import org.opendaylight.yangtools.yang.model.api.SchemaContext
+import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener
+import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl
+import java.util.Map
+import org.opendaylight.yangtools.sal.binding.model.api.Type
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder
+import org.opendaylight.yangtools.yang.model.api.SchemaNode
+import java.util.concurrent.ConcurrentHashMap
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+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
+import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl
+import org.opendaylight.controller.sal.binding.dom.serializer.impl.LazyGeneratedCodecRegistry
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService
+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
+
+class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingService, SchemaServiceListener {
+
+ @Property
+ ClassPool pool;
+
+ private static val LOG = LoggerFactory.getLogger(RuntimeGeneratedMappingServiceImpl);
+
+ @Property
+ extension TransformerGenerator binding;
+
+ @Property
+ extension LazyGeneratedCodecRegistry registry;
+
+ @Property
+ val ConcurrentMap<Type, Type> typeDefinitions = new ConcurrentHashMap();
+
+ @Property
+ val ConcurrentMap<Type, GeneratedTypeBuilder> typeToDefinition = new ConcurrentHashMap();
+
+ @Property
+ val ConcurrentMap<Type, SchemaNode> typeToSchemaNode = new ConcurrentHashMap();
+
+ val promisedTypeDefinitions = HashMultimap.<Type, SettableFuture<GeneratedTypeBuilder>>create;
+
+ val promisedSchemas = HashMultimap.<Type, SettableFuture<SchemaNode>>create;
+
+ override onGlobalContextUpdated(SchemaContext arg0) {
+ recreateBindingContext(arg0);
+ registry.onGlobalContextUpdated(arg0);
+ }
+
+ def recreateBindingContext(SchemaContext schemaContext) {
+ val newBinding = new BindingGeneratorImpl();
+ newBinding.generateTypes(schemaContext);
+
+ for (entry : newBinding.moduleContexts.entrySet) {
+
+ registry.onModuleContextAdded(schemaContext, entry.key, entry.value);
+
+ //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);
+ }
+ val augmentations = context.augmentations;
+ for (augmentation : augmentations) {
+ binding.typeToDefinition.put(augmentation, augmentation);
+ }
+
+ binding.typeToAugmentation.putAll(context.typeToAugmentation);
+ }
+ }
+
+ override CompositeNode toDataDom(DataObject data) {
+ toCompositeNodeImpl(data);
+ }
+
+ override Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> toDataDom(
+ Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry) {
+ val key = toDataDom(entry.key)
+ val data = toCompositeNodeImpl(entry.value);
+ return new SimpleEntry(key, data);
+ }
+
+ private def CompositeNode toCompositeNodeImpl(DataObject object) {
+ val cls = object.implementedInterface;
+ waitForSchema(cls);
+ val codec = registry.getCodecForDataObject(cls) as DataContainerCodec<DataObject>;
+ val ret = codec.serialize(new ValueWithQName(null, object));
+ return ret as CompositeNode;
+ }
+
+ private def waitForSchema(Class<? extends DataContainer> class1) {
+ val ref = Types.typeForClass(class1);
+ getSchemaWithRetry(ref);
+ }
+
+ override org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom(
+ InstanceIdentifier<? extends DataObject> path) {
+ for (arg : path.path) {
+ waitForSchema(arg.type);
+ }
+ return registry.instanceIdentifierCodec.serialize(path);
+ }
+
+ override dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode node) {
+ if (node == null) {
+ return null;
+ }
+ val targetType = path.targetType
+ val transformer = registry.getCodecForDataObject(targetType);
+ val ret = transformer.deserialize(node)?.value as DataObject;
+ return ret;
+ }
+
+ private def void updateBindingFor(Map<SchemaPath, GeneratedTypeBuilder> map, SchemaContext module) {
+ for (entry : map.entrySet) {
+ val schemaNode = SchemaContextUtil.findDataSchemaNode(module, entry.key);
+ //LOG.info("{} : {}",entry.key,entry.value.fullyQualifiedName)
+ if (schemaNode != null) {
+ typeToSchemaNode.put(entry.value, schemaNode);
+ typeToDefinition.put(entry.value, entry.value);
+ updatePromisedSchemas(entry.value, schemaNode);
+ }
+ }
+ }
+
+ public def void start() {
+ binding = new TransformerGenerator(pool);
+ registry = new LazyGeneratedCodecRegistry()
+ registry.generator = binding
+
+ //binding.staticFieldsInitializer = registry
+ binding.listener = registry
+ binding.typeToDefinition = typeToDefinition
+ binding.typeToSchemaNode = typeToSchemaNode
+ binding.typeDefinitions = typeDefinitions
+
+ }
+
+ private def getTypeDefinition(Type type) {
+ val typeDef = typeToDefinition.get(type);
+ if (typeDef !== null) {
+ return typeDef;
+ }
+ return type.getTypeDefInFuture.get();
+ }
+
+ private def Future<GeneratedTypeBuilder> getTypeDefInFuture(Type type) {
+ val future = SettableFuture.<GeneratedTypeBuilder>create()
+ promisedTypeDefinitions.put(type, future);
+ return future;
+ }
+
+ private def void updatePromisedTypeDefinitions(GeneratedTypeBuilder builder) {
+ val futures = promisedTypeDefinitions.get(builder);
+ if (futures === null || futures.empty) {
+ return;
+ }
+ for (future : futures) {
+ future.set(builder);
+ }
+ promisedTypeDefinitions.removeAll(builder);
+ }
+
+ private def getSchemaWithRetry(Type type) {
+ val typeDef = typeToSchemaNode.get(type);
+ if (typeDef !== null) {
+ return typeDef;
+ }
+ return type.getSchemaInFuture.get();
+ }
+
+ private def Future<SchemaNode> getSchemaInFuture(Type type) {
+ val future = SettableFuture.<SchemaNode>create()
+ promisedSchemas.put(type, future);
+ return future;
+ }
+
+ private def void updatePromisedSchemas(Type builder, SchemaNode schema) {
+ val ref = new ReferencedTypeImpl(builder.packageName, builder.name);
+ val futures = promisedSchemas.get(ref);
+ if (futures === null || futures.empty) {
+ return;
+ }
+ for (future : futures) {
+ future.set(schema);
+ }
+ promisedSchemas.removeAll(builder);
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.dom.serializer.impl;
+
+public interface StaticFieldInitializer {
+
+ void initializeStaticFields(Class<?> cls);
+}
import org.opendaylight.yangtools.yang.common.QName
import javassist.CtField
import static javassist.Modifier.*
+import static org.opendaylight.controller.sal.binding.dom.serializer.impl.CodecMapping.*
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
-import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
import org.opendaylight.yangtools.sal.binding.model.api.Type
import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder
import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
-import java.util.WeakHashMap
import java.util.List
import java.util.TreeSet
import com.google.common.base.Joiner
import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode
import static org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils.*;
import org.opendaylight.yangtools.yang.binding.BindingDeserializer
-import org.opendaylight.yangtools.yang.binding.BindingSerializer
import org.opendaylight.yangtools.yang.binding.BindingCodec
import org.slf4j.LoggerFactory
import org.opendaylight.controller.sal.binding.codegen.CodeGenerationException
import org.opendaylight.yangtools.yang.model.api.ChoiceNode
import java.security.ProtectionDomain
import java.io.File
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty
+import java.util.Map.Entry
+import java.util.AbstractMap.SimpleEntry
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.Augmentation
+import java.util.Iterator
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema
+import java.util.concurrent.ConcurrentHashMap
class TransformerGenerator {
public static val STRING = Types.typeForClass(String);
public static val BOOLEAN = Types.typeForClass(Boolean);
public static val INTEGER = Types.typeForClass(Integer);
+ public static val INSTANCE_IDENTIFIER = Types.typeForClass(InstanceIdentifier)
//public static val DECIMAL = Types.typeForClass(Decimal);
public static val LONG = Types.typeForClass(Long);
val ClassPool classPool
val extension JavassistUtils utils;
- CtClass ctTransformator
+ CtClass BINDING_CODEC
CtClass ctQName
@Property
var File classFileCapturePath;
+ @Property
+ var Map<Type, Type> typeDefinitions = new ConcurrentHashMap();
@Property
- var Map<Type, Type> typeDefinitions;
+ var Map<Type, GeneratedTypeBuilder> typeToDefinition = new ConcurrentHashMap();
@Property
- var Map<Type, GeneratedTypeBuilder> typeToDefinition
+ var Map<Type, SchemaNode> typeToSchemaNode = new ConcurrentHashMap();
@Property
- var Map<Type, SchemaNode> typeToSchemaNode
+ var Map<Type, AugmentationSchema> typeToAugmentation = new ConcurrentHashMap();
- val Map<Class<?>, Class<?>> generatedClasses = new WeakHashMap();
+ @Property
+ var GeneratorListener listener;
public new(ClassPool pool) {
classPool = pool;
utils = new JavassistUtils(pool)
- ctTransformator = BindingCodec.asCtClass;
+ BINDING_CODEC = BindingCodec.asCtClass;
ctQName = QName.asCtClass
}
def Class<? extends BindingCodec<Map<QName, Object>, Object>> transformerFor(Class<?> inputType) {
- return withClassLoader(inputType.classLoader) [ |
- val ret = generatedClasses.get(inputType);
+ return withClassLoaderAndLock(inputType.classLoader, lock) [ |
+ val ret = getGeneratedClass(inputType)
if (ret !== null) {
return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
}
val node = typeToSchemaNode.get(ref)
val typeSpecBuilder = typeToDefinition.get(ref)
val typeSpec = typeSpecBuilder.toInstance();
- val newret = generateTransformerFor(inputType, typeSpec, node)
- generatedClasses.put(inputType, newret);
+ val newret = generateTransformerFor(inputType, typeSpec, node);
+ return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+ ]
+ }
+
+ def Class<? extends BindingCodec<Map<QName, Object>, Object>> augmentationTransformerFor(Class<?> inputType) {
+ return withClassLoaderAndLock(inputType.classLoader, lock) [ |
+ val ret = getGeneratedClass(inputType)
+ if (ret !== null) {
+ return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+ }
+ val ref = Types.typeForClass(inputType)
+ val node = typeToAugmentation.get(ref)
+ val typeSpecBuilder = typeToDefinition.get(ref)
+ val typeSpec = typeSpecBuilder.toInstance();
+ val newret = generateAugmentationTransformerFor(inputType, typeSpec, node);
+ return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+ ]
+ }
+
+ def Class<? extends BindingCodec<Object, Object>> caseCodecFor(Class<?> inputType, ChoiceCaseNode node) {
+ return withClassLoaderAndLock(inputType.classLoader, lock) [ |
+ val ret = getGeneratedClass(inputType)
+ if (ret !== null) {
+ return ret as Class<? extends BindingCodec<Object, Object>>;
+ }
+ val ref = Types.typeForClass(inputType)
+ val typeSpecBuilder = typeToDefinition.get(ref)
+ val typeSpec = typeSpecBuilder.toInstance();
+ val newret = generateCaseCodec(inputType, typeSpec, node);
+ return newret as Class<? extends BindingCodec<Object, Object>>;
+ ]
+ }
+
+ def Class<? extends BindingCodec<Map<QName, Object>, Object>> keyTransformerForIdentifiable(Class<?> parentType) {
+ return withClassLoaderAndLock(parentType.classLoader, lock) [ |
+ val inputName = parentType.name + "Key";
+ val inputType = loadClassWithTCCL(inputName);
+ val ret = getGeneratedClass(inputType)
+ if (ret !== null) {
+ return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+ }
+ val ref = Types.typeForClass(parentType)
+ val node = typeToSchemaNode.get(ref) as ListSchemaNode
+ val typeSpecBuilder = typeToDefinition.get(ref)
+ val typeSpec = typeSpecBuilder.identifierDefinition;
+ val newret = generateKeyTransformerFor(inputType, typeSpec, node);
+ return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+ ]
+ }
+
+ def getIdentifierDefinition(GeneratedTypeBuilder builder) {
+ val inst = builder.toInstance
+ val keyMethod = inst.methodDefinitions.findFirst[name == "getKey"]
+ return keyMethod.returnType as GeneratedTransferObject
+ }
+
+ def Class<? extends BindingCodec<Map<QName, Object>, Object>> keyTransformerForIdentifier(Class<?> inputType) {
+ return withClassLoaderAndLock(inputType.classLoader, lock) [ |
+ val ret = getGeneratedClass(inputType)
+ if (ret !== null) {
+ return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+ }
+ val ref = Types.typeForClass(inputType)
+ val node = typeToSchemaNode.get(ref) as ListSchemaNode
+ val typeSpecBuilder = typeToDefinition.get(ref)
+ val typeSpec = typeSpecBuilder.toInstance();
+ val newret = generateKeyTransformerFor(inputType, typeSpec, node);
return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
]
}
private def Class<?> keyTransformerFor(Class<?> inputType, GeneratedType type, ListSchemaNode schema) {
- return withClassLoader(inputType.classLoader) [ |
- val transformer = generatedClasses.get(inputType);
+ return withClassLoaderAndLock(inputType.classLoader, lock) [ |
+ val transformer = getGeneratedClass(inputType)
if (transformer != null) {
return transformer;
}
val newret = generateKeyTransformerFor(inputType, type, schema);
- generatedClasses.put(inputType, newret);
return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
]
}
- def Class<?> keyTransformer(GeneratedType type, ListSchemaNode node) {
+ private def Class getGeneratedClass(Class<? extends Object> cls) {
+
+ try {
+ return loadClassWithTCCL(cls.codecClassName)
+ } catch (ClassNotFoundException e) {
+ return null;
+ }
+ }
+
+ private def Class<?> keyTransformer(GeneratedType type, ListSchemaNode node) {
val cls = loadClassWithTCCL(type.resolvedName + "Key");
keyTransformerFor(cls, type, node);
}
private def serializer(Type type) {
val cls = loadClassWithTCCL(type.resolvedName);
+
transformerFor(cls);
}
private def Class<?> getValueSerializer(GeneratedTransferObject type) {
val cls = loadClassWithTCCL(type.resolvedName);
- val transformer = generatedClasses.get(cls);
+ val transformer = cls.generatedClass;
if (transformer !== null) {
return transformer;
}
val valueTransformer = generateValueTransformer(cls, type);
- generatedClasses.put(cls, valueTransformer);
return valueTransformer;
}
private def generateKeyTransformerFor(Class<? extends Object> inputType, GeneratedType typeSpec, ListSchemaNode node) {
try {
- log.info("Generating DOM Codec for {} with {}",inputType,inputType.classLoader)
+ log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
val properties = typeSpec.allProperties;
- val ctCls = createClass(inputType.transformatorFqn) [
+ val ctCls = createClass(inputType.codecClassName) [
//staticField(Map,"AUGMENTATION_SERIALIZERS");
+ staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
staticQNameField(node.QName);
- implementsType(ctTransformator)
+ implementsType(BINDING_CODEC)
method(Object, "toDomStatic", QName, Object) [
modifiers = PUBLIC + FINAL + STATIC
body = '''
{
-
- return null;
+ «QName.name» _resultName;
+ if($1 != null) {
+ _resultName = «QName.name».create($1,QNAME.getLocalName());
+ } else {
+ _resultName = QNAME;
+ }
+ java.util.List _childNodes = new java.util.ArrayList();
+ «inputType.name» value = («inputType.name») $2;
+ «FOR key : node.keyDefinition»
+ «val propertyName = key.getterName»
+ «val keyDef = node.getDataChildByName(key)»
+ «val property = properties.get(propertyName)»
+ «serializeProperty(keyDef, property, propertyName)»;
+ «ENDFOR»
+ return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
}
'''
]
«val propertyName = key.getterName»
«val keyDef = node.getDataChildByName(key)»
«val property = properties.get(propertyName)»
- «deserializeProperty(keyDef, property.returnType, property)»;
+ «deserializeProperty(keyDef, property, propertyName)»;
«ENDFOR»
«inputType.name» _value = new «inputType.name»(«node.keyDefinition.keyConstructorList»);
return _value;
]
method(Object, "serialize", Object) [
body = '''
- return toDomStatic(QNAME,$1);
+ {
+ java.util.Map.Entry _input = (java.util.Map.Entry) $1;
+ «QName.name» _localQName = («QName.name») _input.getKey();
+ «inputType.name» _keyValue = («inputType.name») _input.getValue();
+ return toDomStatic(_localQName,_keyValue);
+ }
'''
]
method(Object, "deserialize", Object) [
]
]
val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
- log.info("DOM Codec for {} was generated {}",inputType,ret)
+ log.info("DOM Codec for {} was generated {}", inputType, ret)
return ret as Class<? extends BindingCodec<Map<QName,Object>, ?>>;
} catch (Exception e) {
- processException(inputType,e);
+ processException(inputType, e);
return null;
}
}
- private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(Class inputType,
- GeneratedType typeSpec, SchemaNode node) {
+ private def Class<? extends BindingCodec<Object, Object>> generateCaseCodec(Class inputType, GeneratedType type,
+ ChoiceCaseNode node) {
try {
- log.info("Generating DOM Codec for {} with {}",inputType,inputType.classLoader)
- val ctCls = createClass(typeSpec.transformatorFqn) [
+ log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
+ val ctCls = createClass(type.codecClassName) [
//staticField(Map,"AUGMENTATION_SERIALIZERS");
+ implementsType(BINDING_CODEC)
staticQNameField(inputType);
- implementsType(ctTransformator)
+ staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+ staticField(it, AUGMENTATION_CODEC, BindingCodec)
+ method(Object, "toDomStatic", QName, Object) [
+ modifiers = PUBLIC + FINAL + STATIC
+ body = '''
+ {
+ «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
+ java.util.List _childNodes = new java.util.ArrayList();
+ «type.resolvedName» value = («type.resolvedName») $2;
+ «transformDataContainerBody(type.allProperties, node)»
+ return ($r) _childNodes;
+ }
+ '''
+ ]
+ method(Object, "serialize", Object) [
+ body = '''
+ {
+ java.util.Map.Entry _input = (java.util.Map.Entry) $1;
+ «QName.name» _localName = QNAME;
+ if(_input.getKey() != null) {
+ _localName = («QName.name») _input.getKey();
+ }
+ return toDomStatic(_localName,_input.getValue());
+ }
+ '''
+ ]
+ method(Object, "fromDomStatic", QName, Object) [
+ modifiers = PUBLIC + FINAL + STATIC
+ body = deserializeBody(type, node)
+ ]
+ method(Object, "deserialize", Object) [
+ body = '''
+ {
+
+ return fromDomStatic(QNAME,$1);
+ }
+ '''
+ ]
+ ]
+
+ val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+ log.info("DOM Codec for {} was generated {}", inputType, ret)
+ return ret as Class<? extends BindingCodec<Object, Object>>;
+ } catch (Exception e) {
+ processException(inputType, e);
+ return null;
+ }
+ }
+
+ private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(
+ Class inputType, GeneratedType typeSpec, SchemaNode node) {
+ try {
+ log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
+ val ctCls = createClass(typeSpec.codecClassName) [
+ //staticField(Map,"AUGMENTATION_SERIALIZERS");
+ staticQNameField(inputType);
+ staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+ staticField(it, AUGMENTATION_CODEC, BindingCodec)
+ implementsType(BINDING_CODEC)
method(Object, "toDomStatic", QName, Object) [
modifiers = PUBLIC + FINAL + STATIC
body = serializeBodyFacade(typeSpec, node)
]
method(Object, "serialize", Object) [
body = '''
- return toDomStatic(QNAME,$1);
+ {
+ java.util.Map.Entry _input = (java.util.Map.Entry) $1;
+ «QName.name» _localName = QNAME;
+ if(_input.getKey() != null) {
+ _localName = («QName.name») _input.getKey();
+ }
+ return toDomStatic(_localName,_input.getValue());
+ }
'''
]
method(Object, "fromDomStatic", QName, Object) [
]
]
- val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
- return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+ val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
+ listener?.onDataContainerCodecCreated(inputType, ret);
+ log.info("DOM Codec for {} was generated {}", inputType, ret)
+ return ret;
} catch (Exception e) {
- processException(inputType,e);
+ processException(inputType, e);
return null;
}
}
-
-
- private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(Class inputType,
- GeneratedType typeSpec, ChoiceNode node) {
+
+ private def Class<? extends BindingCodec<Map<QName, Object>, Object>> generateAugmentationTransformerFor(
+ Class inputType, GeneratedType type, AugmentationSchema node) {
try {
- log.info("Generating DOM Codec for {} with {}",inputType,inputType.classLoader)
- val ctCls = createClass(typeSpec.transformatorFqn) [
+ log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
+ val properties = type.allProperties
+ val ctCls = createClass(type.codecClassName) [
//staticField(Map,"AUGMENTATION_SERIALIZERS");
- //staticQNameField(inputType);
- implementsType(ctTransformator)
+ staticQNameField(inputType);
+ staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+ staticField(it, AUGMENTATION_CODEC, BindingCodec)
+ implementsType(BINDING_CODEC)
method(Object, "toDomStatic", QName, Object) [
modifiers = PUBLIC + FINAL + STATIC
body = '''
- return null;
+ {
+ //System.out.println("Qname " + $1);
+ //System.out.println("Value " + $2);
+ «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
+ java.util.List _childNodes = new java.util.ArrayList();
+ «type.resolvedName» value = («type.resolvedName») $2;
+ «FOR child : node.childNodes»
+ «var signature = properties.getFor(child)»
+ //System.out.println("«signature.key»" + value.«signature.key»());
+ «serializeProperty(child, signature.value, signature.key)»
+ «ENDFOR»
+ return ($r) _childNodes;
+ }
'''
]
method(Object, "serialize", Object) [
body = '''
- return null;
+ {
+ java.util.Map.Entry _input = (java.util.Map.Entry) $1;
+ «QName.name» _localName = QNAME;
+ if(_input.getKey() != null) {
+ _localName = («QName.name») _input.getKey();
+ }
+ return toDomStatic(_localName,_input.getValue());
+ }
'''
]
method(Object, "fromDomStatic", QName, Object) [
modifiers = PUBLIC + FINAL + STATIC
body = '''
- return null;
+ {
+ «QName.name» _localQName = QNAME;
+
+ if($2 == null) {
+ return null;
+ }
+ java.util.Map _compositeNode = (java.util.Map) $2;
+ ////System.out.println(_localQName + " " + _compositeNode);
+ «type.builderName» _builder = new «type.builderName»();
+ «FOR child : node.childNodes»
+ «val signature = properties.getFor(child)»
+ «deserializeProperty(child, signature.value, signature.key)»
+
+ _builder.«signature.key.toSetter»(«signature.key»);
+ «ENDFOR»
+ return _builder.build();
+ }
'''
]
method(Object, "deserialize", Object) [
body = '''
- return null;
+ return fromDomStatic(QNAME,$1);
'''
]
]
- val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
- return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+ val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
+ listener?.onDataContainerCodecCreated(inputType, ret);
+ return ret;
} catch (Exception e) {
- processException(inputType,e);
+ processException(inputType, e);
+ return null;
+ }
+ }
+
+ private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(
+ Class inputType, GeneratedType typeSpec, ChoiceNode node) {
+ try {
+ log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
+ val ctCls = createClass(typeSpec.codecClassName) [
+ //staticField(Map,"AUGMENTATION_SERIALIZERS");
+ //staticQNameField(inputType);
+ staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+ staticField(it, CLASS_TO_CASE_MAP, Map)
+ staticField(it, COMPOSITE_TO_CASE, Map)
+ //staticField(it,QNAME_TO_CASE_MAP,BindingCodec)
+ implementsType(BINDING_CODEC)
+ method(List, "toDomStatic", QName, Object) [
+ modifiers = PUBLIC + FINAL + STATIC
+ body = '''
+ {
+ if($2 == null) {
+ return null;
+ }
+ «DataObject.name» _baValue = («DataObject.name») $2;
+ Class _baClass = _baValue.getImplementedInterface();
+ «BINDING_CODEC.name» _codec = «CLASS_TO_CASE_MAP».get(_baClass);
+ if(_codec == null) {
+ return null;
+ }
+ java.util.Map.Entry _input = new «SimpleEntry.name»($1,_baValue);
+ return (java.util.List) _codec.serialize(_input);
+ }
+ '''
+ ]
+ method(Object, "serialize", Object) [
+ body = '''
+ throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
+ '''
+ ]
+ method(Object, "fromDomStatic", QName, Map) [
+ modifiers = PUBLIC + FINAL + STATIC
+ body = '''
+ {
+ «BINDING_CODEC.name» _codec = («BINDING_CODEC.name») «COMPOSITE_TO_CASE».get($2);
+ if(_codec != null) {
+ return _codec.deserialize(new «SimpleEntry.name»($1,$2));
+ }
+ return null;
+ }
+ '''
+ ]
+ method(Object, "deserialize", Object) [
+ body = '''
+ throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
+ '''
+ ]
+ ]
+
+ val rawRet = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+ val ret = rawRet as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+ listener?.onChoiceCodecCreated(inputType, ret);
+ log.info("DOM Codec for {} was generated {}", inputType, ret)
+ return ret;
+ } catch (Exception e) {
+ processException(inputType, e);
return null;
}
}
-
private def keyConstructorList(List<QName> qnames) {
val names = new TreeSet<String>()
}
java.util.Map _compositeNode = (java.util.Map) $2;
«type.builderName» _builder = new «type.builderName»();
-
return _builder.build();
}
'''
«type.builderName» _builder = new «type.builderName»();
«deserializeKey(type, node)»
«deserializeDataNodeContainerBody(type, node)»
+ «deserializeAugmentations»
return _builder.build();
}
'''
java.util.Map _compositeNode = (java.util.Map) $2;
«type.builderName» _builder = new «type.builderName»();
«deserializeDataNodeContainerBody(type, node)»
+ «deserializeAugmentations»
return _builder.build();
}
'''
private def dispatch String deserializeBodyImpl(GeneratedType type, ChoiceCaseNode node) '''
{
«QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
+
if($2 == null) {
return null;
}
java.util.Map _compositeNode = (java.util.Map) $2;
+ ////System.out.println(_localQName + " " + _compositeNode);
«type.builderName» _builder = new «type.builderName»();
«deserializeDataNodeContainerBody(type, node)»
+ «deserializeAugmentations»
return _builder.build();
}
'''
deserializeNodeContainerBodyImpl(type, type.allProperties, node);
}
- private def deserializeNodeContainerBodyImpl(GeneratedType type, HashMap<String, MethodSignature> properties,
+ private def deserializeNodeContainerBodyImpl(GeneratedType type, HashMap<String, Type> properties,
DataNodeContainer node) {
val ret = '''
«FOR child : node.childNodes.filter[!augmenting]»
«val signature = properties.getFor(child)»
- «deserializeProperty(child, signature.returnType, signature)»
- _builder.«signature.name.toSetter»(«signature.name»);
+ «deserializeProperty(child, signature.value, signature.key)»
+
+ _builder.«signature.key.toSetter»(«signature.key»);
«ENDFOR»
'''
return ret;
}
+ def deserializeAugmentations() '''
+ java.util.Map _augmentation = (java.util.Map) «AUGMENTATION_CODEC».deserialize(_compositeNode);
+ if(_augmentation != null) {
+ «Iterator.name» _entries = _augmentation.entrySet().iterator();
+ while(_entries.hasNext()) {
+ java.util.Map.Entry _entry = (java.util.Map.Entry) _entries.next();
+ //System.out.println("Aug. key:" + _entry.getKey());
+ Class _type = (Class) _entry.getKey();
+ «Augmentation.resolvedName» _value = («Augmentation.name») _entry.getValue();
+ _builder.addAugmentation(_type,_value);
+ }
+ }
+ '''
+
private def dispatch CharSequence deserializeProperty(ListSchemaNode schema, ParameterizedType type,
- MethodSignature property) '''
- java.util.List _dom_«property.name» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
+ String propertyName) '''
+ java.util.List _dom_«propertyName» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
localName»"));
- //System.out.println("«property.name»#deCode"+_dom_«property.name»);
- java.util.List «property.name» = new java.util.ArrayList();
- if(_dom_«property.name» != null) {
+ ////System.out.println("«propertyName»#deCode"+_dom_«propertyName»);
+ java.util.List «propertyName» = new java.util.ArrayList();
+ if(_dom_«propertyName» != null) {
java.util.List _serialized = new java.util.ArrayList();
- java.util.Iterator _iterator = _dom_«property.name».iterator();
+ java.util.Iterator _iterator = _dom_«propertyName».iterator();
boolean _hasNext = _iterator.hasNext();
while(_hasNext) {
Object _listItem = _iterator.next();
- //System.out.println(" item" + _listItem);
- Object _value = «type.actualTypeArguments.get(0).serializer.name».fromDomStatic(_localQName,_listItem);
- //System.out.println(" value" + _value);
- «property.name».add(_value);
+ ////System.out.println(" item" + _listItem);
+ Object _value = «type.actualTypeArguments.get(0).serializer.resolvedName».fromDomStatic(_localQName,_listItem);
+ ////System.out.println(" value" + _value);
+ «propertyName».add(_value);
_hasNext = _iterator.hasNext();
}
}
- //System.out.println(" list" + «property.name»);
+ ////System.out.println(" list" + «propertyName»);
'''
private def dispatch CharSequence deserializeProperty(LeafListSchemaNode schema, ParameterizedType type,
- MethodSignature property) '''
- java.util.List _dom_«property.name» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
+ String propertyName) '''
+ java.util.List _dom_«propertyName» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
localName»"));
- java.util.List «property.name» = new java.util.ArrayList();
- if(_dom_«property.name» != null) {
+ java.util.List «propertyName» = new java.util.ArrayList();
+ if(_dom_«propertyName» != null) {
java.util.List _serialized = new java.util.ArrayList();
- java.util.Iterator _iterator = _dom_«property.name».iterator();
+ java.util.Iterator _iterator = _dom_«propertyName».iterator();
boolean _hasNext = _iterator.hasNext();
while(_hasNext) {
Object _listItem = _iterator.next();
if(_listItem instanceof java.util.Map.Entry) {
Object _innerValue = ((java.util.Map.Entry) _listItem).getValue();
Object _value = «deserializeValue(type.actualTypeArguments.get(0), "_innerValue")»;
- «property.name».add(_value);
+ «propertyName».add(_value);
}
_hasNext = _iterator.hasNext();
}
}
'''
- private def dispatch CharSequence deserializeProperty(LeafSchemaNode schema, Type type, MethodSignature property) '''
- java.util.List _dom_«property.name»_list =
+ private def dispatch CharSequence deserializeProperty(LeafSchemaNode schema, Type type, String propertyName) '''
+ java.util.List _dom_«propertyName»_list =
_compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»"));
- «type.resolvedName» «property.name» = null;
- if(_dom_«property.name»_list != null && _dom_«property.name»_list.size() > 0) {
- java.util.Map.Entry _dom_«property.name» = (java.util.Map.Entry) _dom_«property.name»_list.get(0);
- Object _inner_value = _dom_«property.name».getValue();
- «property.name» = «deserializeValue(type, "_inner_value")»;
+ «type.resolvedName» «propertyName» = null;
+ if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
+ java.util.Map.Entry _dom_«propertyName» = (java.util.Map.Entry) _dom_«propertyName»_list.get(0);
+ Object _inner_value = _dom_«propertyName».getValue();
+ «propertyName» = «deserializeValue(type, "_inner_value")»;
}
'''
private def dispatch CharSequence deserializeProperty(ContainerSchemaNode schema, Type type,
- MethodSignature property) '''
- java.util.List _dom_«property.name»_list =
+ String propertyName) '''
+ java.util.List _dom_«propertyName»_list =
_compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»"));
- «type.resolvedName» «property.name» = null;
- if(_dom_«property.name»_list != null && _dom_«property.name»_list.size() > 0) {
+ «type.resolvedName» «propertyName» = null;
+ if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
- java.util.Map _dom_«property.name» = (java.util.Map) _dom_«property.name»_list.get(0);
- «type.resolvedName» «property.name» = «type.serializer.name».fromDomStatic(_localQName,_dom_«property.name»);
+ java.util.Map _dom_«propertyName» = (java.util.Map) _dom_«propertyName»_list.get(0);
+ «propertyName» = «type.serializer.resolvedName».fromDomStatic(_localQName,_dom_«propertyName»);
}
'''
+ private def dispatch CharSequence deserializeProperty(ChoiceNode schema, Type type, String propertyName) '''
+ «type.resolvedName» «propertyName» = «type.serializer.resolvedName».fromDomStatic(_localQName,_compositeNode);
+ '''
+
private def dispatch String deserializeValue(GeneratedTransferObject type, String domParameter) '''
- («type.resolvedName») «type.valueSerializer.name».fromDomValue(«domParameter»);
+ («type.resolvedName») «type.valueSerializer.resolvedName».fromDomValue(«domParameter»);
'''
private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
}
- val ctCls = createClass(typeSpec.transformatorFqn) [
+ val ctCls = createClass(typeSpec.codecClassName) [
//staticField(Map,"AUGMENTATION_SERIALIZERS");
- implementsType(ctTransformator)
+ implementsType(BINDING_CODEC)
+ staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
implementsType(BindingDeserializer.asCtClass)
method(Object, "toDomValue", Object) [
modifiers = PUBLIC + FINAL + STATIC
return null;
}
«typeSpec.resolvedName» _encapsulatedValue = («typeSpec.resolvedName») $1;
- //System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
+ ////System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
«returnType.resolvedName» _value = _encapsulatedValue.getValue();
- //System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_value);
- return _value;
+ ////System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_value);
+ Object _domValue = «serializeValue(returnType, "_value")»;
+ return _domValue;
}
'''
]
modifiers = PUBLIC + FINAL + STATIC
body = '''
{
- //System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
+ ////System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
if($1 == null) {
return null;
]
val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
- log.info("DOM Codec for {} was generated {}",inputType,ret)
+ log.info("DOM Codec for {} was generated {}", inputType, ret)
return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
} catch (Exception e) {
- log.error("Cannot compile DOM Codec for {}",inputType,e);
+ log.error("Cannot compile DOM Codec for {}", inputType, e);
val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
exception.addSuppressed(e);
throw exception;
}
private def createDummyImplementation(Class<?> object, GeneratedTransferObject typeSpec) {
- log.info("Generating Dummy DOM Codec for {} with {}",object,object.classLoader)
- return createClass(typeSpec.transformatorFqn) [
+ log.info("Generating Dummy DOM Codec for {} with {}", object, object.classLoader)
+ return createClass(typeSpec.codecClassName) [
//staticField(Map,"AUGMENTATION_SERIALIZERS");
- implementsType(ctTransformator)
+ implementsType(BINDING_CODEC)
implementsType(BindingDeserializer.asCtClass)
method(Object, "toDomValue", Object) [
modifiers = PUBLIC + FINAL + STATIC
private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
Class<?> inputType, Enumeration typeSpec) {
try {
- log.info("Generating DOM Codec for {} with {}",inputType,inputType.classLoader)
- val ctCls = createClass(typeSpec.transformatorFqn) [
+ log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
+ val ctCls = createClass(typeSpec.codecClassName) [
//staticField(Map,"AUGMENTATION_SERIALIZERS");
- implementsType(ctTransformator)
+ implementsType(BINDING_CODEC)
method(Object, "toDomValue", Object) [
modifiers = PUBLIC + FINAL + STATIC
body = '''
]
val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
- log.info("DOM Codec for {} was generated {}",inputType,ret)
+ log.info("DOM Codec for {} was generated {}", inputType, ret)
return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
} catch (CodeGenerationException e) {
- throw new CodeGenerationException("Cannot compile Transformator for " + inputType,e);
+ throw new CodeGenerationException("Cannot compile Transformator for " + inputType, e);
} catch (Exception e) {
- log.error("Cannot compile DOM Codec for {}",inputType,e);
+ log.error("Cannot compile DOM Codec for {}", inputType, e);
val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
exception.addSuppressed(e);
throw exception;
}
}
-
+
def Class<?> toClassImpl(CtClass newClass, ClassLoader loader, ProtectionDomain domain) {
- val cls = newClass.toClass(loader,domain);
- if(classFileCapturePath !== null) {
+ val cls = newClass.toClass(loader, domain);
+ if (classFileCapturePath !== null) {
newClass.writeFile(classFileCapturePath.absolutePath);
}
+ listener?.onCodecCreated(cls);
return cls;
}
-
+
def debugWriteClass(CtClass class1) {
- val path = class1.name.replace(".","/")+".class"
-
- val captureFile = new File(classFileCapturePath,path);
+ val path = class1.name.replace(".", "/") + ".class"
+
+ val captureFile = new File(classFileCapturePath, path);
captureFile.createNewFile
-
-
+
}
- private def dispatch String deserializeValue(Type type, String domParameter) '''(«type.resolvedName») «domParameter»'''
+ private def dispatch String deserializeValue(Type type, String domParameter) {
+ if (INSTANCE_IDENTIFIER.equals(type)) {
+
+ return '''(«InstanceIdentifier.name») «INSTANCE_IDENTIFIER_CODEC».deserialize(«domParameter»)'''
+ }
+
+ return '''(«type.resolvedName») «domParameter»'''
+
+ }
/**
* Default catch all
*
**/
- private def dispatch CharSequence deserializeProperty(DataSchemaNode container, Type type, MethodSignature property) '''
- «type.resolvedName» «property.name» = null;
+ private def dispatch CharSequence deserializeProperty(DataSchemaNode container, Type type, String propertyName) '''
+ «type.resolvedName» «propertyName» = null;
'''
private def dispatch CharSequence deserializeProperty(DataSchemaNode container, GeneratedTypeBuilder type,
- MethodSignature property) {
- _deserializeProperty(container, type.toInstance, property)
+ String propertyName) {
+ _deserializeProperty(container, type.toInstance, propertyName)
}
public static def toSetter(String it) {
}
/*
- private def dispatch CharSequence deserializeProperty(DataSchemaNode container,GeneratedType type, MethodSignature property) '''
- «property.returnType.resolvedName» «property.name» = value.«property.name»();
- if(«property.name» != null) {
- Object domValue = «type.serializer».toDomStatic(QNAME,«property.name»);
- childNodes.add(domValue);
+ private def dispatch CharSequence deserializeProperty(DataSchemaNode container,GeneratedType type, String propertyName) '''
+ «type.resolvedName» «propertyName» = value.«propertyName»();
+ if(«propertyName» != null) {
+ Object domValue = «type.serializer».toDomStatic(QNAME,«propertyName»);
+ _childNodes.add(domValue);
}
'''
*/
private def getBuilderName(GeneratedType type) '''«type.resolvedName»Builder'''
- private def staticQNameField(CtClass it, Class node) {
+ private def staticQNameField(CtClass it, Class<?> node) {
val field = new CtField(ctQName, "QNAME", it);
field.modifiers = PUBLIC + FINAL + STATIC;
addField(field, '''«node.name».QNAME''')
}
-
+
private def staticQNameField(CtClass it, QName node) {
val field = new CtField(ctQName, "QNAME", it);
field.modifiers = PUBLIC + FINAL + STATIC;
- addField(field, '''«QName.asCtClass.name».create("«node.namespace»","«node.formattedRevision»","«node.localName»")''')
+ addField(field,
+ '''«QName.asCtClass.name».create("«node.namespace»","«node.formattedRevision»","«node.localName»")''')
}
private def dispatch String serializeBody(GeneratedType type, ListSchemaNode node) '''
{
- «QName.name» resultName = «QName.name».create($1,QNAME.getLocalName());
- java.util.List childNodes = new java.util.ArrayList();
+ «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
+ java.util.List _childNodes = new java.util.ArrayList();
«type.resolvedName» value = («type.resolvedName») $2;
«transformDataContainerBody(type.allProperties, node)»
- return ($r) java.util.Collections.singletonMap(resultName,childNodes);
+ «serializeAugmentations»
+ return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
}
'''
private def dispatch String serializeBody(GeneratedType type, ContainerSchemaNode node) '''
{
- «QName.name» resultName = «QName.name».create($1,QNAME.getLocalName());
- java.util.List childNodes = new java.util.ArrayList();
+ «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
+ java.util.List _childNodes = new java.util.ArrayList();
«type.resolvedName» value = («type.resolvedName») $2;
«transformDataContainerBody(type.allProperties, node)»
- return ($r) java.util.Collections.singletonMap(resultName,childNodes);
+ «serializeAugmentations»
+ return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
}
'''
private def dispatch String serializeBody(GeneratedType type, ChoiceCaseNode node) '''
{
- «QName.name» resultName = «QName.name».create($1,QNAME.getLocalName());
- java.util.List childNodes = new java.util.ArrayList();
+ «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
+ java.util.List _childNodes = new java.util.ArrayList();
«type.resolvedName» value = («type.resolvedName») $2;
«transformDataContainerBody(type.allProperties, node)»
- return ($r) java.util.Collections.singletonMap(resultName,childNodes);
+ «serializeAugmentations»
+ return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
}
'''
private def dispatch String serializeBody(GeneratedType type, SchemaNode node) '''
{
- «QName.name» resultName = «QName.name».create($1,QNAME.getLocalName());
- java.util.List childNodes = new java.util.ArrayList();
+ «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName());
+ java.util.List _childNodes = new java.util.ArrayList();
«type.resolvedName» value = («type.resolvedName») $2;
- return ($r) java.util.Collections.singletonMap(resultName,childNodes);
+ return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
}
'''
-
- private def transformDataContainerBody(Map<String, MethodSignature> properties, DataNodeContainer node) {
+ private def transformDataContainerBody(Map<String, Type> properties, DataNodeContainer node) {
val ret = '''
«FOR child : node.childNodes.filter[!augmenting]»
«var signature = properties.getFor(child)»
- «serializeProperty(child, signature.returnType, signature)»
+ //System.out.println("«signature.key»" + value.«signature.key»());
+ «serializeProperty(child, signature.value, signature.key)»
«ENDFOR»
'''
return ret;
}
-
- def MethodSignature getFor(Map<String,MethodSignature> map, DataSchemaNode node) {
+
+ def serializeAugmentations() '''
+ java.util.List _augmentations = (java.util.List) «AUGMENTATION_CODEC».serialize(value);
+ if(_augmentations != null) {
+ _childNodes.addAll(_augmentations);
+ }
+ '''
+
+ def Entry<String, Type> getFor(Map<String, Type> map, DataSchemaNode node) {
val sig = map.get(node.getterName);
- if(sig == null) {
- return map.get(node.booleanGetterName);
+ if (sig == null) {
+
+ return new SimpleEntry(node.booleanGetterName, map.get(node.booleanGetterName));
}
- return sig;
+ return new SimpleEntry(node.getterName, sig);
}
private static def String getBooleanGetterName(DataSchemaNode node) {
}
private def dispatch CharSequence serializeProperty(ListSchemaNode schema, ParameterizedType type,
- MethodSignature property) '''
- «property.returnType.resolvedName» «property.name» = value.«property.name»();
- if(«property.name» != null) {
- java.util.Iterator _iterator = «property.name».iterator();
+ String propertyName) '''
+ «type.resolvedName» «propertyName» = value.«propertyName»();
+ if(«propertyName» != null) {
+ java.util.Iterator _iterator = «propertyName».iterator();
boolean _hasNext = _iterator.hasNext();
while(_hasNext) {
Object _listItem = _iterator.next();
- Object _domValue = «type.actualTypeArguments.get(0).serializer.name».toDomStatic(QNAME,_listItem);
- childNodes.add(_domValue);
+ Object _domValue = «type.actualTypeArguments.get(0).serializer.resolvedName».toDomStatic(_resultName,_listItem);
+ _childNodes.add(_domValue);
_hasNext = _iterator.hasNext();
}
}
'''
- private def dispatch CharSequence serializeProperty(LeafSchemaNode schema, Type type, MethodSignature property) '''
- «property.returnType.resolvedName» «property.name» = value.«property.name»();
+ private def dispatch CharSequence serializeProperty(LeafSchemaNode schema, Type type, String propertyName) '''
+ «type.resolvedName» «propertyName» = value.«propertyName»();
- if(«property.name» != null) {
- «QName.name» _qname = «QName.name».create(resultName,"«schema.QName.localName»");
- Object _propValue = «serializeValue(type, property.name)»;
+ if(«propertyName» != null) {
+ «QName.name» _qname = «QName.name».create(_resultName,"«schema.QName.localName»");
+ Object _propValue = «serializeValue(type, propertyName)»;
if(_propValue != null) {
Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
- childNodes.add(_domValue);
+ _childNodes.add(_domValue);
}
}
'''
- private def dispatch serializeValue(GeneratedTransferObject type, String parameter) '''«type.valueSerializer.name».toDomValue(«parameter»)'''
+ private def dispatch serializeValue(GeneratedTransferObject type, String parameter) '''«type.valueSerializer.
+ resolvedName».toDomValue(«parameter»)'''
- private def dispatch serializeValue(Type signature, String property) '''«property»'''
+ private def dispatch serializeValue(Type signature, String property) {
+ if (INSTANCE_IDENTIFIER == signature) {
+ return '''«INSTANCE_IDENTIFIER_CODEC».serialize(«property»)'''
+ }
+ return '''«property»''';
+ }
- private def dispatch CharSequence serializeProperty(LeafListSchemaNode schema, Type type, MethodSignature property) '''
- «property.returnType.resolvedName» «property.name» = value.«property.name»();
- if(«property.name» != null) {
- «QName.name» _qname = «QName.name».create(resultName,"«schema.QName.localName»");
- java.util.Iterator _iterator = «property.name».iterator();
+ private def dispatch CharSequence serializeProperty(LeafListSchemaNode schema, ParameterizedType type,
+ String propertyName) '''
+ «type.resolvedName» «propertyName» = value.«propertyName»();
+ if(«propertyName» != null) {
+ «QName.name» _qname = «QName.name».create(_resultName,"«schema.QName.localName»");
+ java.util.Iterator _iterator = «propertyName».iterator();
boolean _hasNext = _iterator.hasNext();
while(_hasNext) {
Object _listItem = _iterator.next();
- Object _propValue = «property.name»;
+ Object _propValue = «serializeValue(type.actualTypeArguments.get(0), "_listItem")»;
Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
- childNodes.add(_domValue);
+ _childNodes.add(_domValue);
_hasNext = _iterator.hasNext();
}
}
'''
+ private def dispatch CharSequence serializeProperty(ChoiceNode container, GeneratedType type,
+ String propertyName) '''
+ «type.resolvedName» «propertyName» = value.«propertyName»();
+ if(«propertyName» != null) {
+ java.util.List domValue = «type.serializer.resolvedName».toDomStatic(_resultName,«propertyName»);
+ _childNodes.addAll(domValue);
+ }
+ '''
+
/**
* Default catch all
*
**/
- private def dispatch CharSequence serializeProperty(DataSchemaNode container, Type type, MethodSignature property) '''
- «property.returnType.resolvedName» «property.name» = value.«property.name»();
- if(«property.name» != null) {
- Object domValue = «property.name»;
- childNodes.add(domValue);
+ private def dispatch CharSequence serializeProperty(DataSchemaNode container, Type type, String propertyName) '''
+ «type.resolvedName» «propertyName» = value.«propertyName»();
+ if(«propertyName» != null) {
+ Object domValue = «propertyName»;
+ _childNodes.add(domValue);
}
'''
private def dispatch CharSequence serializeProperty(DataSchemaNode container, GeneratedTypeBuilder type,
- MethodSignature property) {
- serializeProperty(container, type.toInstance, property)
+ String propertyName) {
+ serializeProperty(container, type.toInstance, propertyName)
}
private def dispatch CharSequence serializeProperty(DataSchemaNode container, GeneratedType type,
- MethodSignature property) '''
- «property.returnType.resolvedName» «property.name» = value.«property.name»();
- if(«property.name» != null) {
- Object domValue = «type.serializer.name».toDomStatic(QNAME,«property.name»);
- childNodes.add(domValue);
+ String propertyName) '''
+ «type.resolvedName» «propertyName» = value.«propertyName»();
+ if(«propertyName» != null) {
+ Object domValue = «type.serializer.resolvedName».toDomStatic(_resultName,«propertyName»);
+ _childNodes.add(domValue);
}
'''
-
-
- private def transformatorFqn(GeneratedType typeSpec) {
+ private def codecClassName(GeneratedType typeSpec) {
return '''«typeSpec.resolvedName»$Broker$Codec$DOM'''
}
- private def transformatorFqn(Class typeSpec) {
+ private def codecClassName(Class typeSpec) {
return '''«typeSpec.name»$Broker$Codec$DOM'''
}
- private def HashMap<String, MethodSignature> getAllProperties(GeneratedType type) {
- val ret = new HashMap<String, MethodSignature>();
+ private def dispatch HashMap<String, Type> getAllProperties(GeneratedType type) {
+ val ret = new HashMap<String, Type>();
type.collectAllProperties(ret);
return ret;
}
- private def dispatch void collectAllProperties(GeneratedType type, Map<String, MethodSignature> set) {
+ private def dispatch void collectAllProperties(GeneratedType type, Map<String, Type> set) {
for (definition : type.methodDefinitions) {
- set.put(definition.name, definition);
+ set.put(definition.name, definition.returnType);
+ }
+ for (property : type.properties) {
+ set.put(property.getterName, property.returnType);
}
-
for (parent : type.implements) {
parent.collectAllProperties(set);
}
}
- private def dispatch void collectAllProperties(Type type, Map<String, MethodSignature> set) {
+ def String getGetterName(GeneratedProperty property) {
+ return "get" + property.name.toFirstUpper
+ }
+
+ private def dispatch void collectAllProperties(Type type, Map<String, Type> set) {
// NOOP for generic type.
}
return type.asCtClass.name;
}
+ def String getResolvedName(Class type) {
+ return type.asCtClass.name;
+ }
+
def CtClass asCtClass(Type type) {
val name = type.fullyQualifiedName
val cls = loadClassWithTCCL(type.fullyQualifiedName)
return cls.asCtClass;
}
-
-
-
- private def dispatch processException(Class<?> inputType,CodeGenerationException e){
- log.error("Cannot compile DOM Codec for {}. One of it's prerequisites was not generated.",inputType);
+
+ private def dispatch processException(Class<?> inputType, CodeGenerationException e) {
+ log.error("Cannot compile DOM Codec for {}. One of it's prerequisites was not generated.", inputType);
throw e;
}
-
- private def dispatch processException(Class<?> inputType,Exception e){
- log.error("Cannot compile DOM Codec for {}",inputType,e);
- val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType,e);
+
+ private def dispatch processException(Class<?> inputType, Exception e) {
+ log.error("Cannot compile DOM Codec for {}", inputType, e);
+ val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType, e);
throw exception;
}
Type type;
@Property
- MethodSignature signature;
+ Type returnType;
@Property
SchemaNode schemaNode;
}
try {
listener.onNotification(notification);
} catch (Exception e) {
- log.error("Unhandled exception {} thrown by listener: {} Notification: {}", e, listener, notification);
+ log.error("Unhandled exception thrown by listener: {}", listener, e);
}
return null;
}
import java.util.Map.Entry;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom(InstanceIdentifier<? extends DataObject> path);
DataObject dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode result);
+
+
}
+++ /dev/null
-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
-import com.google.common.collect.HashMultimap
-import com.google.common.collect.ArrayListMultimap
-import com.google.common.collect.Multimap
-import java.util.Collection
-import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature
-
-class BindingMapping {
-
- @Property
- val Map<Type, GeneratedTypeBuilder> typeToDefinition = new HashMap();
-
- @Property
- val Map<Type, SchemaNode> 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<? extends DataObject> obj) {
- val pathArguments = obj.path;
- var Class<? extends DataObject> parent;
- val dataDomArgs = new ArrayList<PathArgument>();
- 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<? extends DataObject> 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);
-
- }
-
- private def dispatch PathArgument toDataDomPathArgument(IdentifiableItem argument, Class<? extends DataObject> 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);
- }
-
- private def dispatch PathArgument toDataDomPathArgument(Item<?> argument, Class<? extends DataObject> parent) {
- val ref = Types.typeForClass(argument.type);
- val qname = typeToSchemaNode.get(ref).QName
- return new NodeIdentifier(qname);
- }
-
- private def Map<QName, Object> toPredicates(Object identifier, ListSchemaNode node) {
- val keyDefinitions = node.keyDefinition;
- val map = new HashMap<QName, Object>();
- 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<SchemaPath, GeneratedTypeBuilder> 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<Node<?>> toDataDomComponents(DataContainer data, DataNodeContainer node) {
- val subnodes = new ArrayList<Node<?>>();
- for (childNode : node.childNodes) {
- val value = childNode.dataDomFromParent(data);
- if (value !== null) {
- subnodes.addAll(value);
- }
- }
- return subnodes;
- }
-
- private def List<Node<?>> dataDomFromParent(DataSchemaNode node, DataContainer container) {
- if (node.augmenting) {
- return Collections.emptyList();
- }
- return dataDomFromParentImpl(node, container);
- }
-
- private def dispatch List<Node<?>> dataDomFromParentImpl(LeafSchemaNode node, DataContainer container) {
- val value = container.getSimpleValue(node.QName, node.type);
- if (value !== null) {
- return Collections.<Node<?>>singletonList(value);
- }
- return Collections.emptyList();
- }
-
- private def dispatch List<Node<?>> dataDomFromParentImpl(LeafListSchemaNode node, DataContainer container) {
- val values = container.getSimpleValues(node);
- if (values !== null) {
- //val it = new ArrayList<Node<?>>();
- //for (value : values) {
- //}
-
- }
- return Collections.emptyList();
- }
-
- private def getSimpleValues(DataContainer container, LeafListSchemaNode node) {
- return Collections.emptyList();
- }
-
- private def dispatch List<Node<?>> dataDomFromParentImpl(ListSchemaNode node, DataContainer container) {
- val qname = node.QName;
- val values = container.<List>getValue(qname, List) as List<? extends DataContainer>;
- if (values === null) {
- return Collections.emptyList;
- }
- val it = new ArrayList<Node<?>>();
- for (value : values) {
- add(value.toCompositeNode());
- }
-
- return it;
- }
-
- private def dispatch List<Node<?>> dataDomFromParentImpl(ChoiceNode node, DataContainer container) {
- }
-
- private def dispatch List<Node<?>> serializeValueImpl(List<?> list, GeneratedTypeBuilder builder,
- ListSchemaNode node) {
- val it = new ArrayList<Node<?>>();
- for (value : list) {
-
- val serVal = value.serializeValueImpl(builder, node);
- if (serVal !== null) {
- addAll(serVal);
- }
- }
- return it;
- }
-
- public static def dispatch Node<?> getSimpleValue(Object container, QName name, ExtendedType type) {
- getSimpleValue(container, name, type.baseType);
- }
-
- public static 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);
- }
-
- public static 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);
- }
-
- public static 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);
- }
-
- public static 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);
- }
-
- public static def <T> T getValue(Object object, QName node, Class<T> 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);
- }
-
- public static def <T> T getEncapsulatedValue(Object value, Class<T> 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<Node<?>> serializeValueImpl(DataContainer data, GeneratedTypeBuilder builder,
- SchemaNode node) {
- return Collections.<Node<?>>singletonList(data.toDataDom(node, builder));
- }
-
- private def dispatch List<Node<?>> 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;
- }
-
- private 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);
- }
- node.fillBuilderFromContainer(builder,loader,type,schema);
- }
-
-
-
- private def dispatch void fillDataObject(CompositeNode node, Object builder, ClassLoader loader, GeneratedType type,
- ContainerSchemaNode schema) {
- node.fillBuilderFromContainer(builder,loader,type,schema);
- }
-
-
- private def void fillBuilderFromContainer(CompositeNode node, Object builder, ClassLoader loader, GeneratedType type, DataNodeContainer schema) {
- val Multimap<QName,Node<?>> dataMap = ArrayListMultimap.create();
- for(child :node.children) {
- dataMap.put(child.nodeType,node);
- }
- for(entry : dataMap.asMap.entrySet) {
- val entrySchema = schema.getDataChildByName(entry.key);
- val entryType = type.methodDefinitions.byQName(entry.key);
- entry.value.addValueToBuilder(builder,loader,entryType,entrySchema);
- }
- }
-
- private def Type byQName(List<MethodSignature> signatures, QName name) {
-
- }
-
- private def dispatch addValueToBuilder(Collection<Node<? extends Object>> nodes, Object object, ClassLoader loader, Object object2, LeafSchemaNode container) {
-
- }
-
-
-
- private def dispatch addValueToBuilder(Collection<Node<? extends Object>> nodes, Object object, ClassLoader loader, Object object2, ContainerSchemaNode container) {
-
- }
-
-
- private def dispatch addValueToBuilder(Collection<Node<? extends Object>> nodes, Object object, ClassLoader loader, Object object2, ListSchemaNode container) {
-
- }
-
- private def dispatch addValueToBuilder(Collection<Node<? extends Object>> nodes, Object object, ClassLoader loader, Object object2, LeafListSchemaNode container) {
-
- }
-
-
-
-
- private 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) {
- var keyProperty = keyType.get(BindingGeneratorUtil.parseToClassName(key.localName));
- if (keyProperty == null) {
- keyProperty = keyType.get(BindingGeneratorUtil.parseToValidParamName(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);
- }
-
- private def dispatch Object deserializeSimpleValue(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
- LeafSchemaNode node2) {
- deserializeSimpleValueImpl(node, loader, type, node2.type);
- }
-
- private def dispatch Object deserializeSimpleValue(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
- LeafListSchemaNode node2) {
- deserializeSimpleValueImpl(node, loader, type, node2.type);
- }
-
- private def dispatch Object deserializeSimpleValueImpl(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
- ExtendedType definition) {
- deserializeSimpleValueImpl(node, loader, type, definition.baseType);
- }
-
- private def dispatch Object deserializeSimpleValueImpl(SimpleNode<? extends Object> 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;
- }
-
- private def Class<?> getClassForType(ClassLoader loader, Type type) {
- loader.loadClass(type.fullyQualifiedName);
- }
-
- private def dispatch Object deserializeSimpleValueImpl(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
- TypeDefinition definition) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
- }
-
- private def Map<String, GeneratedProperty> getKeyTypeProperties(GeneratedType type) {
- val method = FluentIterable.from(type.methodDefinitions).findFirst[name == "getKey"]
- val key = method.returnType as GeneratedTransferObject;
- val ret = new HashMap<String, GeneratedProperty>();
- for (prop : key.properties) {
- ret.put(prop.name, prop);
- }
- return ret;
- }
-
- private 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);
- }
-
- private def String getBuilderFQN(Type type) '''«type.fullyQualifiedName»Builder'''
-
- private def String getKeyFQN(Type type) '''«type.fullyQualifiedName»Key'''
-
-}
-
-@Data
-class PropertyCapture {
-
- @Property
- val Type returnType;
- @Property
- val String name;
-
-}
import javassist.ClassPool;
import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.binding.dom.serializer.impl.RuntimeGeneratedMappingServiceImpl;
import org.opendaylight.controller.sal.binding.dom.serializer.impl.TransformerGenerator;
import org.opendaylight.controller.sal.core.api.Broker;
import org.opendaylight.controller.sal.core.api.Provider;
public void onSessionInitiated(ProviderSession session) {
RuntimeGeneratedMappingServiceImpl mappingImpl = new RuntimeGeneratedMappingServiceImpl();
+ mappingImpl.setPool(new ClassPool());
SchemaService schemaService = (session.getService(SchemaService.class));
ClassPool pool = new ClassPool();
mappingImpl.setBinding(new TransformerGenerator(pool));
+++ /dev/null
-package org.opendaylight.controller.sal.binding.impl.connect.dom
-
-import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener
-import org.opendaylight.yangtools.yang.model.api.SchemaContext
-import org.opendaylight.yangtools.sal.binding.model.api.CodeGenerator
-import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl
-import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
-import java.util.Collections
-import java.util.Map.Entry
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import java.util.AbstractMap.SimpleEntry
-import org.opendaylight.controller.sal.core.api.model.SchemaService
-
-class MappingServiceImpl implements SchemaServiceListener, BindingIndependentMappingService {
-
- var extension BindingMapping mapping = new BindingMapping;
-
- @Property
- BindingGeneratorImpl binding;
-
- @Property
- SchemaService schemaService;
-
- override onGlobalContextUpdated(SchemaContext arg0) {
- recreateBindingContext(arg0);
- }
-
- def recreateBindingContext(SchemaContext schemaContext) {
- val newBinding = new BindingGeneratorImpl();
- newBinding.generateTypes(schemaContext);
- val newMapping = new BindingMapping();
- for (entry : newBinding.moduleContexts.entrySet) {
- val module = entry.key;
- val context = entry.value;
-
- newMapping.updateBinding(schemaContext, context);
- }
- mapping = newMapping
- }
-
- override CompositeNode toDataDom(DataObject data) {
- mapping.toCompositeNode(data);
- }
-
- override Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> toDataDom(
- Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry) {
- val key = mapping.toDataDom(entry.key);
- val data = mapping.toCompositeNode(entry.value);
- return new SimpleEntry(key, data);
- }
-
- override org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom(
- InstanceIdentifier<? extends DataObject> path) {
- return mapping.toDataDom(path);
- }
-
- override dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode result) {
- return mapping.dataObjectFromDataDom(path,result);
- }
-
- public def void start() {
- schemaService.registerSchemaServiceListener(this);
- recreateBindingContext(schemaService.globalContext);
- }
-}
+++ /dev/null
-package org.opendaylight.controller.sal.binding.impl.connect.dom
-
-import org.opendaylight.controller.sal.binding.dom.serializer.impl.TransformerGenerator
-import javassist.ClassPool
-import org.opendaylight.yangtools.yang.model.api.SchemaContext
-import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener
-import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl
-import java.util.Map
-import org.opendaylight.yangtools.sal.binding.model.api.Type
-import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder
-import org.opendaylight.yangtools.yang.model.api.SchemaNode
-import java.util.HashMap
-import java.util.concurrent.ConcurrentHashMap
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-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.data.api.InstanceIdentifier.PathArgument
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
-import org.opendaylight.yangtools.binding.generator.util.Types
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
-import org.opendaylight.yangtools.yang.common.QName
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier
-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
-
-class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingService, SchemaServiceListener {
-
- ClassPool pool;
-
- @Property
- extension TransformerGenerator binding;
-
- val ConcurrentMap<Type, Type> typeDefinitions = new ConcurrentHashMap();
-
- val ConcurrentMap<Class<? extends DataContainer>, TransformerWrapper> domSerializers = new ConcurrentHashMap();
-
- @Property
- val ConcurrentMap<Type, GeneratedTypeBuilder> typeToDefinition = new ConcurrentHashMap();
-
- @Property
- val ConcurrentMap<Type, SchemaNode> typeToSchemaNode = new ConcurrentHashMap();
-
- override onGlobalContextUpdated(SchemaContext arg0) {
- recreateBindingContext(arg0);
- }
-
- def recreateBindingContext(SchemaContext schemaContext) {
- val newBinding = new BindingGeneratorImpl();
- newBinding.generateTypes(schemaContext);
-
- for (entry : newBinding.moduleContexts.entrySet) {
-
- //val module = entry.key;
- val context = entry.value;
- updateBindingFor(context.childNodes, schemaContext);
-
- val typedefs = context.typedefs;
- for(typedef : typedefs.values) {
- binding.typeDefinitions.put(typedef,typedef as GeneratedType);
- }
- }
- }
-
- override CompositeNode toDataDom(DataObject data) {
- toCompositeNodeImpl(data);
- }
-
- override Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> toDataDom(
- Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry) {
- val key = toDataDomImpl(entry.key);
- val data = toCompositeNodeImpl(entry.value);
- return new SimpleEntry(key, data);
- }
-
- private def CompositeNode toCompositeNodeImpl(DataObject object) {
- val cls = object.implementedInterface;
- val transformator = resolveTransformator(cls);
- val ret = transformator.transform(object);
- return ret;
- }
-
- private def resolveTransformator(Class<? extends DataContainer> cls) {
- val serializer = domSerializers.get(cls);
- if (serializer !== null) {
- return serializer;
- }
- val transformerClass = binding.transformerFor(cls).newInstance;
- val wrapper = new TransformerWrapper(transformerClass);
- domSerializers.putIfAbsent(cls, wrapper);
- return wrapper;
- }
-
- private def org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDomImpl(
- InstanceIdentifier<? extends DataObject> object) {
- val pathArguments = object.path;
- var Class<? extends DataObject> parent;
- val dataDomArgs = new ArrayList<PathArgument>();
- for (pathArgument : pathArguments) {
- dataDomArgs.add(pathArgument.toDataDomPathArgument(parent));
- parent = pathArgument.type;
- }
-
- return new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(dataDomArgs);
- }
-
- override org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom(
- InstanceIdentifier<? extends DataObject> path) {
- return toDataDomImpl(path);
- }
-
- override dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode result) {
- return dataObjectFromDataDomImpl(path, result);
- }
-
- def DataObject dataObjectFromDataDomImpl(InstanceIdentifier<? extends DataObject> identifier, CompositeNode node) {
- val targetType = identifier.targetType
- val transformer = resolveTransformator(targetType);
- val ret = transformer.deserialize(node) as DataObject;
- return ret;
- }
-
- def void updateBindingFor(Map<SchemaPath, GeneratedTypeBuilder> 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)
- }
- }
-
- private def dispatch PathArgument toDataDomPathArgument(IdentifiableItem argument,
- Class<? extends DataObject> 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);
- }
-
- private def Map<QName, Object> toPredicates(Object identifier, ListSchemaNode node) {
- val keyDefinitions = node.keyDefinition;
- val map = new HashMap<QName, Object>();
- for (keydef : keyDefinitions) {
- val keyNode = node.getDataChildByName(keydef) as LeafSchemaNode;
- val value = BindingMapping.getSimpleValue(identifier, keydef, keyNode.type);
- map.put(keydef, value.value);
- }
- return map;
- }
-
- private def dispatch PathArgument toDataDomPathArgument(Item<?> argument, Class<? extends DataObject> parent) {
- val ref = Types.typeForClass(argument.type);
- val qname = typeToSchemaNode.get(ref).QName
- return new NodeIdentifier(qname);
- }
-
- public def void start() {
- pool = new ClassPool()
- binding = new TransformerGenerator(pool);
-
- binding.typeToDefinition = typeToDefinition
- binding.typeToSchemaNode = typeToSchemaNode
- binding.typeDefinitions = typeDefinitions
-
- }
-}
-
-class TransformerWrapper implements // //
-Delegator<BindingCodec<Map<QName, Object>, Object>> {
-
- @Property
- val BindingCodec<Map<QName, Object>, Object> delegate;
-
- new(BindingCodec<Map<QName, Object>, Object> delegate) {
- _delegate = delegate;
- }
-
- def CompositeNode transform(DataObject input) {
- val ret = delegate.serialize(input);
- val node = toNode(ret)
- return node as CompositeNode;
- }
-
- def deserialize(CompositeNode node) {
- if (node === null) {
- return null;
- }
- val Map mapCapture = node
- return delegate.deserialize(mapCapture as Map<QName,Object>);
- }
-
- static def Node<?> toNode(Map map) {
- val nodeMap = map as Map<QName,Object>;
- checkArgument(map.size == 1);
- val elem = nodeMap.entrySet.iterator.next;
- val qname = elem.key;
- val value = elem.value;
- toNodeImpl(qname, value);
- }
-
- static def dispatch Node<?> toNodeImpl(QName name, List objects) {
- val values = new ArrayList<Node<?>>(objects.size);
- for (obj : objects) {
- values.add(toNode(obj as Map));
- }
- return new CompositeNodeTOImpl(name, null, values);
- }
-
- static def dispatch Node<?> toNodeImpl(QName name, Map<QName, Object> object) {
- throw new UnsupportedOperationException("Unsupported node hierarchy.");
- }
-
- static def dispatch Node<?> toNodeImpl(QName name, Object object) {
- return new SimpleNodeTOImpl(name, null, object);
- }
-}
import java.util.concurrent.Callable;
+import java.util.concurrent.locks.Lock;
import static com.google.common.base.Preconditions.*;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
+import com.google.common.base.Optional;
+
public class ClassLoaderUtils {
public static <V> V withClassLoader(ClassLoader cls,Callable<V> function) throws Exception {
- checkNotNull(cls);
- checkNotNull(function);
+ return withClassLoaderAndLock(cls, Optional.<Lock>absent(), function);
+ }
+
+ public static <V> V withClassLoaderAndLock(ClassLoader cls,Lock lock,Callable<V> function) throws Exception {
+ checkNotNull(lock,"Lock should not be null");
+ return withClassLoaderAndLock(cls, Optional.of(lock), function);
+ }
+
+ public static <V> V withClassLoaderAndLock(ClassLoader cls,Optional<Lock> lock,Callable<V> function) throws Exception {
+ checkNotNull(cls, "Classloader should not be null");
+ checkNotNull(function,"Function should not be null");
+ if(lock.isPresent()) {
+ lock.get().lock();
+ }
ClassLoader oldCls = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(cls);
V result = function.call();
- Thread.currentThread().setContextClassLoader(oldCls);
return result;
- } catch (Exception e) {
+ } finally {
Thread.currentThread().setContextClassLoader(oldCls);
- throw new Exception(e);
+ if(lock.isPresent()) {
+ lock.get().unlock();
+ }
}
}
import java.util.List;
import java.util.Set;
+import javassist.ClassPool;
+
import org.junit.Before;
import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentDataServiceConnector;
import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService;
-import org.opendaylight.controller.sal.binding.impl.connect.dom.RuntimeGeneratedMappingServiceImpl;
-import org.opendaylight.controller.sal.binding.test.connect.dom.MappingServiceTest;
+import org.opendaylight.controller.sal.binding.dom.serializer.impl.RuntimeGeneratedMappingServiceImpl;
import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
import org.opendaylight.yangtools.yang.model.api.Module;
protected DataBrokerService biDataService;
protected DataProviderService baDataService;
+ /**
+ * Workaround for JUNIT sharing classloaders
+ *
+ */
+ protected static final ClassPool POOL = new ClassPool();
+
protected RuntimeGeneratedMappingServiceImpl mappingServiceImpl;
protected BindingIndependentMappingService mappingService;
protected DataBrokerImpl baDataImpl;
biDataImpl.registerCommitHandler(treeRoot, dataStore);
mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl();
+ mappingServiceImpl.setPool(POOL);
mappingService = mappingServiceImpl;
File pathname = new File("target/gen-classes-debug");
//System.out.println("Generated classes are captured in " + pathname.getAbsolutePath());
connectorServiceImpl.start();
String[] yangFiles= getModelFilenames();
- mappingServiceImpl.onGlobalContextUpdated(getContext(yangFiles));
+ if(yangFiles != null && yangFiles.length > 0) {
+ mappingServiceImpl.onGlobalContextUpdated(getContext(yangFiles));
+ }
}
protected String[] getModelFilenames() {
- return getModelFilenamesImpl();
+ return getAllModelFilenames();
}
- public static String[] getModelFilenamesImpl() {
+ public static String[] getAllModelFilenames() {
Predicate<String> predicate = new Predicate<String>() {
@Override
public boolean apply(String input) {
package org.opendaylight.controller.sal.binding.test.bugfix;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
import org.junit.Test;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
import static org.junit.Assert.*;
-/**
- *
- * Testcase for https://bugs.opendaylight.org/show_bug.cgi?id=144
- *
- * Cannot compile CoDec for org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow
- *
- * @author ttkacik
- *
- */
public class DOMCodecBug01Test extends AbstractDataServiceTest {
private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
private static final QName FLOW_ID_QNAME = QName.create(Flow.QNAME, "id");
private static final QName FLOW_NODE_QNAME = QName.create(Flow.QNAME, "node");
-
private static final long FLOW_ID = 1234;
private static final String NODE_ID = "node:1";
private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID));
- private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = InstanceIdentifier.builder().node(Nodes.class)
- .node(Node.class, NODE_KEY).toInstance();
-
-
+
private static final Map<QName, Object> NODE_KEY_BI = Collections.<QName, Object> singletonMap(NODE_ID_QNAME,
NODE_ID);
-
+
+ private static final InstanceIdentifier<Nodes> NODES_INSTANCE_ID_BA = InstanceIdentifier.builder() //
+ .node(Nodes.class) //
+ .toInstance();
+
+ private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier NODES_INSTANCE_ID_BI = //
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
+ .node(Nodes.QNAME) //
+ .toInstance();
+
+ private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = InstanceIdentifier.builder() //
+ .node(Nodes.class) //
+ .child(Node.class, NODE_KEY).toInstance();
+
private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier NODE_INSTANCE_ID_BI = //
- org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
- .node(Nodes.QNAME) //
- .nodeWithKey(Node.QNAME, NODE_KEY_BI) //
- .toInstance();
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
+ .node(Nodes.QNAME) //
+ .nodeWithKey(Node.QNAME, NODE_KEY_BI) //
+ .toInstance();
private static final NodeRef NODE_REF = new NodeRef(NODE_INSTANCE_ID_BA);
-
+
private static final FlowKey FLOW_KEY = new FlowKey(FLOW_ID, NODE_REF);
private static final Map<QName, Object> FLOW_KEY_BI = //
- ImmutableMap.<QName,Object>of(FLOW_ID_QNAME, FLOW_ID, FLOW_NODE_QNAME, NODE_REF);
-
-
-
+ ImmutableMap.<QName, Object> of(FLOW_ID_QNAME, FLOW_ID, FLOW_NODE_QNAME, NODE_INSTANCE_ID_BI);
private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier FLOW_INSTANCE_ID_BI = //
- org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
- .node(Flows.QNAME) //
- .nodeWithKey(Flow.QNAME, FLOW_KEY_BI) //
- .toInstance();
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
+ .node(Flows.QNAME) //
+ .nodeWithKey(Flow.QNAME, FLOW_KEY_BI) //
+ .toInstance();
private static final InstanceIdentifier<? extends DataObject> FLOW_INSTANCE_ID_BA = //
- InstanceIdentifier.builder() //
- .node(Flows.class) //
- .node(Flow.class, FLOW_KEY) //
- .toInstance();
+ InstanceIdentifier.builder() //
+ .node(Flows.class) //
+ .node(Flow.class, FLOW_KEY) //
+ .toInstance();
+
+
+
/**
- *
+ *
+ * Testcase for https://bugs.opendaylight.org/show_bug.cgi?id=
+ *
+ * Cannot compile CoDec for
+ * org.opendaylight.yang.gen.v1.urn.opendaylight.flow
+ * .config.rev130819.flows.Flow
+ *
* When invoking following code in the consumer, user got an
* IllegalStateException during creation of mapping between Java DTOs and
* data-dom.
- *
+ *
* Exception was compilation error which was caused by incorect generation
* of code.
- *
- *
+ *
+ * Reported by Depthi V V
+ *
*/
@Test
public void testIndirectGeneration() throws Exception {
+ ExecutorService basePool = Executors.newFixedThreadPool(2);
+ ListeningExecutorService listenablePool = MoreExecutors.listeningDecorator(basePool);
+
+ createFlow();
+
+ Object lock = new Object();
+ CreateFlowTask task1 = new CreateFlowTask(lock);
+ CreateFlowTask task2 = new CreateFlowTask(lock);
+ CreateFlowTask task3 = new CreateFlowTask(lock);
+
+ ListenableFuture<Void> task1Future = listenablePool.submit(task1);
+ ListenableFuture<Void> task2Future = listenablePool.submit(task2);
+ ListenableFuture<Void> task3Future = listenablePool.submit(task3);
+
+
+ ListenableFuture<List<Void>> compositeFuture = Futures.allAsList(task1Future,task2Future,task3Future);
+
+ Thread.sleep(500);
+ //lock.notifyAll();
+ compositeFuture.get();
+
+ verifyDataAreStoredProperly();
+
+ DataModificationTransaction modification2 = baDataService.beginTransaction();
+ modification2.removeConfigurationData(FLOW_INSTANCE_ID_BA);
+
+ DataObject originalData = modification2.getOriginalConfigurationData().get(FLOW_INSTANCE_ID_BA);
+ assertNotNull(originalData);
+ RpcResult<TransactionStatus> ret2 = modification2.commit().get();
+
+ assertNotNull(ret2);
+ assertEquals(TransactionStatus.COMMITED, ret2.getResult());
+
+ // Data are not in the store.
+ assertNull(baDataService.readOperationalData(FLOW_INSTANCE_ID_BA));
+
+ }
+
+ private void createFlow() throws Exception {
+
DataModificationTransaction modification = baDataService.beginTransaction();
- FlowBuilder flow = new FlowBuilder();
+ FlowBuilder flow = new FlowBuilder();
MatchBuilder match = new MatchBuilder();
VlanMatchBuilder vlanBuilder = new VlanMatchBuilder();
VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
flow.setMatch(match.build());
flow.setNode(NODE_REF);
+
+ InstructionsBuilder instructions = new InstructionsBuilder();
+ InstructionBuilder instruction = new InstructionBuilder();
+ ApplyActionsBuilder applyActions = new ApplyActionsBuilder();
+ List<Action> actionList = new ArrayList<>();
+ PopMplsActionBuilder popMplsAction = new PopMplsActionBuilder();
+ popMplsAction.setEthernetType(34);
+ actionList.add(new ActionBuilder().setAction(popMplsAction.build()).build());
+
+ applyActions.setAction(actionList );
+
+
+ instruction.setInstruction(applyActions.build());
+
+
+ List<Instruction> instructionList = Collections.<Instruction>singletonList(instruction.build());
+ instructions.setInstruction(instructionList );
+
+ flow.setInstructions(instructions.build());
modification.putConfigurationData(FLOW_INSTANCE_ID_BA, flow.build());
RpcResult<TransactionStatus> ret = modification.commit().get();
assertNotNull(ret);
assertEquals(TransactionStatus.COMMITED, ret.getResult());
-
- verifyDataAreStoredProperly();
-
-
- DataModificationTransaction modification2 = baDataService.beginTransaction();
- modification2.removeConfigurationData(FLOW_INSTANCE_ID_BA);
-
- DataObject originalData = modification2.getOriginalConfigurationData().get(FLOW_INSTANCE_ID_BA);
- assertNotNull(originalData);
- RpcResult<TransactionStatus> ret2 = modification2.commit().get();
-
- assertNotNull(ret2);
- assertEquals(TransactionStatus.COMMITED, ret2.getResult());
-
-
- // Data are not in the store.
- assertNull(baDataService.readOperationalData(FLOW_INSTANCE_ID_BA));
-
-
+ }
+
+ private class CreateFlowTask implements Callable<Void> {
+
+ final Object startSyncObject;
+
+ public CreateFlowTask(Object startSync) {
+ startSyncObject = startSync;
+ }
+
+ @Override
+ public Void call() {
+ try {
+ //startSyncObject.wait();
+ //Thread.sleep(500);
+ createFlow();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ return null;
+ }
}
private void verifyDataAreStoredProperly() {
CompositeNode biFlow = biDataService.readConfigurationData(FLOW_INSTANCE_ID_BI);
assertNotNull(biFlow);
- CompositeNode biMatch = biFlow.getFirstCompositeByName(QName.create(Flow.QNAME,Match.QNAME.getLocalName()));
+ CompositeNode biMatch = biFlow.getFirstCompositeByName(QName.create(Flow.QNAME, Match.QNAME.getLocalName()));
assertNotNull(biMatch);
}
+
+
}
--- /dev/null
+package org.opendaylight.controller.sal.binding.test.bugfix;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
+import static org.junit.Assert.*;
+
+public class DOMCodecBug02Test extends AbstractDataServiceTest {
+
+ private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
+ private static final QName FLOW_ID_QNAME = QName.create(Flow.QNAME, "id");
+ private static final QName FLOW_NODE_QNAME = QName.create(Flow.QNAME, "node");
+
+ private static final String FLOW_ID = "foo";
+ private static final String NODE_ID = "node:1";
+
+ private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID));
+
+ private static final Map<QName, Object> NODE_KEY_BI = Collections.<QName, Object> singletonMap(NODE_ID_QNAME,
+ NODE_ID);
+
+ private static final InstanceIdentifier<Nodes> NODES_INSTANCE_ID_BA = InstanceIdentifier.builder() //
+ .node(Nodes.class) //
+ .toInstance();
+
+ private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier NODES_INSTANCE_ID_BI = //
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
+ .node(Nodes.QNAME) //
+ .toInstance();
+
+ private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = InstanceIdentifier.builder() //
+ .node(Nodes.class) //
+ .child(Node.class, NODE_KEY).toInstance();
+
+ private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier NODE_INSTANCE_ID_BI = //
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
+ .node(Nodes.QNAME) //
+ .nodeWithKey(Node.QNAME, NODE_KEY_BI) //
+ .toInstance();
+ private static final NodeRef NODE_REF = new NodeRef(NODE_INSTANCE_ID_BA);
+
+ @Override
+ protected String[] getModelFilenames() {
+ return null;
+ }
+
+ /**
+ *
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testSchemaContextNotAvailable() throws Exception {
+
+ ExecutorService testExecutor = Executors.newFixedThreadPool(1);
+
+ Future<Future<RpcResult<TransactionStatus>>> future = testExecutor.submit(new Callable<Future<RpcResult<TransactionStatus>>>() {
+ @Override
+ public Future<RpcResult<TransactionStatus>> call() throws Exception {
+ NodesBuilder nodesBuilder = new NodesBuilder();
+ nodesBuilder.setNode(Collections.<Node> emptyList());
+ DataModificationTransaction transaction = baDataService.beginTransaction();
+ transaction.putOperationalData(NODES_INSTANCE_ID_BA, nodesBuilder.build());
+ return transaction.commit();
+ }
+ });
+ mappingServiceImpl.onGlobalContextUpdated(getContext(getAllModelFilenames()));
+
+ RpcResult<TransactionStatus> result = future.get().get();
+ assertEquals(TransactionStatus.COMMITED, result.getResult());
+
+
+ Nodes nodes = checkForNodes();
+ assertNotNull(nodes);
+
+ }
+
+ private Nodes checkForNodes() {
+ return (Nodes) baDataService.readOperationalData(NODES_INSTANCE_ID_BA);
+
+ }
+
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.test.bugfix;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
+import static org.junit.Assert.*;
+
+public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataChangeListener {
+
+ private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
+ private static final String NODE_ID = "openflow:1";
+
+ private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID));
+
+ private static final Map<QName, Object> NODE_KEY_BI = Collections.<QName, Object> singletonMap(NODE_ID_QNAME,
+ NODE_ID);
+
+ private static final InstanceIdentifier<Nodes> NODES_INSTANCE_ID_BA = InstanceIdentifier.builder() //
+ .node(Nodes.class) //
+ .toInstance();
+
+ private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier NODES_INSTANCE_ID_BI = //
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
+ .node(Nodes.QNAME) //
+ .toInstance();
+
+ private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = InstanceIdentifier.builder() //
+ .node(Nodes.class) //
+ .child(Node.class, NODE_KEY).toInstance();
+
+ private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier NODE_INSTANCE_ID_BI = //
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
+ .node(Nodes.QNAME) //
+ .nodeWithKey(Node.QNAME, NODE_KEY_BI) //
+ .toInstance();
+ private static final NodeRef NODE_REF = new NodeRef(NODE_INSTANCE_ID_BA);
+ private DataChangeEvent<InstanceIdentifier<?>, DataObject> receivedChangeEvent;
+
+
+
+ /**
+ * Test for Bug 148
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testAugmentSerialization() throws Exception {
+
+
+ baDataService.registerDataChangeListener(NODES_INSTANCE_ID_BA, this);
+
+ NodeBuilder nodeBuilder = new NodeBuilder();
+ nodeBuilder.setId(new NodeId(NODE_ID));
+ nodeBuilder.setKey(NODE_KEY);
+ DataModificationTransaction transaction = baDataService.beginTransaction();
+
+
+ FlowCapableNodeBuilder fnub = new FlowCapableNodeBuilder();
+ fnub.setHardware("Hardware Foo");
+ fnub.setManufacturer("Manufacturer Foo");
+ fnub.setSerialNumber("Serial Foo");
+ fnub.setDescription("Description Foo");
+ fnub.setSoftware("JUnit emulated");
+ FlowCapableNode fnu = fnub.build();
+ nodeBuilder.addAugmentation(FlowCapableNode.class, fnu);
+ Node original = nodeBuilder.build();
+ transaction.putOperationalData(NODE_INSTANCE_ID_BA, original);
+
+ RpcResult<TransactionStatus> result = transaction.commit().get();
+ assertEquals(TransactionStatus.COMMITED, result.getResult());
+
+ assertNotNull(receivedChangeEvent);
+
+ verifyNodes((Nodes) receivedChangeEvent.getUpdatedOperationalSubtree(),original);
+ assertBindingIndependentVersion(NODE_INSTANCE_ID_BI);
+ Nodes nodes = checkForNodes();
+ verifyNodes(nodes,original);
+
+
+ }
+
+ private void verifyNodes(Nodes nodes,Node original) {
+ assertNotNull(nodes);
+ assertNotNull(nodes.getNode());
+ assertEquals(1, nodes.getNode().size());
+ Node readedNode = nodes.getNode().get(0);
+ assertEquals(original.getId(), readedNode.getId());
+ assertEquals(original.getKey(), readedNode.getKey());
+
+ FlowCapableNode fnu = original.getAugmentation(FlowCapableNode.class);
+ FlowCapableNode readedAugment = readedNode.getAugmentation(FlowCapableNode.class);
+ assertNotNull(fnu);
+ assertEquals(fnu.getDescription(), readedAugment.getDescription());
+ assertEquals(fnu.getSerialNumber(), readedAugment.getSerialNumber());
+
+ }
+
+ private void assertBindingIndependentVersion(
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier nodeId) {
+ CompositeNode node = biDataService.readOperationalData(nodeId);
+ assertNotNull(node);
+ }
+
+ private Nodes checkForNodes() {
+ return (Nodes) baDataService.readOperationalData(NODES_INSTANCE_ID_BA);
+ }
+
+ @Override
+ public void onDataChanged(DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+ receivedChangeEvent = change;
+ }
+
+}
+++ /dev/null
-package org.opendaylight.controller.sal.binding.test.connect.dom;
-
-import static org.junit.Assert.*;
-
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.junit.Before;
-import org.junit.Test;
-import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService;
-import org.opendaylight.controller.sal.binding.impl.connect.dom.MappingServiceImpl;
-import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
-import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleContext;
-import org.opendaylight.yangtools.yang.binding.Augmentation;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
-
-public class MappingServiceTest {
-
- private static final QName NODES = QName.create("urn:opendaylight:inventory", "2013-08-19", "nodes");
- private static final QName NODE = QName.create(NODES,"node");
- private static final QName ID = QName.create(NODES,"id");
-
- BindingIndependentMappingService service;
- private MappingServiceImpl impl;
-
- @Before
- public void setUp() {
- impl = new MappingServiceImpl();
- service = impl;
- }
-
- @Test
- public void baDataToBiData() throws Exception {
-
- String[] yangFiles = AbstractDataServiceTest.getModelFilenamesImpl();
-
- SchemaContext ctx = AbstractDataServiceTest.getContext(yangFiles);
-
- impl.onGlobalContextUpdated(ctx);
-
- NodesBuilder nodes = new NodesBuilder();
-
- List<Node> nodeList = new ArrayList<>();
- nodeList.add(createChildNode("foo"));
- nodeList.add(createChildNode("bar"));
-
- nodes.setNode(nodeList);
- Nodes nodesTO = nodes.build();
- CompositeNode xmlNodes = service.toDataDom(nodesTO);
- assertNotNull(xmlNodes);
- List<CompositeNode> invNodes = xmlNodes.getCompositesByName(NODE);
- assertNotNull(invNodes);
- assertEquals(2, invNodes.size());
- }
-
- @Test
- public void instanceIdentifierTest() throws Exception {
-
- String[] yangFiles = AbstractDataServiceTest.getModelFilenamesImpl();
- SchemaContext ctx = AbstractDataServiceTest.getContext(yangFiles);
- impl.onGlobalContextUpdated(ctx);
-
- NodeKey nodeKey = new NodeKey(new NodeId("foo"));
- InstanceIdentifier<Node> path = InstanceIdentifier.builder().node(Nodes.class).child(Node.class, nodeKey).toInstance();
- org.opendaylight.yangtools.yang.data.api.InstanceIdentifier result = service.toDataDom(path);
- assertNotNull(result);
- assertEquals(2, result.getPath().size());
- }
-
- private Node createChildNode(String id) {
- NodeBuilder node = new NodeBuilder();
- NodeId nodeId = new NodeId(id);
-
- node.setId(nodeId);
- node.setKey(new NodeKey(nodeId));
-
- FlowCapableNodeBuilder aug = new FlowCapableNodeBuilder();
- aug.setManufacturer(id);
- node.addAugmentation(FlowCapableNode.class, aug.build());
-
- return node.build();
- }
-
-}
import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter
import org.opendaylight.yangtools.concepts.Path
import org.slf4j.LoggerFactory
-
-abstract class AbstractDataBroker<P extends Path<P>,D,DCL extends DataChangeListener<P,D>> implements
-DataModificationTransactionFactory<P, D>, //
+import java.util.HashSet
+import java.util.Map.Entry
+import java.util.Iterator
+import java.util.Collection
+import com.google.common.collect.FluentIterable;
+import java.util.Set
+import com.google.common.collect.ImmutableList
+
+abstract class AbstractDataBroker<P extends Path<P>, D, DCL extends DataChangeListener<P, D>> implements DataModificationTransactionFactory<P, D>, //
DataReader<P, D>, //
DataChangePublisher<P, D, DCL>, //
-DataProvisionService<P,D> {
+DataProvisionService<P, D> {
@Property
var ExecutorService executor;
@Property
- var AbstractDataReadRouter<P,D> dataReadRouter;
-
- Multimap<P, DataChangeListenerRegistration<P,D,DCL>> listeners = HashMultimap.create();
- Multimap<P, DataCommitHandlerRegistration<P,D>> commitHandlers = HashMultimap.create();
+ var AbstractDataReadRouter<P, D> dataReadRouter;
+ Multimap<P, DataChangeListenerRegistration<P, D, DCL>> listeners = HashMultimap.create();
+ Multimap<P, DataCommitHandlerRegistration<P, D>> commitHandlers = HashMultimap.create();
public new() {
-
+ }
+
+ protected def /*Iterator<Entry<Collection<DataChangeListenerRegistration<P,D,DCL>>,D>>*/ affectedCommitHandlers(
+ HashSet<P> paths) {
+ return FluentIterable.from(commitHandlers.asMap.entrySet)
+ .filter[key.isAffectedBy(paths)] //
+ .transformAndConcat [value] //
+ .transform[instance].toList()
}
override final readConfigurationData(P path) {
return dataReadRouter.readOperationalData(path);
}
- override final registerCommitHandler(P path,
- DataCommitHandler<P, D> commitHandler) {
- val registration = new DataCommitHandlerRegistration(path,commitHandler,this);
- commitHandlers.put(path,registration)
- return registration;
+ override final registerCommitHandler(P path, DataCommitHandler<P, D> commitHandler) {
+ val registration = new DataCommitHandlerRegistration(path, commitHandler, this);
+ commitHandlers.put(path, registration)
+ return registration;
}
override final def registerDataChangeListener(P path, DCL listener) {
return reg;
}
- final def registerDataReader(P path,DataReader<P,D> reader) {
-
- val confReg = dataReadRouter.registerConfigurationReader(path,reader);
- val dataReg = dataReadRouter.registerOperationalReader(path,reader);
-
- return new CompositeObjectRegistration(reader,Arrays.asList(confReg,dataReg));
+ final def registerDataReader(P path, DataReader<P, D> reader) {
+
+ val confReg = dataReadRouter.registerConfigurationReader(path, reader);
+ val dataReg = dataReadRouter.registerOperationalReader(path, reader);
+
+ return new CompositeObjectRegistration(reader, Arrays.asList(confReg, dataReg));
}
- protected final def removeListener(DataChangeListenerRegistration<P,D,DCL> registration) {
+ protected final def removeListener(DataChangeListenerRegistration<P, D, DCL> registration) {
listeners.remove(registration.path, registration);
}
- protected final def removeCommitHandler(DataCommitHandlerRegistration<P,D> registration) {
+ protected final def removeCommitHandler(DataCommitHandlerRegistration<P, D> registration) {
commitHandlers.remove(registration.path, registration);
}
-
- protected final def getActiveCommitHandlers() {
- return commitHandlers.entries.map[ value.instance].toSet
+
+ protected final def getActiveCommitHandlers() {
+ return commitHandlers.entries;
}
- package final def Future<RpcResult<TransactionStatus>> commit(AbstractDataTransaction<P,D> transaction) {
+ protected def /*Iterator<Entry<Collection<DataChangeListenerRegistration<P,D,DCL>>,D>>*/ affectedListenersWithInitialState(
+ HashSet<P> paths) {
+ return FluentIterable.from(listeners.asMap.entrySet).filter[key.isAffectedBy(paths)].transform [
+ val operationalState = readOperationalData(key)
+ val configurationState = readConfigurationData(key)
+ return new ListenerStateCapture(key, value, operationalState, configurationState)
+ ].toList()
+ }
+
+ protected def boolean isAffectedBy(P key, Set<P> paths) {
+ if (paths.contains(key)) {
+ return true;
+ }
+ for (path : paths) {
+ if (key.contains(path)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ package final def Future<RpcResult<TransactionStatus>> commit(AbstractDataTransaction<P, D> transaction) {
checkNotNull(transaction);
transaction.changeStatus(TransactionStatus.SUBMITED);
val task = new TwoPhaseCommit(transaction, this);
}
-package class DataChangeListenerRegistration<P extends Path<P>,D,DCL extends DataChangeListener<P,D>> extends AbstractObjectRegistration<DCL> implements ListenerRegistration<DCL> {
+@Data
+package class ListenerStateCapture<P extends Path<P>, D,DCL extends DataChangeListener<P, D>> {
- AbstractDataBroker<P,D,DCL> dataBroker;
+ @Property
+ P path;
+
+ @Property
+ Collection<DataChangeListenerRegistration<P, D, DCL>> listeners;
+
+ @Property
+ D initialOperationalState;
+
+ @Property
+ D initialConfigurationState;
+}
+
+package class DataChangeListenerRegistration<P extends Path<P>, D, DCL extends DataChangeListener<P, D>> extends AbstractObjectRegistration<DCL> implements ListenerRegistration<DCL> {
+
+ AbstractDataBroker<P, D, DCL> dataBroker;
@Property
val P path;
- new(P path, DCL instance, AbstractDataBroker<P,D,DCL> broker) {
+ new(P path, DCL instance, AbstractDataBroker<P, D, DCL> broker) {
super(instance)
dataBroker = broker;
_path = path;
}
-package class DataCommitHandlerRegistration<P extends Path<P>,D>
-extends AbstractObjectRegistration<DataCommitHandler<P, D>> {
+package class DataCommitHandlerRegistration<P extends Path<P>, D> extends AbstractObjectRegistration<DataCommitHandler<P, D>> {
- AbstractDataBroker<P,D,?> dataBroker;
+ AbstractDataBroker<P, D, ?> dataBroker;
@Property
val P path;
- new(P path, DataCommitHandler<P, D> instance,
- AbstractDataBroker<P,D,?> broker) {
+ new(P path, DataCommitHandler<P, D> instance, AbstractDataBroker<P, D, ?> broker) {
super(instance)
dataBroker = broker;
_path = path;
}
-package class TwoPhaseCommit<P extends Path<P>,D> implements Callable<RpcResult<TransactionStatus>> {
-
+package class TwoPhaseCommit<P extends Path<P>, D,DCL extends DataChangeListener<P, D>> implements Callable<RpcResult<TransactionStatus>> {
+
private static val log = LoggerFactory.getLogger(TwoPhaseCommit);
- val AbstractDataTransaction<P,D> transaction;
- val AbstractDataBroker<P,D,?> dataBroker;
+ val AbstractDataTransaction<P, D> transaction;
+ val AbstractDataBroker<P, D, DCL> dataBroker;
- new(AbstractDataTransaction<P,D> transaction, AbstractDataBroker<P,D,?> broker) {
+ new(AbstractDataTransaction<P, D> transaction, AbstractDataBroker<P, D, DCL> broker) {
this.transaction = transaction;
this.dataBroker = broker;
}
override call() throws Exception {
- val Iterable<DataCommitHandler<P, D>> commitHandlers = dataBroker.activeCommitHandlers;
+ // get affected paths
+ val affectedPaths = new HashSet<P>();
+
+ affectedPaths.addAll(transaction.createdConfigurationData.keySet);
+ affectedPaths.addAll(transaction.updatedConfigurationData.keySet);
+ affectedPaths.addAll(transaction.removedConfigurationData);
+
+ affectedPaths.addAll(transaction.createdOperationalData.keySet);
+ affectedPaths.addAll(transaction.updatedOperationalData.keySet);
+ affectedPaths.addAll(transaction.removedOperationalData);
+
+ val listeners = dataBroker.affectedListenersWithInitialState(affectedPaths);
// requesting commits
+ val Iterable<DataCommitHandler<P, D>> commitHandlers = dataBroker.affectedCommitHandlers(affectedPaths);
val List<DataCommitTransaction<P, D>> handlerTransactions = new ArrayList();
try {
for (handler : commitHandlers) {
handlerTransactions.add(handler.requestCommit(transaction));
}
} catch (Exception e) {
- log.error("Request Commit failded",e);
- return rollback(handlerTransactions,e);
+ log.error("Request Commit failded", e);
+ return rollback(handlerTransactions, e);
}
val List<RpcResult<Void>> results = new ArrayList();
try {
for (subtransaction : handlerTransactions) {
results.add(subtransaction.finish());
}
+ listeners.publishDataChangeEvent();
} catch (Exception e) {
- log.error("Finish Commit failed",e);
- return rollback(handlerTransactions,e);
+ log.error("Finish Commit failed", e);
+ return rollback(handlerTransactions, e);
}
+
return Rpcs.getRpcResult(true, TransactionStatus.COMMITED, Collections.emptySet());
+
+ }
+
+ def void publishDataChangeEvent(ImmutableList<ListenerStateCapture<P, D,DCL>> listeners) {
+ for(listenerSet : listeners) {
+ val updatedConfiguration = dataBroker.readConfigurationData(listenerSet.path);
+ val updatedOperational = dataBroker.readOperationalData(listenerSet.path);
+
+ val changeEvent = new DataChangeEventImpl(transaction,listenerSet.initialConfigurationState,listenerSet.initialOperationalState,updatedOperational,updatedConfiguration);
+ for(listener : listenerSet.listeners) {
+ try {
+ listener.instance.onDataChanged(changeEvent);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
}
- def rollback(List<DataCommitTransaction<P, D>> transactions,Exception e) {
+ def rollback(List<DataCommitTransaction<P, D>> transactions, Exception e) {
for (transaction : transactions) {
transaction.rollback()
}
+
// FIXME return encountered error.
return Rpcs.getRpcResult(false, TransactionStatus.FAILED, Collections.emptySet());
}
}
-
public abstract class AbstractDataTransaction<P extends Path<P>, D> extends AbstractDataModification<P, D> {
@Property
private val Object identifier;
-
var TransactionStatus status;
-
-
+
var AbstractDataBroker<P, D, ?> broker;
- protected new (AbstractDataBroker<P,D,?> dataBroker) {
+ protected new(AbstractDataBroker<P, D, ?> dataBroker) {
super(dataBroker);
_identifier = new Object();
broker = dataBroker;
status = TransactionStatus.NEW;
- //listeners = new ListenerRegistry<>();
+
+ //listeners = new ListenerRegistry<>();
}
- override commit() {
+ override commit() {
return broker.commit(this);
}
return false;
if (getClass() != obj.getClass())
return false;
- val other = (obj as AbstractDataTransaction<P,D>) ;
+ val other = (obj as AbstractDataTransaction<P,D>);
if (broker == null) {
if (other.broker != null)
return false;
return status;
}
-
protected abstract def void onStatusChange(TransactionStatus status);
-
+
public def changeStatus(TransactionStatus status) {
this.status = status;
onStatusChange(status);
}
-
+
}
--- /dev/null
+package org.opendaylight.controller.md.sal.common.impl.service;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataChange;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+
+public class DataChangeEventImpl<P, D> implements DataChangeEvent<P, D> {
+
+ private final DataChange<P, D> dataChange;
+
+ private final D originalConfigurationSubtree;
+ private final D originalOperationalSubtree;
+ private final D updatedOperationalSubtree;
+ private final D updatedConfigurationSubtree;
+
+
+
+
+ public DataChangeEventImpl(DataChange<P, D> dataChange, D originalConfigurationSubtree,
+ D originalOperationalSubtree, D updatedOperationalSubtree, D updatedConfigurationSubtree) {
+ super();
+ this.dataChange = dataChange;
+ this.originalConfigurationSubtree = originalConfigurationSubtree;
+ this.originalOperationalSubtree = originalOperationalSubtree;
+ this.updatedOperationalSubtree = updatedOperationalSubtree;
+ this.updatedConfigurationSubtree = updatedConfigurationSubtree;
+ }
+
+ @Override
+ public D getUpdatedOperationalSubtree() {
+ return updatedOperationalSubtree;
+ }
+
+ @Override
+ public D getUpdatedConfigurationSubtree() {
+ return updatedConfigurationSubtree;
+ }
+
+ public Map<P, D> getCreatedOperationalData() {
+ return dataChange.getCreatedOperationalData();
+ }
+
+ public Map<P, D> getCreatedConfigurationData() {
+ return dataChange.getCreatedConfigurationData();
+ }
+
+ public Map<P, D> getUpdatedOperationalData() {
+ return dataChange.getUpdatedOperationalData();
+ }
+
+ public Map<P, D> getUpdatedConfigurationData() {
+ return dataChange.getUpdatedConfigurationData();
+ }
+
+ public Set<P> getRemovedConfigurationData() {
+ return dataChange.getRemovedConfigurationData();
+ }
+
+ public Set<P> getRemovedOperationalData() {
+ return dataChange.getRemovedOperationalData();
+ }
+
+ public Map<P, D> getOriginalConfigurationData() {
+ return dataChange.getOriginalConfigurationData();
+ }
+
+ public Map<P, D> getOriginalOperationalData() {
+ return dataChange.getOriginalOperationalData();
+ }
+
+}