<artifactId>binding-generator-impl</artifactId>
<dependencies>
+ <dependency>
+ <groupId>org.javassist</groupId>
+ <artifactId>javassist</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>binding-generator-util</artifactId>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-parser-impl</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-data-impl</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>binding-generator-api</artifactId>
--- /dev/null
+package org.opendaylight.yangtools.sal.binding.generator.impl;
+
+public interface BindingClassListener {
+
+ void onBindingClassCaptured(Class<?> cls);
+
+ void onBindingClassProcessed(Class<?> cls);
+}
--- /dev/null
+package org.opendaylight.yangtools.sal.binding.generator.impl;
+
+import java.lang.reflect.Field;
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.data.impl.codec.IdentitityCodec;
+import org.opendaylight.yangtools.yang.data.impl.codec.InstanceIdentifierCodec;
+import org.opendaylight.yangtools.yang.binding.BindingCodec;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CodecMapping {
+
+ private static final Logger LOG = LoggerFactory.getLogger(CodecMapping.class);
+
+ public static final String INSTANCE_IDENTIFIER_CODEC = "INSTANCE_IDENTIFIER_CODEC";
+ public static final String IDENTITYREF_CODEC = "IDENTITYREF_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);
+ if(obj != null) {
+ instanceIdField.set(null, codec);
+ }
+ } catch (NoSuchFieldException e) {
+ LOG.trace("Instance identifier codec is not needed for {}",obj.getName(),e);
+ } catch (SecurityException | IllegalAccessException e) {
+ LOG.error("Instance identifier could not be set for {}",obj.getName(),e);
+ }
+ }
+
+
+ public static void setIdentityRefCodec(Class<?> obj,IdentitityCodec<?> codec) {
+ Field instanceIdField;
+ try {
+ instanceIdField = obj.getField(IDENTITYREF_CODEC);
+ if(obj != null) {
+ instanceIdField.set(null, codec);
+ }
+ } catch (NoSuchFieldException e) {
+ LOG.trace("Instance identifier codec is not needed for {}",obj.getName(),e);
+ } catch (SecurityException | IllegalAccessException e) {
+ LOG.error("Instance identifier could not be set for {}",obj.getName(),e);
+ }
+ }
+
+ 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) {
+ LOG.debug("BUG: Class to case mappping is not needed for {}",codec.getName(),e);
+ } catch (SecurityException | IllegalAccessException e) {
+ LOG.error("Class to case mappping could not be set for {}",codec.getName(),e);
+ }
+ }
+
+ 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) {
+ LOG.debug("BUG: Class to case mappping is not needed for {}",codec.getName(),e);
+ } catch (SecurityException | IllegalAccessException e) {
+ LOG.error("Composite node to case mappping could not be set for {}",codec.getName(),e);
+ }
+ }
+
+ public static void setAugmentationCodec(Class<? extends BindingCodec<?,?>> dataCodec,
+ BindingCodec<?,?> augmentableCodec) {
+ Field instanceIdField;
+ try {
+ instanceIdField = dataCodec.getField(AUGMENTATION_CODEC);
+ instanceIdField.set(null, augmentableCodec);
+ } catch (NoSuchFieldException e) {
+ LOG.debug("BUG: Augmentation codec is not needed for {}",dataCodec.getName(),e);
+ } catch (SecurityException | IllegalAccessException e) {
+ LOG.error("Augmentation codec could not be set for {}",dataCodec.getName(),e);
+ }
+ }
+
+
+ public static BindingCodec<?,?> getAugmentationCodec(Class<? extends BindingCodec<?,?>> dataCodec) {
+ Field instanceIdField;
+ try {
+ instanceIdField = dataCodec.getField(AUGMENTATION_CODEC);
+ return (BindingCodec<?,?>) instanceIdField.get(null);
+ } catch (NoSuchFieldException e) {
+ LOG.debug("BUG: Augmentation codec is not needed for {}",dataCodec.getName(),e);
+ } catch (SecurityException | IllegalAccessException e) {
+ LOG.error("Augmentation codec could not be set for {}",dataCodec.getName(),e);
+ }
+ return null;
+ }
+}
--- /dev/null
+package org.opendaylight.yangtools.sal.binding.generator.impl;
+
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
+
+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.yangtools.sal.binding.generator.impl;
+
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.binding.BindingCodec;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+
+public interface GeneratorListener {
+
+
+
+ void onClassProcessed(Class<?> cl);
+
+ void onCodecCreated(Class<?> codec);
+ void onValueCodecCreated(Class<?> valueClass, Class<?> valueCodec);
+ void onCaseCodecCreated(Class<?> choiceClass, Class<? extends BindingCodec<Map<QName, Object>, Object>> choiceCodec);
+ void onDataContainerCodecCreated(Class<?> dataClass, Class<? extends BindingCodec<?, ?>> dataCodec);
+
+ void onChoiceCodecCreated(Class<?> choiceClass,
+ Class<? extends BindingCodec<Map<QName, Object>, Object>> choiceCodec, ChoiceNode schema);
+}
--- /dev/null
+package org.opendaylight.yangtools.sal.binding.generator.impl
+
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yangtools.yang.data.impl.codec.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.yangtools.yang.data.impl.codec.InstanceIdentifierCodec
+import org.opendaylight.yangtools.yang.data.impl.codec.ValueWithQName
+import java.util.HashMap
+import org.slf4j.LoggerFactory
+import java.util.List
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.data.impl.codec.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
+import org.opendaylight.yangtools.yang.binding.Augmentable
+import com.google.common.collect.ImmutableList
+import org.opendaylight.yangtools.yang.binding.Augmentation
+import java.util.concurrent.ConcurrentHashMap
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections
+
+class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
+
+ private static val LOG = LoggerFactory.getLogger(InstanceIdentifierCodecImpl);
+ val CodecRegistry codecRegistry;
+
+ val Map<Class<?>, Map<List<QName>, Class<?>>> classToPreviousAugment = 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)
+ baType = baArg?.type
+ val injectAugment = classToPreviousAugment.get(baType);
+ if(injectAugment != null) {
+ val augment = injectAugment.get(scannedPath) as Class<? extends DataObject>;
+ if(augment != null) {
+ baArgs.add(new Item(augment));
+ }
+ }
+ baArgs.add(baArg)
+ }
+ val ret = new InstanceIdentifier(baArgs,baType as Class<? extends DataObject>);
+ LOG.debug("DOM Instance Identifier {} deserialized to {}",input,ret);
+ 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) {
+ var Class<?> previousAugmentation = null
+ val pathArgs = input.path as List<org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument>
+ var QName previousQName = null;
+ val components = new ArrayList<PathArgument>(pathArgs.size);
+ val qnamePath = new ArrayList<QName>(pathArgs.size);
+ for(baArg : pathArgs) {
+
+ if(!Augmentation.isAssignableFrom(baArg.type)) {
+
+ val biArg = serializePathArgument(baArg,previousQName);
+ previousQName = biArg.nodeType;
+ components.add(biArg);
+ qnamePath.add(biArg.nodeType);
+ val immutableList = ImmutableList.copyOf(qnamePath);
+ codecRegistry.putPathToClass(immutableList,baArg.type);
+ if(previousAugmentation !== null) {
+ updateAugmentationInjection(baArg.type,immutableList,previousAugmentation)
+ }
+
+ previousAugmentation = null;
+ } else {
+ previousQName = codecRegistry.getQNameForAugmentation(baArg.type as Class);
+ previousAugmentation = baArg.type;
+ }
+ }
+ val ret = new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(components);
+ LOG.debug("Binding Instance Identifier {} serialized to DOM InstanceIdentifier {}",input,ret);
+ return ret;
+ }
+
+ def updateAugmentationInjection(Class<? extends DataObject> class1, ImmutableList<QName> list, Class<?> augmentation) {
+ if(classToPreviousAugment.get(class1) == null) {
+ classToPreviousAugment.put(class1,new ConcurrentHashMap());
+ }
+ classToPreviousAugment.get(class1).put(list,augmentation);
+ }
+
+ private def dispatch PathArgument serializePathArgument(Item argument, QName previousQname) {
+ val type = argument.type;
+ val qname = BindingReflections.findQName(type);
+ if(previousQname == null) {
+ return new NodeIdentifier(qname);
+ }
+ return new NodeIdentifier(QName.create(previousQname,qname.localName));
+ }
+
+ @SuppressWarnings("rawtypes")
+ 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 = BindingReflections.findQName(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);
+ }
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.yangtools.sal.binding.generator.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) {
+ if(map instanceof Node<?>) {
+ return map as Node<?>;
+ }
+ 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) {
+ if(obj instanceof Node<?>) {
+ values.add(obj as Node<?>);
+ } else if(obj instanceof Map<?,?>) {
+ 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.yangtools.sal.binding.generator.impl;
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Field;
+import java.lang.reflect.ParameterizedType;
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.opendaylight.yangtools.sal.binding.generator.util.ClassLoaderUtils;
+import org.opendaylight.yangtools.yang.data.impl.codec.*;
+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.sal.binding.model.api.ConcreteType;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTOBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
+import org.opendaylight.yangtools.yang.binding.*;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+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.data.impl.CompositeNodeTOImpl;
+import org.opendaylight.yangtools.yang.model.api.*;
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+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 final IdentityCompositeCodec identityRefCodec = new IdentityCompositeCodec();
+
+ private TransformerGenerator generator;
+
+ // Concrete class to codecs
+ private static final Map<Class<?>, DataContainerCodec<?>> containerCodecs = new WeakHashMap<>();
+ private static final Map<Class<?>, IdentifierCodec<?>> identifierCodecs = new WeakHashMap<>();
+ private static final Map<Class<?>, ChoiceCodecImpl<?>> choiceCodecs = new WeakHashMap<>();
+ private static final Map<Class<?>, ChoiceCaseCodecImpl<?>> caseCodecs = new WeakHashMap<>();
+ private static final Map<Class<?>, AugmentableCompositeCodec> augmentableCodecs = new WeakHashMap<>();
+ private static final Map<Class<?>, AugmentationCodec<?>> augmentationCodecs = new WeakHashMap<>();
+ private static final Map<Class<?>, QName> identityQNames = new WeakHashMap<>();
+ private static final Map<QName, Type> qnamesToIdentityMap = new ConcurrentHashMap<>();
+ /** Binding type to encountered classes mapping **/
+ @SuppressWarnings("rawtypes")
+ private static final Map<Type, WeakReference<Class>> typeToClass = new ConcurrentHashMap<>();
+
+ @SuppressWarnings("rawtypes")
+ private static final ConcurrentMap<Type, ChoiceCaseCodecImpl> typeToCaseCodecs = new ConcurrentHashMap<>();
+
+ private CaseClassMapFacade classToCaseRawCodec = new CaseClassMapFacade();
+
+ private static final Map<SchemaPath, GeneratedTypeBuilder> pathToType = new ConcurrentHashMap<>();
+ private static final Map<List<QName>, Type> pathToInstantiatedType = new ConcurrentHashMap<>();
+ private static final Map<Type, QName> typeToQname = 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) {
+ AugmentationCodec<T> codec = null;
+ @SuppressWarnings("rawtypes")
+ AugmentationCodec potentialCodec = augmentationCodecs.get(object);
+ if (potentialCodec != null) {
+ codec = potentialCodec;
+ } else
+ try {
+ Class<? extends BindingCodec<Map<QName, Object>, Object>> augmentRawCodec = generator
+ .augmentationTransformerFor(object);
+ BindingCodec<Map<QName, Object>, Object> rawCodec = augmentRawCodec.newInstance();
+ codec = new AugmentationCodecWrapper<T>(rawCodec);
+ augmentationCodecs.put(augmentRawCodec, codec);
+ } catch (InstantiationException e) {
+ LOG.error("Can not instantiate raw augmentation codec {}", object.getSimpleName(), e);
+ } catch (IllegalAccessException e) {
+ LOG.debug("BUG: Constructor for {} is not accessible.", object.getSimpleName(), e);
+ }
+ Class<? extends Augmentable<?>> objectSupertype = getAugmentableArgumentFrom(object);
+ if (objectSupertype != null) {
+ getAugmentableCodec(objectSupertype).addAugmentationCodec(object, codec);
+ } else {
+ LOG.warn("Could not find augmentation target for augmentation {}", object);
+ }
+ return codec;
+ }
+
+ @Override
+ public QName getQNameForAugmentation(Class<?> cls) {
+ Preconditions.checkArgument(Augmentation.class.isAssignableFrom(cls));
+ return getCodecForAugmentation((Class<? extends Augmentation>)cls).getAugmentationQName();
+ }
+
+ private static Class<? extends Augmentable<?>> getAugmentableArgumentFrom(
+ final Class<? extends Augmentation<?>> augmentation) {
+ try {
+ Class<? extends Augmentable<?>> ret = ClassLoaderUtils.withClassLoader(augmentation.getClassLoader(),
+ new Callable<Class<? extends Augmentable<?>>>() {
+ @Override
+ @SuppressWarnings("unchecked")
+ public Class<? extends Augmentable<?>> call() throws Exception {
+ for (java.lang.reflect.Type supertype : augmentation.getGenericInterfaces()) {
+ if (supertype instanceof ParameterizedType
+ && Augmentation.class.equals(((ParameterizedType) supertype).getRawType())) {
+ ParameterizedType augmentationGeneric = (ParameterizedType) supertype;
+ return (Class<? extends Augmentable<?>>) augmentationGeneric
+ .getActualTypeArguments()[0];
+ }
+ }
+ return null;
+ }
+ });
+ return ret;
+ } catch (Exception e) {
+ LOG.debug("Could not find augmentable for {} using {}", augmentation, augmentation.getClassLoader(), e);
+ return null;
+ }
+ }
+
+ @Override
+ public Class<?> getClassForPath(List<QName> names) {
+ DataSchemaNode node = getSchemaNode(names);
+ SchemaPath path = node.getPath();
+ Type type = pathToType.get(path);
+ if (type != null) {
+ type = new ReferencedTypeImpl(type.getPackageName(), type.getName());
+ } else {
+ type = pathToInstantiatedType.get(names);
+ }
+ @SuppressWarnings("rawtypes")
+ WeakReference<Class> weakRef = typeToClass.get(type);
+ if (weakRef == null) {
+ LOG.error("Could not find loaded class for path: {} and type: {}", path, type.getFullyQualifiedName());
+ }
+ return weakRef.get();
+ }
+
+ @Override
+ public void putPathToClass(List<QName> names, Class<?> cls) {
+ Type reference = Types.typeForClass(cls);
+ pathToInstantiatedType.put(names, reference);
+ bindingClassEncountered(cls);
+ }
+
+ @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;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public void bindingClassEncountered(Class cls) {
+
+ ConcreteType typeRef = Types.typeForClass(cls);
+ if (typeToClass.containsKey(typeRef)) {
+ return;
+ }
+ LOG.trace("Binding Class {} encountered.", cls);
+ WeakReference<Class> weakRef = new WeakReference<>(cls);
+ typeToClass.put(typeRef, weakRef);
+ if (Augmentation.class.isAssignableFrom(cls)) {
+
+ } else if (DataObject.class.isAssignableFrom(cls)) {
+ @SuppressWarnings({ "unchecked", "unused" })
+ Object cdc = getCodecForDataObject((Class<? extends DataObject>) cls);
+ }
+ }
+
+ @Override
+ public void onClassProcessed(Class<?> cls) {
+ ConcreteType typeRef = Types.typeForClass(cls);
+ if (typeToClass.containsKey(typeRef)) {
+ return;
+ }
+ LOG.trace("Binding Class {} encountered.", cls);
+ WeakReference<Class> weakRef = new WeakReference<>((Class) 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) {
+ Preconditions.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 IdentitityCodec<?> getIdentityCodec() {
+ return identityRefCodec;
+ }
+
+ @Override
+ public <T extends BaseIdentity> IdentitityCodec<T> getCodecForIdentity(Class<T> codec) {
+ bindingClassEncountered(codec);
+ return identityRefCodec;
+ }
+
+ @Override
+ public void onCodecCreated(Class<?> cls) {
+ CodecMapping.setIdentifierCodec(cls, instanceIdentifierCodec);
+ CodecMapping.setIdentityRefCodec(cls, identityRefCodec);
+ }
+
+ @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 = typeToCaseCodecs.get(typeref);
+
+ Preconditions.checkState(caseCodec != null, "Case Codec was not created proactivelly for %s", caseClass.getName());
+ Preconditions.checkState(caseCodec.getSchema() != null, "Case schema is not available for %s", caseClass.getName());
+ @SuppressWarnings("unchecked")
+ Class<? extends BindingCodec> newCodec = generator.caseCodecFor(caseClass, caseCodec.getSchema());
+ 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());
+ qnamesToIdentityMap.putAll(context.getIdentities());
+ for (Entry<QName, GeneratedTOBuilder> identity : context.getIdentities().entrySet()) {
+ typeToQname.put(
+ new ReferencedTypeImpl(identity.getValue().getPackageName(), identity.getValue().getName()),
+ identity.getKey());
+ }
+ 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());
+
+ pathToType.put(caseNode.getKey(), caseNode.getValue());
+
+ ChoiceCaseNode node = (ChoiceCaseNode) SchemaContextUtil.findDataSchemaNode(module, caseNode.getKey());
+
+ if (node == null) {
+ LOG.error("YANGTools Bug: SchemaNode for {}, with path {} was not found in context.",
+ typeref.getFullyQualifiedName(), caseNode.getKey());
+ @SuppressWarnings("rawtypes")
+ ChoiceCaseCodecImpl value = new ChoiceCaseCodecImpl();
+ typeToCaseCodecs.putIfAbsent(typeref, value);
+ continue;
+ }
+ @SuppressWarnings("rawtypes")
+ ChoiceCaseCodecImpl value = new ChoiceCaseCodecImpl(node);
+ typeToCaseCodecs.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, ChoiceNode schema) {
+ ChoiceCodec<?> oldCodec = choiceCodecs.get(choiceClass);
+ Preconditions.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());
+
+ tryToCreateCasesCodecs(schema);
+
+ }
+
+ private void tryToCreateCasesCodecs(ChoiceNode schema) {
+ for (ChoiceCaseNode caseNode : schema.getCases()) {
+ SchemaPath path = caseNode.getPath();
+ GeneratedTypeBuilder type;
+ if (path != null && (type = pathToType.get(path)) != null) {
+ ReferencedTypeImpl typeref = new ReferencedTypeImpl(type.getPackageName(), type.getName());
+ ChoiceCaseCodecImpl partialCodec = typeToCaseCodecs.get(typeref);
+ if (partialCodec.getSchema() == null) {
+ partialCodec.setSchema(caseNode);
+ }
+
+ Class<?> caseClass = ClassLoaderUtils.tryToLoadClassWithTCCL(type.getFullyQualifiedName());
+ if (caseClass != null) {
+ getCaseCodecFor(caseClass);
+ }
+ }
+ }
+
+ }
+
+ @Override
+ public void onValueCodecCreated(Class<?> valueClass, Class<?> valueCodec) {
+ }
+
+ @Override
+ public void onCaseCodecCreated(Class<?> choiceClass,
+ Class<? extends BindingCodec<Map<QName, Object>, Object>> choiceCodec) {
+ }
+
+ @Override
+ public void onDataContainerCodecCreated(Class<?> dataClass, Class<? extends BindingCodec<?, ?>> dataCodec) {
+ if (Augmentable.class.isAssignableFrom(dataClass)) {
+ AugmentableCompositeCodec augmentableCodec = getAugmentableCodec(dataClass);
+ CodecMapping.setAugmentationCodec(dataCodec, augmentableCodec);
+ }
+
+ }
+
+ public 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 IntermediateMapping.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 boolean augmenting;
+ private BindingCodec delegate;
+
+ private Set<String> validNames;
+ private Set<QName> validQNames;
+ private ChoiceCaseNode schema;
+
+ public void setSchema(ChoiceCaseNode caseNode) {
+ this.schema = schema;
+ 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();
+ }
+
+ public ChoiceCaseCodecImpl() {
+ this.delegate = NOT_READY_CODEC;
+ }
+
+ public ChoiceCaseCodecImpl(ChoiceCaseNode caseNode) {
+ this.delegate = NOT_READY_CODEC;
+ setSchema(caseNode);
+ }
+
+ @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 (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 (!Objects.equals(parent.getNamespace(), child.getNamespace())
+ || !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<Entry<Class, BindingCodec<Object, Object>>> entrySet() {
+ return Collections.emptySet();
+ }
+
+ @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 BindingCodec get(Object key) {
+ if (!(key instanceof CompositeNode)) {
+ return null;
+ }
+ for (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 org.opendaylight.yangtools.yang.binding.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 Collections.emptySet();
+ }
+
+ 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 true;
+ }
+
+ @Override
+ public Set<T> keySet() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Set<Entry<T, BindingCodec<?, ?>>> entrySet() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public boolean containsValue(Object value) {
+ return false;
+ }
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ private class AugmentableCompositeCodec implements BindingCodec {
+
+ private final Class augmentableType;
+
+ Map<Class, AugmentationCodec<?>> localAugmentationCodecs = new WeakHashMap<>();
+
+ public AugmentableCompositeCodec(Class type) {
+ Preconditions.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 (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
+ LOG.debug("Could not read augmentations for {}", input, e);
+ }
+ return Collections.emptyMap();
+ }
+
+ private List serializeImpl(Map<Class, Augmentation> input) {
+ List ret = new ArrayList<>();
+ for (Entry<Class, Augmentation> entry : input.entrySet()) {
+ AugmentationCodec codec = getCodecForAugmentation(entry.getKey());
+ CompositeNode node = codec.serialize(new ValueWithQName(null, entry.getValue()));
+ ret.addAll(node.getChildren());
+ }
+ return ret;
+ }
+
+ public synchronized <T extends Augmentation<?>> void addAugmentationCodec(Class<T> augmentationClass,
+ AugmentationCodec<T> value) {
+ localAugmentationCodecs.put(augmentationClass, value);
+ }
+
+ @Override
+ public Map<Class, Augmentation> deserialize(Object input) {
+ Map<Class, Augmentation> ret = new HashMap<>();
+ if (input instanceof CompositeNode) {
+ List<Entry<Class, AugmentationCodec<?>>> codecs = new ArrayList<>(localAugmentationCodecs.entrySet());
+ for (Entry<Class, AugmentationCodec<?>> codec : codecs) {
+ ValueWithQName<?> value = codec.getValue().deserialize((CompositeNode) input);
+ if (value != null && value.getValue() != null) {
+ ret.put(codec.getKey(), (Augmentation) value.getValue());
+ }
+ }
+ }
+ return ret;
+ }
+
+ 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);
+ }
+ }
+
+ private static class AugmentationCodecWrapper<T extends Augmentation<?>> implements AugmentationCodec<T>,
+ Delegator<BindingCodec> {
+
+ private BindingCodec delegate;
+ private QName augmentationQName;
+
+ public AugmentationCodecWrapper(BindingCodec<Map<QName, Object>, Object> rawCodec) {
+ this.delegate = rawCodec;
+ this.augmentationQName = BindingReflections.findQName(rawCodec.getClass());
+ }
+
+ @Override
+ public BindingCodec getDelegate() {
+ return delegate;
+ }
+
+ @Override
+ public CompositeNode serialize(ValueWithQName<T> input) {
+ @SuppressWarnings("unchecked")
+ List<Map<QName, Object>> rawValues = (List<Map<QName, Object>>) getDelegate().serialize(input);
+ List<Node<?>> serialized = new ArrayList<>(rawValues.size());
+ for (Map<QName, Object> val : rawValues) {
+ serialized.add(IntermediateMapping.toNode(val));
+ }
+ return new CompositeNodeTOImpl(input.getQname(), null, serialized);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public ValueWithQName<T> deserialize(Node<?> input) {
+ Object rawCodecValue = getDelegate().deserialize((Map<QName, Object>) input);
+ return new ValueWithQName<T>(input.getNodeType(), (T) rawCodecValue);
+ }
+
+ @Override
+ public QName getAugmentationQName() {
+ return augmentationQName;
+ }
+ }
+
+ private class IdentityCompositeCodec implements IdentitityCodec {
+
+ @Override
+ public Object deserialize(Object input) {
+ Preconditions.checkArgument(input instanceof QName);
+ return deserialize((QName) input);
+ }
+
+ @Override
+ public Class<?> deserialize(QName input) {
+ Type type = qnamesToIdentityMap.get(input);
+ if (type == null) {
+ return null;
+ }
+ ReferencedTypeImpl typeref = new ReferencedTypeImpl(type.getPackageName(), type.getName());
+ WeakReference<Class> softref = typeToClass.get(typeref);
+ if (softref == null) {
+ return null;
+ }
+ return softref.get();
+ }
+
+ @Override
+ public QName serialize(Class input) {
+ Preconditions.checkArgument(BaseIdentity.class.isAssignableFrom(input));
+ bindingClassEncountered(input);
+ QName qname = identityQNames.get(input);
+ if (qname != null) {
+ return qname;
+ }
+ ConcreteType typeref = Types.typeForClass(input);
+ qname = typeToQname.get(typeref);
+ if (qname != null) {
+ identityQNames.put(input, qname);
+ }
+ return qname;
+ }
+
+ @Override
+ public Object serialize(Object input) {
+ Preconditions.checkArgument(input instanceof Class);
+ return serialize((Class) input);
+ }
+ }
+
+ public boolean isCodecAvailable(Class<? extends DataContainer> cls) {
+ if (containerCodecs.containsKey(cls)) {
+ return true;
+ }
+ if (identifierCodecs.containsKey(cls)) {
+ return true;
+ }
+ if (choiceCodecs.containsKey(cls)) {
+ return true;
+ }
+ if (caseCodecs.containsKey(cls)) {
+ return true;
+ }
+ if (augmentableCodecs.containsKey(cls)) {
+ return true;
+ }
+ if (augmentationCodecs.containsKey(cls)) {
+ return true;
+ }
+ return false;
+ }
+}
--- /dev/null
+package org.opendaylight.yangtools.sal.binding.generator.impl
+
+import javassist.ClassPool
+import org.opendaylight.yangtools.yang.model.api.SchemaContext
+import org.opendaylight.yangtools.yang.model.api.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 org.opendaylight.yangtools.yang.binding.DataContainer
+import java.util.concurrent.ConcurrentMap
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
+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.yangtools.yang.data.impl.codec.BindingIndependentMappingService
+import org.slf4j.LoggerFactory
+import org.opendaylight.yangtools.yang.data.impl.codec.ValueWithQName
+import org.opendaylight.yangtools.yang.data.impl.codec.DataContainerCodec
+import org.opendaylight.yangtools.binding.generator.util.Types
+//import org.osgi.framework.BundleContext
+import java.util.Hashtable
+//import org.osgi.framework.ServiceRegistration
+import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException
+import java.util.concurrent.Callable
+import org.opendaylight.yangtools.yang.binding.Augmentation
+import org.opendaylight.yangtools.sal.binding.generator.util.YangSchemaUtils
+import org.opendaylight.yangtools.yang.data.impl.codec.AugmentationCodec
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
+import java.util.ArrayList
+import org.opendaylight.yangtools.yang.data.api.Node
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
+import org.opendaylight.yangtools.yang.binding.RpcService
+import java.util.Set
+import org.opendaylight.yangtools.yang.common.QName
+import com.google.common.collect.FluentIterable
+import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil
+
+class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingService, SchemaServiceListener, AutoCloseable {
+
+ @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();
+
+ @Property
+ val ConcurrentMap<Type,Set<QName>> serviceTypeToRpc = new ConcurrentHashMap();
+
+ val promisedTypeDefinitions = HashMultimap.<Type, SettableFuture<GeneratedTypeBuilder>>create;
+
+ val promisedSchemas = HashMultimap.<Type, SettableFuture<SchemaNode>>create;
+
+ //ServiceRegistration<SchemaServiceListener> listenerRegistration
+
+ 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);
+ binding.pathToType.putAll(entry.value.childNodes)
+ val module = entry.key;
+ val context = entry.value;
+ updateBindingFor(context.childNodes, schemaContext);
+ updateBindingFor(context.cases, schemaContext);
+ val namespace = BindingGeneratorUtil.moduleNamespaceToPackageName(module);
+
+ if(!module.rpcs.empty) {
+ val rpcs = FluentIterable.from(module.rpcs).transform[QName].toSet
+ val serviceClass = new ReferencedTypeImpl(namespace,BindingGeneratorUtil.parseToClassName(module.name)+"Service");
+ serviceTypeToRpc.put(serviceClass,rpcs);
+ }
+
+ val typedefs = context.typedefs;
+ for (typedef : typedefs.entrySet) {
+ val typeRef = new ReferencedTypeImpl(typedef.value.packageName,typedef.value.name)
+ binding.typeDefinitions.put(typeRef, typedef.value as GeneratedType);
+ val schemaNode = YangSchemaUtils.findTypeDefinition(schemaContext,typedef.key);
+ if(schemaNode != null) {
+
+ binding.typeToSchemaNode.put(typeRef,schemaNode);
+ } else {
+ LOG.error("Type definition for {} is not available",typedef.value);
+ }
+
+ }
+ val augmentations = context.augmentations;
+ for (augmentation : augmentations) {
+ binding.typeToDefinition.put(augmentation, augmentation);
+ }
+
+ binding.typeToAugmentation.putAll(context.typeToAugmentation);
+ }
+ }
+
+ override CompositeNode toDataDom(DataObject data) {
+ toCompositeNodeImpl(data);
+ }
+
+ override Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> toDataDom(
+ Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry) {
+
+ try {
+ val key = toDataDom(entry.key)
+ var CompositeNode data;
+ if(Augmentation.isAssignableFrom(entry.key.targetType)) {
+ data = toCompositeNodeImpl(key,entry.value);
+ } else {
+ data = toCompositeNodeImpl(entry.value);
+ }
+ return new SimpleEntry(key, data);
+
+ } catch (Exception e) {
+ LOG.error("Error during serialization for {}.", entry.key,e);
+ throw e;
+ }
+ }
+
+ private def CompositeNode toCompositeNodeImpl(DataObject object) {
+ 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 CompositeNode toCompositeNodeImpl(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier identifier,DataObject object) {
+
+ //val cls = object.implementedInterface;
+ //waitForSchema(cls);
+ val last = identifier.path.last;
+ val codec = registry.getCodecForAugmentation(object.implementedInterface as Class) as AugmentationCodec;
+ val ret = codec.serialize(new ValueWithQName(last.nodeType, object));
+ if(last instanceof NodeIdentifierWithPredicates) {
+ val predicates = last as NodeIdentifierWithPredicates;
+ val newNodes = new ArrayList<Node<?>>(predicates.keyValues.size);
+ for(predicate : predicates.keyValues.entrySet) {
+ newNodes.add(new SimpleNodeTOImpl(predicate.key,null,predicate.value));
+ }
+ newNodes.addAll(ret.children);
+ return new CompositeNodeTOImpl(last.nodeType,null,newNodes);
+ }
+ return ret as CompositeNode;
+ }
+
+ private def void waitForSchema(Class<? extends DataContainer> class1) {
+ if(Augmentation.isAssignableFrom(class1)) {
+ /* FIXME: We should wait also for augmentations. Currently YANGTools does not provide correct
+ * mapping between java Augmentation classes and augmentations.
+ */
+ return;
+ }
+ if(registry.isCodecAvailable(class1)) {
+ return;
+ }
+ 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) {
+ dataObjectFromDataDom(path.targetType,node) as DataObject;
+ }
+
+ override fromDataDom(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry) {
+ return tryDeserialization[ |
+ registry.instanceIdentifierCodec.deserialize(entry);
+ ]
+ }
+
+ override getCodecRegistry() {
+ return getRegistry();
+ }
+
+ private static def <T> T tryDeserialization(Callable<T> deserializationBlock) throws DeserializationException {
+ try {
+ deserializationBlock.call()
+ } catch (Exception e) {
+
+ // FIXME: Make this block providing more information.
+ throw new DeserializationException(e);
+ }
+ }
+
+ 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)
+ val typeRef = new ReferencedTypeImpl(entry.value.packageName,entry.value.name)
+ typeToDefinition.put(typeRef, entry.value);
+ if (schemaNode != null) {
+ typeToSchemaNode.put(typeRef, schemaNode);
+ updatePromisedSchemas(typeRef, schemaNode);
+ }
+
+ }
+ }
+
+ public def void init() {
+ 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
+// if (ctx !== null) {
+// listenerRegistration = ctx.registerService(SchemaServiceListener, this, new Hashtable<String, String>());
+// }
+ }
+
+ override getRpcQNamesFor(Class<? extends RpcService> service) {
+ return serviceTypeToRpc.get(new ReferencedTypeImpl(service.package.name,service.simpleName));
+ }
+
+ private def getSchemaWithRetry(Type type) {
+ val typeDef = typeToSchemaNode.get(type);
+ if (typeDef !== null) {
+ return typeDef;
+ }
+ LOG.trace("Thread blocked waiting for schema for: {}",type.fullyQualifiedName)
+ 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);
+ }
+
+ override close() throws Exception {
+ //listenerRegistration?.unregister();
+ }
+
+ override dataObjectFromDataDom(Class<? extends DataContainer> container, CompositeNode domData) {
+ return tryDeserialization[ |
+ if (domData == null) {
+ return null;
+ }
+ val transformer = registry.getCodecForDataObject(container);
+ val ret = transformer.deserialize(domData)?.value as DataObject;
+ return ret;
+ ]
+ }
+
+}
--- /dev/null
+package org.opendaylight.yangtools.sal.binding.generator.impl;
+
+public interface StaticFieldInitializer {
+
+ void initializeStaticFields(Class<?> cls);
+}
--- /dev/null
+package org.opendaylight.yangtools.sal.binding.generator.impl
+
+import javassist.ClassPool
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
+import org.opendaylight.yangtools.yang.model.api.SchemaNode
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils
+import javassist.CtClass
+import java.util.Map
+import org.opendaylight.yangtools.yang.common.QName
+import javassist.CtField
+import static javassist.Modifier.*
+import static org.opendaylight.yangtools.sal.binding.generator.impl.CodecMapping.*
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
+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.Types
+import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType
+import java.util.HashMap
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
+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.List
+import java.util.TreeSet
+import com.google.common.base.Joiner
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
+import org.opendaylight.yangtools.sal.binding.model.api.Enumeration
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode
+import static org.opendaylight.yangtools.sal.binding.generator.util.ClassLoaderUtils.*;
+import org.opendaylight.yangtools.yang.binding.BindingDeserializer
+import org.opendaylight.yangtools.yang.binding.BindingCodec
+import org.slf4j.LoggerFactory
+import org.opendaylight.yangtools.sal.binding.generator.util.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
+import static extension org.opendaylight.yangtools.sal.binding.generator.util.YangSchemaUtils.*;
+import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl
+import org.opendaylight.yangtools.yang.model.util.ExtendedType
+import org.opendaylight.yangtools.yang.model.util.EnumerationType
+import static com.google.common.base.Preconditions.*
+import org.opendaylight.yangtools.yang.model.api.SchemaPath
+import javassist.CtMethod
+import javassist.CannotCompileException
+import java.util.concurrent.locks.Lock
+import java.util.concurrent.Callable
+import org.opendaylight.yangtools.sal.binding.generator.util.ClassLoaderUtils
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition
+import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition
+import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition
+import java.util.HashSet
+import java.util.Collections
+import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit
+import java.util.Set
+import org.opendaylight.yangtools.sal.binding.generator.util.XtendHelper
+
+class TransformerGenerator {
+
+ private static val log = LoggerFactory.getLogger(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 BINDING_CODEC
+
+ CtClass ctQName
+
+ @Property
+ var File classFileCapturePath;
+
+ @Property
+ var Map<Type, Type> typeDefinitions = new ConcurrentHashMap();
+
+ @Property
+ var Map<Type, GeneratedTypeBuilder> typeToDefinition = new ConcurrentHashMap();
+
+ @Property
+ var Map<SchemaPath, GeneratedTypeBuilder> pathToType = new ConcurrentHashMap();
+
+ @Property
+ var Map<Type, SchemaNode> typeToSchemaNode = new ConcurrentHashMap();
+
+ @Property
+ var Map<Type, AugmentationSchema> typeToAugmentation = new ConcurrentHashMap();
+
+ @Property
+ var GeneratorListener listener;
+
+ public static val CLASS_TYPE = Types.typeForClass(Class);
+
+ public new(ClassPool pool) {
+ classPool = pool;
+ utils = new JavassistUtils(pool)
+
+ BINDING_CODEC = BindingCodec.asCtClass;
+ ctQName = QName.asCtClass
+ }
+
+ def Class<? extends BindingCodec<Map<QName, Object>, Object>> transformerFor(Class<?> inputType) {
+ return withClassLoaderAndLock(inputType.classLoader, lock) [ |
+ val ret = getGeneratedClass(inputType)
+ if (ret !== null) {
+ listener.onClassProcessed(inputType);
+ return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+ }
+ val ref = Types.typeForClass(inputType)
+ val node = typeToSchemaNode.get(ref)
+ val typeSpecBuilder = typeToDefinition.get(ref)
+ checkState(typeSpecBuilder !== null, "Could not find typedefinition for %s", inputType.name);
+ val typeSpec = typeSpecBuilder.toInstance();
+ val newret = generateTransformerFor(inputType, typeSpec, node);
+ listener.onClassProcessed(inputType);
+ return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+ ]
+ }
+
+ def Class<? extends BindingCodec<Map<QName, Object>, Object>> transformerFor(Class<?> inputType, DataSchemaNode node) {
+ return withClassLoaderAndLock(inputType.classLoader, lock) [ |
+ val ret = getGeneratedClass(inputType)
+ if (ret !== null) {
+ listener.onClassProcessed(inputType);
+ return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+ }
+ val ref = Types.typeForClass(inputType)
+ var typeSpecBuilder = typeToDefinition.get(ref)
+ if (typeSpecBuilder == null) {
+ typeSpecBuilder = pathToType.get(node.path);
+ }
+ var schemaNode = typeToSchemaNode.get(ref);
+ if(schemaNode === null) {
+ schemaNode = node;
+ }
+ checkState(typeSpecBuilder !== null, "Could not find TypeDefinition for %s, $s", inputType.name, node);
+ val typeSpec = typeSpecBuilder.toInstance();
+ val newret = generateTransformerFor(inputType, typeSpec, schemaNode);
+ listener.onClassProcessed(inputType);
+ 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);
+ listener.onClassProcessed(inputType);
+ 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 withClassLoaderAndLock(inputType.classLoader, lock) [ |
+ val transformer = getGeneratedClass(inputType)
+ if (transformer != null) {
+ return transformer;
+ }
+ val newret = generateKeyTransformerFor(inputType, type, schema);
+ return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+ ]
+ }
+
+ 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, DataSchemaNode node) {
+ val cls = loadClassWithTCCL(type.resolvedName);
+ transformerFor(cls, node);
+ }
+
+ private def Class<?> valueSerializer(GeneratedTransferObject type, TypeDefinition<?> typeDefinition) {
+ val cls = loadClassWithTCCL(type.resolvedName);
+ val transformer = cls.generatedClass;
+ if (transformer !== null) {
+ return transformer;
+ }
+ var baseType = typeDefinition;
+ while (baseType.baseType != null) {
+ baseType = baseType.baseType;
+ }
+ val finalType = baseType;
+ return withClassLoaderAndLock(cls.classLoader, lock) [ |
+ val valueTransformer = generateValueTransformer(cls, type, finalType);
+ return valueTransformer;
+ ]
+ }
+
+ private def Class<?> valueSerializer(Enumeration type, TypeDefinition<?> typeDefinition) {
+ val cls = loadClassWithTCCL(type.resolvedName);
+ val transformer = cls.generatedClass;
+ if (transformer !== null) {
+ return transformer;
+ }
+
+ return withClassLoaderAndLock(cls.classLoader, lock) [ |
+ val valueTransformer = generateValueTransformer(cls, type);
+ return valueTransformer;
+ ]
+ }
+
+ private def generateKeyTransformerFor(Class<? extends Object> inputType, GeneratedType typeSpec, ListSchemaNode node) {
+ try {
+
+ //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
+ val properties = typeSpec.allProperties;
+ val ctCls = createClass(inputType.codecClassName) [
+ //staticField(Map,"AUGMENTATION_SERIALIZERS");
+ staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+ staticField(it, IDENTITYREF_CODEC, BindingCodec)
+ staticQNameField(node.QName);
+ implementsType(BINDING_CODEC)
+ method(Object, "toDomStatic", QName, Object) [
+ modifiers = PUBLIC + FINAL + STATIC
+ bodyChecked = '''
+ {
+ «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.resolvedName» 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);
+ }
+ '''
+ ]
+ method(Object, "fromDomStatic", QName, Object) [
+ modifiers = PUBLIC + FINAL + STATIC
+ bodyChecked = '''
+ {
+ if($2 == null){
+ return null;
+ }
+ «QName.name» _localQName = $1;
+ java.util.Map _compositeNode = (java.util.Map) $2;
+ boolean _is_empty = true;
+ «FOR key : node.keyDefinition»
+ «val propertyName = key.getterName»
+ «val keyDef = node.getDataChildByName(key)»
+ «val property = properties.get(propertyName)»
+ «deserializeProperty(keyDef, property, propertyName)»;
+ «ENDFOR»
+ «inputType.resolvedName» _value = new «inputType.name»(«node.keyDefinition.
+ keyConstructorList»);
+ return _value;
+ }
+ '''
+ ]
+ method(Object, "serialize", Object) [
+ bodyChecked = '''
+ {
+ 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) [
+ bodyChecked = '''
+ return fromDomStatic(QNAME,$1);
+ '''
+ ]
+ ]
+ val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+ log.debug("DOM Codec for {} was generated {}", inputType, ret)
+ return ret as Class<? extends BindingCodec<Map<QName,Object>, ?>>;
+ } catch (Exception e) {
+ processException(inputType, e);
+ return null;
+ }
+ }
+
+ private def Class<? extends BindingCodec<Object, Object>> generateCaseCodec(Class<?> inputType, GeneratedType type,
+ ChoiceCaseNode node) {
+ try {
+
+ //log.info("Generating DOM Codec for {} with {}, TCCL is: {}", inputType, inputType.classLoader,Thread.currentThread.contextClassLoader)
+ val ctCls = createClass(type.codecClassName) [
+ //staticField(Map,"AUGMENTATION_SERIALIZERS");
+ implementsType(BINDING_CODEC)
+ staticQNameField(node.QName);
+ staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+ staticField(it, AUGMENTATION_CODEC, BindingCodec)
+ staticField(it, IDENTITYREF_CODEC, BindingCodec)
+ method(Object, "toDomStatic", QName, Object) [
+ modifiers = PUBLIC + FINAL + STATIC
+ bodyChecked = '''
+ {
+ «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, type.allProperties, node)»
+ return ($r) _childNodes;
+ }
+ '''
+ ]
+ method(Object, "serialize", Object) [
+ bodyChecked = '''
+ {
+ 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
+ bodyChecked = deserializeBody(type, node)
+ ]
+ method(Object, "deserialize", Object) [
+ bodyChecked = '''
+ {
+ //System.out.println("«type.name»#deserialize: " +$1);
+ java.util.Map.Entry _input = (java.util.Map.Entry) $1;
+ return fromDomStatic((«QName.name»)_input.getKey(),_input.getValue());
+ }
+ '''
+ ]
+ ]
+
+ val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Object, Object>>
+ listener?.onDataContainerCodecCreated(inputType, ret);
+ log.debug("DOM Codec for {} was generated {}", inputType, ret)
+ return ret;
+ } 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(node.QName);
+ staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+ staticField(it, IDENTITYREF_CODEC, BindingCodec)
+ staticField(it, AUGMENTATION_CODEC, BindingCodec)
+ implementsType(BINDING_CODEC)
+ method(Object, "toDomStatic", QName, Object) [
+ modifiers = PUBLIC + FINAL + STATIC
+ bodyChecked = serializeBodyFacade(typeSpec, node)
+ ]
+ method(Object, "serialize", Object) [
+ bodyChecked = '''
+ {
+ 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
+ bodyChecked = deserializeBody(typeSpec, node)
+ ]
+ method(Object, "deserialize", Object) [
+ bodyChecked = '''
+ return fromDomStatic(QNAME,$1);
+ '''
+ ]
+ ]
+
+ val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Map<QName,Object>, Object>>
+ listener?.onDataContainerCodecCreated(inputType, ret);
+ log.debug("DOM Codec for {} was generated {}", inputType, ret)
+ return ret;
+ } catch (Exception e) {
+ processException(inputType, e);
+ return null;
+ }
+ }
+
+ 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 properties = type.allProperties
+ val ctCls = createClass(type.codecClassName) [
+ //staticField(Map,"AUGMENTATION_SERIALIZERS");
+ staticQNameField(node.augmentationQName);
+ staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+ staticField(it, AUGMENTATION_CODEC, BindingCodec)
+ staticField(it, IDENTITYREF_CODEC, BindingCodec)
+ implementsType(BINDING_CODEC)
+ method(Object, "toDomStatic", QName, Object) [
+ modifiers = PUBLIC + FINAL + STATIC
+ bodyChecked = '''
+ {
+ ////System.out.println("Qname " + $1);
+ ////System.out.println("Value " + $2);
+ «QName.name» _resultName = «QName.name».create(QNAME,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) [
+ bodyChecked = '''
+ {
+ 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
+ bodyChecked = '''
+ {
+ «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»();
+ boolean _is_empty = true;
+ «FOR child : node.childNodes»
+ «val signature = properties.getFor(child)»
+ «deserializeProperty(child, signature.value, signature.key)»
+ _builder.«signature.key.toSetter»(«signature.key»);
+ «ENDFOR»
+ if(_is_empty) {
+ return null;
+ }
+ return _builder.build();
+ }
+ '''
+ ]
+ method(Object, "deserialize", Object) [
+ bodyChecked = '''
+ return fromDomStatic(QNAME,$1);
+ '''
+ ]
+ ]
+
+ 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);
+ 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, IDENTITYREF_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
+ bodyChecked = '''
+ {
+ 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);
+ Object _ret = _codec.serialize(_input);
+ ////System.out.println("«typeSpec.name»#toDomStatic: " + _ret);
+ return («List.name») _ret;
+ }
+ '''
+ ]
+ method(Object, "serialize", Object) [
+ bodyChecked = '''
+ throw new «UnsupportedOperationException.name»("Direct invocation not supported.");
+ '''
+ ]
+ method(Object, "fromDomStatic", QName, Map) [
+ modifiers = PUBLIC + FINAL + STATIC
+ bodyChecked = '''
+ {
+ «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) [
+ bodyChecked = '''
+ 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, node);
+ log.debug("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>()
+ for (name : qnames) {
+ val fieldName = name.getterName;
+ names.add(fieldName);
+ }
+ return Joiner.on(",").join(names);
+ }
+
+ private def serializeBodyFacade(GeneratedType type, SchemaNode node) {
+ val ret = serializeBody(type, node);
+ return ret;
+ }
+
+ private def String deserializeBody(GeneratedType type, SchemaNode node) {
+ val ret = deserializeBodyImpl(type, node);
+ return ret;
+ }
+
+ private def deserializeKey(GeneratedType type, ListSchemaNode node) {
+ if (node.keyDefinition != null && !node.keyDefinition.empty) {
+ return '''
+ «type.resolvedName»Key getKey = («type.resolvedName»Key) «keyTransformer(type, node).canonicalName».fromDomStatic(_localQName,_compositeNode);
+ _builder.setKey(getKey);
+ ''';
+ }
+ }
+
+ private def dispatch String deserializeBodyImpl(GeneratedType type, SchemaNode node) '''
+ {
+ «QName.name» _localQName = «QName.name».create($1,QNAME.getLocalName());
+
+ if($2 == null) {
+ return null;
+ }
+ java.util.Map _compositeNode = (java.util.Map) $2;
+ «type.builderName» _builder = new «type.builderName»();
+ return _builder.build();
+ }
+ '''
+
+ private def dispatch String deserializeBodyImpl(GeneratedType type, ListSchemaNode 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»();
+ «deserializeKey(type, node)»
+ «deserializeDataNodeContainerBody(type, node)»
+ «deserializeAugmentations»
+ return _builder.build();
+ }
+ '''
+
+ private def dispatch String deserializeBodyImpl(GeneratedType type, ContainerSchemaNode 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();
+ }
+ '''
+
+ 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();
+ }
+ '''
+
+ private def deserializeDataNodeContainerBody(GeneratedType type, DataNodeContainer node) {
+ deserializeNodeContainerBodyImpl(type, type.allProperties, node);
+ }
+
+ private def deserializeNodeContainerBodyImpl(GeneratedType type, HashMap<String, Type> properties,
+ DataNodeContainer node) {
+ val ret = '''
+ boolean _is_empty = true;
+ «FOR child : node.childNodes»
+ «val signature = properties.getFor(child)»
+ «IF signature !== null»
+ «deserializeProperty(child, signature.value, signature.key)»
+ _builder.«signature.key.toSetter»(«signature.key»);
+ «ENDIF»
+ «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();
+ if(_value != null) {
+ _builder.addAugmentation(_type,_value);
+ }
+ }
+ }
+ '''
+
+ private def dispatch CharSequence deserializeProperty(ListSchemaNode schema, ParameterizedType type,
+ String propertyName) '''
+ java.util.List _dom_«propertyName» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
+ localName»"));
+ ////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_«propertyName».iterator();
+ boolean _hasNext = _iterator.hasNext();
+ while(_hasNext) {
+ Object _listItem = _iterator.next();
+ _is_empty = false;
+ ////System.out.println(" item" + _listItem);
+ Object _value = «type.actualTypeArguments.get(0).serializer(schema).resolvedName».fromDomStatic(_localQName,_listItem);
+ ////System.out.println(" value" + _value);
+ «propertyName».add(_value);
+ _hasNext = _iterator.hasNext();
+ }
+ }
+
+ ////System.out.println(" list" + «propertyName»);
+ '''
+
+ private def dispatch CharSequence deserializeProperty(LeafListSchemaNode schema, ParameterizedType type,
+ String propertyName) '''
+ java.util.List _dom_«propertyName» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
+ localName»"));
+ 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_«propertyName».iterator();
+ boolean _hasNext = _iterator.hasNext();
+ while(_hasNext) {
+ _is_empty = false;
+ 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", schema.type)»;
+ «propertyName».add(_value);
+ }
+ _hasNext = _iterator.hasNext();
+ }
+ }
+ '''
+
+ 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» «propertyName» = null;
+ if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
+ _is_empty = false;
+ 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", schema.type)»;
+ }
+ '''
+
+ private def dispatch CharSequence deserializeProperty(ContainerSchemaNode schema, Type type,
+ String propertyName) '''
+ java.util.List _dom_«propertyName»_list =
+ _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.localName»"));
+ «type.resolvedName» «propertyName» = null;
+ if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
+ _is_empty = false;
+ java.util.Map _dom_«propertyName» = (java.util.Map) _dom_«propertyName»_list.get(0);
+ «propertyName» = «type.serializer(schema).resolvedName».fromDomStatic(_localQName,_dom_«propertyName»);
+ }
+ '''
+
+ private def dispatch CharSequence deserializeProperty(ChoiceNode schema, Type type, String propertyName) '''
+ «type.resolvedName» «propertyName» = «type.serializer(schema).resolvedName».fromDomStatic(_localQName,_compositeNode);
+ if(«propertyName» != null) {
+ _is_empty = false;
+ }
+ '''
+
+ private def dispatch String deserializeValue(GeneratedTransferObject type, String domParameter,
+ TypeDefinition<?> typeDefinition) '''
+ («type.resolvedName») «type.valueSerializer(typeDefinition).resolvedName».fromDomValue(«domParameter»)
+ '''
+
+ private def dispatch String deserializeValue(Enumeration type, String domParameter, TypeDefinition<?> typeDefinition) '''
+ («type.resolvedName») «type.valueSerializer(typeDefinition).resolvedName».fromDomValue(«domParameter»)
+ '''
+
+ private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
+ Class<?> inputType, GeneratedTransferObject typeSpec, TypeDefinition<?> typeDef) {
+ try {
+
+ val returnType = typeSpec.valueReturnType;
+ if (returnType == null) {
+ val ctCls = createDummyImplementation(inputType, typeSpec);
+ val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+ return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+ }
+
+ val ctCls = createClass(typeSpec.codecClassName) [
+ //staticField(Map,"AUGMENTATION_SERIALIZERS");
+ if (inputType.isYangBindingAvailable) {
+ implementsType(BINDING_CODEC)
+ staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+ staticField(it, IDENTITYREF_CODEC, BindingCodec)
+ implementsType(BindingDeserializer.asCtClass)
+ }
+ method(Object, "toDomValue", Object) [
+ modifiers = PUBLIC + FINAL + STATIC
+ val ctSpec = typeSpec.asCtClass;
+ bodyChecked = '''
+ {
+ ////System.out.println("«inputType.simpleName»#toDomValue: "+$1);
+
+ if($1 == null) {
+ return null;
+ }
+ «typeSpec.resolvedName» _encapsulatedValue = («typeSpec.resolvedName») $1;
+ ////System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
+ «returnType.resolvedName» _value = _encapsulatedValue.getValue();
+ ////System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_value);
+ Object _domValue = «serializeValue(returnType, "_value", null)»;
+ return _domValue;
+ }
+ '''
+ ]
+ method(Object, "serialize", Object) [
+ bodyChecked = '''
+ {
+ return toDomValue($1);
+ }
+ '''
+ ]
+ method(Object, "fromDomValue", Object) [
+ modifiers = PUBLIC + FINAL + STATIC
+ bodyChecked = '''
+ {
+ ////System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
+
+ if($1 == null) {
+ return null;
+ }
+ «returnType.resolvedName» _simpleValue = «deserializeValue(returnType, "$1", null)»;
+ «typeSpec.resolvedName» _value = new «typeSpec.resolvedName»(_simpleValue);
+ return _value;
+ }
+ '''
+ ]
+ method(Object, "deserialize", Object) [
+ bodyChecked = '''{
+ return fromDomValue($1);
+ }
+ '''
+ ]
+ ]
+
+ val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+ log.debug("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);
+ val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
+ exception.addSuppressed(e);
+ throw exception;
+ }
+ }
+
+ private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
+ Class<?> inputType, GeneratedTransferObject typeSpec, UnionTypeDefinition typeDef) {
+ try {
+ val ctCls = createClass(typeSpec.codecClassName) [
+ val properties = typeSpec.allProperties;
+ val getterToTypeDefinition = XtendHelper.getTypes(typeDef).toMap[type | type.QName.getterName];
+ //staticField(Map,"AUGMENTATION_SERIALIZERS");
+ if (inputType.isYangBindingAvailable) {
+ implementsType(BINDING_CODEC)
+ staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+ staticField(it, IDENTITYREF_CODEC, BindingCodec)
+ implementsType(BindingDeserializer.asCtClass)
+ }
+ method(Object, "toDomValue", Object) [
+ modifiers = PUBLIC + FINAL + STATIC
+ val ctSpec = inputType.asCtClass;
+
+ bodyChecked = '''
+ {
+ ////System.out.println("«inputType.simpleName»#toDomValue: "+$1);
+
+ if($1 == null) {
+ return null;
+ }
+ «typeSpec.resolvedName» _value = («typeSpec.resolvedName») $1;
+ «FOR property : properties.entrySet»
+ «IF property.key != "getValue"»
+ «property.value.resolvedName» «property.key» = («property.value.resolvedName») _value.«property.
+ key»();
+ if(«property.key» != null) {
+ return «serializeValue(property.value, property.key, getterToTypeDefinition.get(property.key))»;
+ }
+ «ENDIF»
+ «ENDFOR»
+
+ return null;
+ }
+ '''
+ ]
+ method(Object, "serialize", Object) [
+ bodyChecked = '''
+ {
+ return toDomValue($1);
+ }
+ '''
+ ]
+ method(Object, "fromDomValue", Object) [
+ modifiers = PUBLIC + FINAL + STATIC
+ bodyChecked = '''
+ {
+ ////System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
+
+ if($1 == null) {
+ return null;
+ }
+ if($1 instanceof String) {
+ String _simpleValue = (String) $1;
+ return new «typeSpec.resolvedName»(_simpleValue.toCharArray());
+ }
+ return null;
+ }
+ '''
+ ]
+ method(Object, "deserialize", Object) [
+ bodyChecked = '''{
+ return fromDomValue($1);
+ }
+ '''
+ ]
+ ]
+
+ val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+ log.debug("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);
+ val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
+ exception.addSuppressed(e);
+ throw exception;
+ }
+ }
+
+
+ private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateValueTransformer(
+ Class<?> inputType, GeneratedTransferObject typeSpec, BitsTypeDefinition typeDef) {
+ try {
+ val ctCls = createClass(typeSpec.codecClassName) [
+ //staticField(Map,"AUGMENTATION_SERIALIZERS");
+ if (inputType.isYangBindingAvailable) {
+ implementsType(BINDING_CODEC)
+ staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+ staticField(it, IDENTITYREF_CODEC, BindingCodec)
+ implementsType(BindingDeserializer.asCtClass)
+ }
+ method(Object, "toDomValue", Object) [
+ modifiers = PUBLIC + FINAL + STATIC
+ val ctSpec = typeSpec.asCtClass;
+ bodyChecked = '''
+ {
+ ////System.out.println("«inputType.simpleName»#toDomValue: "+$1);
+
+ if($1 == null) {
+ return null;
+ }
+ «typeSpec.resolvedName» _encapsulatedValue = («typeSpec.resolvedName») $1;
+ «HashSet.resolvedName» _value = new «HashSet.resolvedName»();
+ //System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
+
+ «FOR bit : typeDef.bits»
+ «val getter = bit.getterName()»
+ if(Boolean.TRUE.equals(_encapsulatedValue.«getter»())) {
+ _value.add("«bit.name»");
+ }
+ «ENDFOR»
+ «Set.resolvedName» _domValue = «Collections.resolvedName».unmodifiableSet(_value);
+ //System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_domValue);
+
+ return _domValue;
+ }
+ '''
+ ]
+ method(Object, "serialize", Object) [
+ bodyChecked = '''
+ {
+ return toDomValue($1);
+ }
+ '''
+ ]
+ method(Object, "fromDomValue", Object) [
+ modifiers = PUBLIC + FINAL + STATIC
+ val sortedBits = typeDef.bits.sort[o1, o2|o1.propertyName.compareTo(o2.propertyName)]
+ bodyChecked = '''
+ {
+ //System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
+
+ if($1 == null) {
+ return null;
+ }
+ «Set.resolvedName» _domValue = («Set.resolvedName») $1;
+ «FOR bit : sortedBits»
+ Boolean «bit.propertyName» = Boolean.valueOf(_domValue.contains("«bit.name»"));
+ «ENDFOR»
+
+ return new «inputType.resolvedName»(«FOR bit : sortedBits SEPARATOR ","»«bit.propertyName»«ENDFOR»);
+ }
+ '''
+ ]
+ method(Object, "deserialize", Object) [
+ bodyChecked = '''{
+ return fromDomValue($1);
+ }
+ '''
+ ]
+ ]
+
+ val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+ log.debug("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);
+ val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
+ exception.addSuppressed(e);
+ throw exception;
+ }
+ }
+
+ def String getPropertyName(Bit bit) {
+ '''_«BindingGeneratorUtil.parseToValidParamName(bit.name)»'''
+ }
+
+ def String getterName(Bit bit) {
+
+ val paramName = BindingGeneratorUtil.parseToValidParamName(bit.name);
+ return '''is«paramName.toFirstUpper»''';
+ }
+
+ def boolean isYangBindingAvailable(Class<?> class1) {
+ try {
+ val bindingCodecClass = class1.classLoader.loadClass(BINDING_CODEC.name);
+ return bindingCodecClass !== null;
+ } catch (ClassNotFoundException e) {
+ return false;
+ }
+ }
+
+ private def createDummyImplementation(Class<?> object, GeneratedTransferObject typeSpec) {
+ log.trace("Generating Dummy DOM Codec for {} with {}", object, object.classLoader)
+ return createClass(typeSpec.codecClassName) [
+ if (object.isYangBindingAvailable) {
+ implementsType(BINDING_CODEC)
+ staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
+ staticField(it, IDENTITYREF_CODEC, BindingCodec)
+ implementsType(BindingDeserializer.asCtClass)
+ }
+ //implementsType(BindingDeserializer.asCtClass)
+ method(Object, "toDomValue", Object) [
+ modifiers = PUBLIC + FINAL + STATIC
+ bodyChecked = '''{
+ if($1 == null) {
+ return null;
+ }
+ return $1.toString();
+
+ }'''
+ ]
+ method(Object, "serialize", Object) [
+ bodyChecked = '''
+ {
+ return toDomValue($1);
+ }
+ '''
+ ]
+ method(Object, "fromDomValue", Object) [
+ modifiers = PUBLIC + FINAL + STATIC
+ bodyChecked = '''return null;'''
+ ]
+ method(Object, "deserialize", Object) [
+ bodyChecked = '''{
+ return fromDomValue($1);
+ }
+ '''
+ ]
+ ]
+ }
+
+ private def Type getValueReturnType(GeneratedTransferObject object) {
+ for (prop : object.properties) {
+ if (prop.name == "value") {
+ return prop.returnType;
+ }
+ }
+ if (object.superType != null) {
+ return getValueReturnType(object.superType);
+ }
+ return null;
+ }
+
+ private def Class<?> generateValueTransformer(Class<?> inputType, Enumeration typeSpec) {
+ try {
+ val typeRef = new ReferencedTypeImpl(typeSpec.packageName, typeSpec.name);
+ val schema = typeToSchemaNode.get(typeRef) as ExtendedType;
+ val enumSchema = schema.baseType as EnumerationType;
+
+ //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
+ val ctCls = createClass(typeSpec.codecClassName) [
+ //staticField(Map,"AUGMENTATION_SERIALIZERS");
+ //implementsType(BINDING_CODEC)
+ method(Object, "toDomValue", Object) [
+ modifiers = PUBLIC + FINAL + STATIC
+ bodyChecked = '''{
+ if($1 == null) {
+ return null;
+ }
+ «typeSpec.resolvedName» _value = («typeSpec.resolvedName») $1;
+ «FOR en : enumSchema.values»
+ if(«typeSpec.resolvedName».«BindingGeneratorUtil.parseToClassName(en.name)».equals(_value)) {
+ return "«en.name»";
+ }
+ «ENDFOR»
+ return null;
+ }
+ '''
+ ]
+ method(Object, "serialize", Object) [
+ bodyChecked = '''
+ return toDomValue($1);
+ '''
+ ]
+ method(Object, "fromDomValue", Object) [
+ modifiers = PUBLIC + FINAL + STATIC
+ bodyChecked = '''
+ {
+ if($1 == null) {
+ return null;
+ }
+ String _value = (String) $1;
+ «FOR en : enumSchema.values»
+ if("«en.name»".equals(_value)) {
+ return «typeSpec.resolvedName».«BindingGeneratorUtil.parseToClassName(en.name)»;
+ }
+ «ENDFOR»
+ return null;
+ }
+ '''
+ ]
+ method(Object, "deserialize", Object) [
+ bodyChecked = '''
+ return fromDomValue($1);
+ '''
+ ]
+ ]
+
+ val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+ log.debug("DOM Codec for {} was generated {}", inputType, ret)
+ return ret;
+ } catch (CodeGenerationException e) {
+ throw new CodeGenerationException("Cannot compile Transformator for " + inputType, e);
+ } catch (Exception 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) {
+ 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);
+ captureFile.createNewFile
+
+ }
+
+ private def dispatch String deserializeValue(Type type, String domParameter, TypeDefinition<?> typeDef) {
+ if (INSTANCE_IDENTIFIER.equals(type)) {
+ return '''(«InstanceIdentifier.name») «INSTANCE_IDENTIFIER_CODEC».deserialize(«domParameter»)'''
+ } else if (CLASS_TYPE.equals(type)) {
+ return '''(«Class.name») «IDENTITYREF_CODEC».deserialize(«domParameter»)'''
+ }
+ return '''(«type.resolvedName») «domParameter»'''
+
+ }
+
+ /**
+ * Default catch all
+ *
+ **/
+ private def dispatch CharSequence deserializeProperty(DataSchemaNode container, Type type, String propertyName) '''
+ «type.resolvedName» «propertyName» = null;
+ '''
+
+ private def dispatch CharSequence deserializeProperty(DataSchemaNode container, GeneratedTypeBuilder type,
+ String propertyName) {
+ _deserializeProperty(container, type.toInstance, propertyName)
+ }
+
+ public static def toSetter(String it) {
+
+ if (startsWith("is")) {
+ return "set" + substring(2);
+ } else if (startsWith("get")) {
+ return "set" + substring(3);
+ }
+ return "set" + it;
+ }
+
+ /*
+ 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, 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»")''')
+ }
+
+ 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();
+ «type.resolvedName» value = («type.resolvedName») $2;
+ «transformDataContainerBody(type, type.allProperties, node)»
+ «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();
+ «type.resolvedName» value = («type.resolvedName») $2;
+ «transformDataContainerBody(type, type.allProperties, node)»
+ «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();
+ «type.resolvedName» value = («type.resolvedName») $2;
+ «transformDataContainerBody(type, type.allProperties, node)»
+ «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();
+ «type.resolvedName» value = («type.resolvedName») $2;
+ return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
+ }
+ '''
+
+ private def transformDataContainerBody(Type type, Map<String, Type> properties, DataNodeContainer node) {
+ val ret = '''
+ «FOR child : node.childNodes»
+ «val signature = properties.getFor(child)»
+ «IF signature !== null»
+ ////System.out.println("«type.name»#«signature.key»" + value.«signature.key»());
+ «serializeProperty(child, signature.value, signature.key)»
+ «ENDIF»
+ «ENDFOR»
+ '''
+ return ret;
+ }
+
+ private 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) {
+ var sig = map.get(node.getterName);
+ if (sig != null) {
+ return new SimpleEntry(node.getterName, sig);
+ }
+ sig = map.get(node.booleanGetterName);
+ if (sig != null) {
+ return new SimpleEntry(node.booleanGetterName, map.get(node.booleanGetterName));
+ }
+ return null;
+ }
+
+ private static def String getBooleanGetterName(DataSchemaNode node) {
+ return "is" + BindingGeneratorUtil.parseToClassName(node.QName.localName);
+ }
+
+ private static def String getGetterName(DataSchemaNode node) {
+ return "get" + BindingGeneratorUtil.parseToClassName(node.QName.localName);
+ }
+
+ private static def String getGetterName(QName node) {
+ return "get" + BindingGeneratorUtil.parseToClassName(node.localName);
+ }
+
+ private def dispatch CharSequence serializeProperty(ListSchemaNode schema, ParameterizedType type,
+ String propertyName) '''
+ «type.resolvedName» «propertyName» = value.«propertyName»();
+ ////System.out.println("«propertyName»:" + «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(schema).resolvedName».toDomStatic(_resultName,_listItem);
+ _childNodes.add(_domValue);
+ _hasNext = _iterator.hasNext();
+ }
+ }
+ '''
+
+ private def dispatch CharSequence serializeProperty(LeafSchemaNode schema, Type type, String propertyName) '''
+ «type.resolvedName» «propertyName» = value.«propertyName»();
+
+ if(«propertyName» != null) {
+ «QName.name» _qname = «QName.name».create(_resultName,"«schema.QName.localName»");
+ Object _propValue = «serializeValue(type, propertyName, schema.type)»;
+ if(_propValue != null) {
+ Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
+ _childNodes.add(_domValue);
+ }
+ }
+ '''
+
+ private def dispatch serializeValue(GeneratedTransferObject type, String parameter, TypeDefinition<?> typeDefinition) {
+ '''«type.valueSerializer(typeDefinition).resolvedName».toDomValue(«parameter»)'''
+ }
+
+ private def dispatch serializeValue(Enumeration type, String parameter, TypeDefinition<?> typeDefinition) {
+ '''«type.valueSerializer(typeDefinition).resolvedName».toDomValue(«parameter»)'''
+ }
+
+ private def dispatch serializeValue(Type signature, String property, TypeDefinition<?> typeDefinition) {
+ if (INSTANCE_IDENTIFIER == signature) {
+ return '''«INSTANCE_IDENTIFIER_CODEC».serialize(«property»)'''
+ } else if (CLASS_TYPE.equals(signature)) {
+ return '''(«QName.resolvedName») «IDENTITYREF_CODEC».serialize(«property»)'''
+ }
+ if ("char[]" == signature.name) {
+ return '''new String(«property»)''';
+ }
+ return '''«property»''';
+ }
+
+ 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 = «serializeValue(type.actualTypeArguments.get(0), "_listItem", schema.type)»;
+ Object _domValue = java.util.Collections.singletonMap(_qname,_propValue);
+ _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(container).resolvedName».toDomStatic(_resultName,«propertyName»);
+ _childNodes.addAll(domValue);
+ }
+ '''
+
+ /**
+ * Default catch all
+ *
+ **/
+ 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,
+ String propertyName) {
+ serializeProperty(container, type.toInstance, propertyName)
+ }
+
+ private def dispatch CharSequence serializeProperty(DataSchemaNode container, GeneratedType type,
+ String propertyName) '''
+ «type.resolvedName» «propertyName» = value.«propertyName»();
+ if(«propertyName» != null) {
+ Object domValue = «type.serializer(container).resolvedName».toDomStatic(_resultName,«propertyName»);
+ _childNodes.add(domValue);
+ }
+ '''
+
+ private def codecClassName(GeneratedType typeSpec) {
+ return '''«typeSpec.resolvedName»$Broker$Codec$DOM'''
+ }
+
+ private def codecClassName(Class<?> typeSpec) {
+ return '''«typeSpec.name»$Broker$Codec$DOM'''
+ }
+
+ private def 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, Type> set) {
+ for (definition : type.methodDefinitions) {
+ set.put(definition.name, definition.returnType);
+ }
+ for (property : type.properties) {
+ set.put(property.getterName, property.returnType);
+ }
+ for (parent : type.implements) {
+ parent.collectAllProperties(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.
+ }
+
+ def String getResolvedName(Type type) {
+ return type.asCtClass.name;
+ }
+
+ def String getResolvedName(Class<?> type) {
+ return type.asCtClass.name;
+ }
+
+ def CtClass asCtClass(Type type) {
+ 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);
+ 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);
+ throw exception;
+ }
+
+ private def setBodyChecked(CtMethod method, String body) {
+ try {
+ method.setBody(body);
+ } catch (CannotCompileException e) {
+ log.error("Cannot compile method: {}#{} {}, Reason: {} Body: {}", method.declaringClass, method.name,
+ method.signature, e.message, body)
+ throw e;
+ }
+ }
+
+ private def <V> V withClassLoaderAndLock(ClassLoader cls, Lock lock, Callable<V> function) throws Exception {
+ appendClassLoaderIfMissing(cls);
+ ClassLoaderUtils.withClassLoaderAndLock(cls, lock, function);
+ }
+
+}
+
+@Data
+class PropertyPair {
+
+ String getterName;
+
+ Type type;
+
+ @Property
+ Type returnType;
+ @Property
+ SchemaNode schemaNode;
+}
--- /dev/null
+package org.opendaylight.yangtools.sal.binding.generator.util;
+
+import javassist.CtClass;
+
+public interface ClassGenerator {
+ void process(CtClass cls);
+}
--- /dev/null
+package org.opendaylight.yangtools.sal.binding.generator.util;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.locks.Lock;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+
+public final class ClassLoaderUtils {
+
+ private ClassLoaderUtils() {
+ throw new UnsupportedOperationException("Utility class");
+ }
+
+ public static <V> V withClassLoader(ClassLoader cls, Callable<V> function) throws Exception {
+ 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);
+ return function.call();
+ } finally {
+ Thread.currentThread().setContextClassLoader(oldCls);
+ if (lock.isPresent()) {
+ lock.get().unlock();
+ }
+ }
+ }
+
+ public static Object construct(Constructor<? extends Object> constructor, List<Object> objects)
+ throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+ Object[] initargs = objects.toArray(new Object[] {});
+ return constructor.newInstance(initargs);
+ }
+
+ public static Class<?> loadClassWithTCCL(String name) throws ClassNotFoundException {
+ if ("byte[]".equals(name)) {
+ return byte[].class;
+ } else if("char[]".equals(name)) {
+ return char[].class;
+ }
+ try {
+ return Thread.currentThread().getContextClassLoader().loadClass(name);
+ } catch (ClassNotFoundException e) {
+ String[] components = name.split("\\.");
+ String potentialOuter;
+ int length = components.length;
+ if (length > 2 && (potentialOuter = components[length - 2]) != null && Character.isUpperCase(potentialOuter.charAt(0))) {
+
+ String outerName = Joiner.on(".").join(Arrays.asList(components).subList(0, length - 1));
+ String innerName = outerName + "$" + components[length-1];
+ return Thread.currentThread().getContextClassLoader().loadClass(innerName);
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ public static Class<?> tryToLoadClassWithTCCL(String fullyQualifiedName) {
+ try {
+ return loadClassWithTCCL(fullyQualifiedName);
+ } catch (ClassNotFoundException e) {
+ return null;
+ }
+ }
+}
--- /dev/null
+package org.opendaylight.yangtools.sal.binding.generator.util;
+
+public class CodeGenerationException extends RuntimeException{
+
+ public CodeGenerationException() {
+ super();
+ }
+
+ public CodeGenerationException(String message, Throwable cause, boolean enableSuppression,
+ boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+
+ public CodeGenerationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public CodeGenerationException(String message) {
+ super(message);
+ }
+
+ public CodeGenerationException(Throwable cause) {
+ super(cause);
+ }
+}
--- /dev/null
+package org.opendaylight.yangtools.sal.binding.generator.util;
+
+import javassist.CtField;
+
+public interface FieldGenerator {
+ void process(CtField field);
+}
--- /dev/null
+package org.opendaylight.yangtools.sal.binding.generator.util
+
+import javassist.CtClass
+import javassist.CtMethod
+import javassist.ClassPool
+import java.util.Arrays
+import static com.google.common.base.Preconditions.*;
+import javassist.CtField
+import javassist.Modifier
+import javassist.NotFoundException
+import javassist.LoaderClassPath
+import javassist.ClassClassPath
+import java.util.concurrent.locks.Lock
+import java.util.concurrent.locks.ReentrantLock
+import org.slf4j.LoggerFactory
+import java.util.HashMap
+import java.util.WeakHashMap
+
+class JavassistUtils {
+
+ private static val LOG = LoggerFactory.getLogger(JavassistUtils);
+
+ private val loaderClassPaths = new WeakHashMap<ClassLoader,LoaderClassPath>();
+
+ ClassPool classPool
+
+ @Property
+ val Lock lock = new ReentrantLock();
+
+ new(ClassPool pool) {
+ classPool = pool;
+ }
+
+ def void method(CtClass it, Class<?> returnType, String name, Class<?> parameter, MethodGenerator function1) {
+ val method = new CtMethod(returnType.asCtClass, name, Arrays.asList(parameter.asCtClass), it);
+ function1.process(method);
+ it.addMethod(method);
+ }
+
+ def void method(CtClass it, Class<?> returnType, String name, Class<?> parameter1, Class<?> parameter2, MethodGenerator function1) {
+ val method = new CtMethod(returnType.asCtClass, name, Arrays.asList(parameter1.asCtClass,parameter2.asCtClass), it);
+ function1.process(method);
+ it.addMethod(method);
+ }
+
+
+ def void staticMethod(CtClass it, Class<?> returnType, String name, Class<?> parameter, MethodGenerator function1) {
+ val method = new CtMethod(returnType.asCtClass, name, Arrays.asList(parameter.asCtClass), it);
+ function1.process(method);
+ it.addMethod(method);
+ }
+
+ def void implementMethodsFrom(CtClass target, CtClass source, MethodGenerator function1) {
+ for (method : source.methods) {
+ if (method.declaringClass == source) {
+ val redeclaredMethod = new CtMethod(method, target, null);
+ function1.process(redeclaredMethod);
+ target.addMethod(redeclaredMethod);
+ }
+ }
+ }
+
+ 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);
+ return target;
+ }
+
+ def void implementsType(CtClass it, CtClass supertype) {
+ checkArgument(supertype.interface, "Supertype must be interface");
+ addInterface(supertype);
+ }
+
+ def asCtClass(Class<?> class1) {
+ classPool.get(class1);
+ }
+
+ def CtField field(CtClass it, String name, Class<?> returnValue) {
+ val field = new CtField(returnValue.asCtClass, name, it);
+ field.modifiers = Modifier.PUBLIC
+ 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 {
+ return pool.get(cls.name)
+ } catch (NotFoundException e) {
+ appendClassLoaderIfMissing(cls.classLoader)
+ try {
+ return pool.get(cls.name)
+ } catch (NotFoundException ef) {
+ LOG.warn("Appending ClassClassPath for {}",cls);
+ pool.appendClassPath(new ClassClassPath(cls));
+
+ return pool.get(cls.name)
+ }
+ }
+ }
+
+ def void appendClassLoaderIfMissing(ClassLoader loader) {
+ if(loaderClassPaths.containsKey(loader)) {
+ return;
+ }
+ val ctLoader = new LoaderClassPath(loader);
+ classPool.appendClassPath(ctLoader);
+ }
+
+ def void ensureClassLoader(Class<?> child) {
+ appendClassLoaderIfMissing(child.classLoader);
+ }
+}
--- /dev/null
+package org.opendaylight.yangtools.sal.binding.generator.util;
+
+import javassist.CtMethod;
+
+public interface MethodGenerator {
+ void process(CtMethod method);
+}
--- /dev/null
+package org.opendaylight.yangtools.sal.binding.generator.util;
+
+import java.util.List;
+
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
+
+public class XtendHelper {
+
+ @SuppressWarnings({"rawtypes","unchecked"})
+ public static Iterable<TypeDefinition> getTypes(UnionTypeDefinition definition) {
+ return (Iterable<TypeDefinition>) (List) definition.getTypes();
+ }
+}
--- /dev/null
+package org.opendaylight.yangtools.sal.binding.generator.util;
+
+import java.util.List;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.*;
+
+import com.google.common.base.Preconditions;
+
+public class YangSchemaUtils {
+
+ public static final String AUGMENT_IDENTIFIER = "augment-identifier";
+
+
+ public YangSchemaUtils() {
+ throw new UnsupportedOperationException("Helper class. Instantiation is prohibited");
+ }
+
+
+ public static QName getAugmentationQName(AugmentationSchema augmentation) {
+ Preconditions.checkNotNull(augmentation, "Augmentation must not be null.");
+ QName identifier = getAugmentationIdentifier(augmentation);
+ if(identifier != null) {
+ return identifier;
+ }
+ for(DataSchemaNode child : augmentation.getChildNodes()) {
+ // FIXME: Return true name
+ return QName.create(child.getQName(), "foo_augment");
+ }
+ // FIXME: Allways return a qname with module namespace.
+ return null;
+ }
+
+ public static QName getAugmentationIdentifier(AugmentationSchema augmentation) {
+ for(UnknownSchemaNode extension : augmentation.getUnknownSchemaNodes()) {
+ if(AUGMENT_IDENTIFIER.equals(extension.getNodeType().getLocalName())) {
+ return extension.getQName();
+ }
+ }
+ return null;
+ }
+
+
+ public static TypeDefinition<?> findTypeDefinition(SchemaContext context, SchemaPath path) {
+ List<QName> arguments = path.getPath();
+ QName first = arguments.get(0);
+ QName typeQName = arguments.get(arguments.size() -1);
+ DataNodeContainer previous = context.findModuleByNamespaceAndRevision(first.getNamespace(), first.getRevision());
+ if(previous == null) {
+ return null;
+ }
+ Preconditions.checkArgument(arguments.size() == 1);
+ for (QName qName : arguments) {
+ //previous.getDataChildByName(qName);
+ }
+ for(TypeDefinition<?> typedef : previous.getTypeDefinitions()) {
+ if(typedef.getQName().equals(typeQName)) {
+ return typedef;
+ }
+ }
+ return null;
+ }
+}
<dependencyManagement>
<dependencies>
- <!-- Local Dependencies -->
+ <dependency>
+ <groupId>org.javassist</groupId>
+ <artifactId>javassist</artifactId>
+ <version>${javassist.version}</version>
+ </dependency>
+
+ <!-- Local Dependencies -->
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>binding-model-api</artifactId>
<artifactId>yang-data-api</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-data-impl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-util</artifactId>
<build>
<pluginManagement>
- <plugins>
+ <plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<xtend.version>2.4.3</xtend.version>
<groovy.version>2.1.6</groovy.version>
<mockito.version>1.9.5</mockito.version>
+ <javassist.version>3.17.1-GA</javassist.version>
</properties>
<scm>
<version>${maven.jar.version}</version>
<configuration>
<archive>
- <!-- Bundle OSGi Manifest created by maven-bundle-plugin
+ <!-- Bundle OSGi Manifest created by maven-bundle-plugin
into jar file -->
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
</archive>
<groupId>${project.groupId}</groupId>
<artifactId>yang-data-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>yang-parser-impl</artifactId>
--- /dev/null
+package org.opendaylight.yangtools.yang.data.impl.codec;
+
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.common.QName;
+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);
+
+ public QName getAugmentationQName();
+}
--- /dev/null
+package org.opendaylight.yangtools.yang.data.impl.codec;
+
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+public interface BindingIndependentMappingService {
+
+ CodecRegistry getCodecRegistry();
+
+ CompositeNode toDataDom(DataObject data);
+
+ Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> toDataDom(
+ Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry);
+
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom(InstanceIdentifier<? extends DataObject> path);
+
+ DataObject dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode result) throws DeserializationException;
+
+ InstanceIdentifier<?> fromDataDom(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry) throws DeserializationException;
+
+ Set<QName> getRpcQNamesFor(Class<? extends RpcService> service);
+
+ DataContainer dataObjectFromDataDom(Class<? extends DataContainer> inputClass, CompositeNode domInput);
+
+}
--- /dev/null
+package org.opendaylight.yangtools.yang.data.impl.codec;
+
+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.yangtools.yang.data.impl.codec;
+
+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.yangtools.yang.data.impl.codec;
+
+import java.util.List;
+
+import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.common.QName;
+
+
+public interface CodecRegistry {
+
+ InstanceIdentifierCodec getInstanceIdentifierCodec();
+
+ IdentitityCodec<?> getIdentityCodec();
+
+ <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);
+
+ <T extends BaseIdentity> IdentitityCodec<T> getCodecForIdentity(Class<T> codec);
+
+ Class<?> getClassForPath(List<QName> names);
+
+ IdentifierCodec<?> getKeyCodecForPath(List<QName> names);
+
+
+ void bindingClassEncountered(Class<?> cls);
+
+ void putPathToClass(List<QName> names, Class<?> cls);
+
+ public abstract QName getQNameForAugmentation(Class<?> cls);
+}
--- /dev/null
+package org.opendaylight.yangtools.yang.data.impl.codec;
+
+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 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.yangtools.yang.data.impl.codec;
+
+public class DeserializationException extends Exception {
+
+ public DeserializationException() {
+ }
+
+ public DeserializationException(String message) {
+ super(message);
+ }
+
+ public DeserializationException(Throwable cause) {
+ super(cause);
+ }
+
+ public DeserializationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public DeserializationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+
+}
--- /dev/null
+package org.opendaylight.yangtools.yang.data.impl.codec;
+
+import org.opendaylight.yangtools.yang.binding.BindingCodec;
+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.yangtools.yang.data.impl.codec;
+
+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.yangtools.yang.data.impl.codec;
+
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.BindingCodec;
+import org.opendaylight.yangtools.yang.common.QName;
+
+public interface IdentitityCodec<T extends BaseIdentity> extends BindingCodec<QName, Class<T>>{
+
+ @Override
+ public QName serialize(Class<T> input);
+
+ @Override
+ public Class<T> deserialize(QName input);
+}
--- /dev/null
+package org.opendaylight.yangtools.yang.data.impl.codec;
+
+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.yangtools.yang.data.impl.codec;
+
+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.yangtools.yang.model.api;
+
+import java.util.EventListener;
+
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+// TODO rename to schemaContextListener
+public interface SchemaServiceListener extends EventListener {
+
+ void onGlobalContextUpdated(SchemaContext context);
+
+}