X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=code-generator%2Fbinding-generator-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fsal%2Fbinding%2Fgenerator%2Fimpl%2FLazyGeneratedCodecRegistry.java;h=f70b168e299b0dead41c27b5b30b61f68d66e214;hb=f4a1cd91e68daeeaeed50984e9ab8fb45ba0223b;hp=65b3f668e256514fda61c968180ab21b02fe8289;hpb=17ed8d9ea2d2094ad4d2be8f292edc492ed9d4f2;p=yangtools.git diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/LazyGeneratedCodecRegistry.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/LazyGeneratedCodecRegistry.java index 65b3f668e2..f70b168e29 100644 --- a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/LazyGeneratedCodecRegistry.java +++ b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/LazyGeneratedCodecRegistry.java @@ -7,6 +7,14 @@ */ package org.opendaylight.yangtools.sal.binding.generator.impl; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Iterables; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multimaps; import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.util.AbstractMap.SimpleEntry; @@ -23,7 +31,6 @@ import java.util.Set; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; - import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl; import org.opendaylight.yangtools.binding.generator.util.Types; import org.opendaylight.yangtools.concepts.Delegator; @@ -37,6 +44,7 @@ import org.opendaylight.yangtools.yang.binding.Augmentable; import org.opendaylight.yangtools.yang.binding.Augmentation; import org.opendaylight.yangtools.yang.binding.BaseIdentity; import org.opendaylight.yangtools.yang.binding.BindingCodec; +import org.opendaylight.yangtools.yang.binding.BindingMapping; import org.opendaylight.yangtools.yang.binding.DataContainer; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.Identifier; @@ -67,19 +75,12 @@ import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaContextListener; +import org.opendaylight.yangtools.yang.model.api.SchemaNode; import org.opendaylight.yangtools.yang.model.api.SchemaPath; +import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Iterables; -import com.google.common.collect.Multimap; -import com.google.common.collect.Multimaps; - class LazyGeneratedCodecRegistry implements // CodecRegistry, // SchemaContextListener, // @@ -193,7 +194,12 @@ class LazyGeneratedCodecRegistry implements // @Override public Class getClassForPath(final List names) { - final DataSchemaNode node = getSchemaNode(names); + DataSchemaNode node = getSchemaNode(names); + Preconditions.checkArgument(node != null, "Path %s points to invalid schema location",names); + SchemaNode originalDefinition = SchemaNodeUtils.getRootOriginalIfPossible(node); + if(originalDefinition instanceof DataSchemaNode) { + node =(DataSchemaNode) originalDefinition; + } final SchemaPath path = node.getPath(); final Type t = pathToType.get(path); @@ -207,9 +213,14 @@ class LazyGeneratedCodecRegistry implements // @SuppressWarnings("rawtypes") final WeakReference weakRef = typeToClass.get(type); - Preconditions.checkState(weakRef != null, "Could not find loaded class for path: %s and type: %s", path, - type.getFullyQualifiedName()); - return weakRef.get(); + if(weakRef != null) { + return weakRef.get(); + } + try { + return classLoadingStrategy.loadClass(type); + } catch (ClassNotFoundException e) { + throw new IllegalStateException(String.format("Could not find loaded class for path: %s and type: %s", path,type.getFullyQualifiedName())); + } } @Override @@ -253,7 +264,7 @@ class LazyGeneratedCodecRegistry implements // WeakReference weakRef = new WeakReference<>(cls); typeToClass.put(typeRef, weakRef); if (Augmentation.class.isAssignableFrom(cls)) { - + // Intentionally NOOP } else if (DataObject.class.isAssignableFrom(cls)) { getCodecForDataObject((Class) cls); } @@ -1019,20 +1030,51 @@ class LazyGeneratedCodecRegistry implements // } } + /** + * + * Dispatch codec for augmented object, which processes augmentations + *

+ * This codec is used from DataObject codec generated using + * {@link TransformerGenerator#transformerFor(Class)} and is wired + * during {@link LazyGeneratedCodecRegistry#onDataContainerCodecCreated(Class, Class)}. + *

+ * Instance of this codec is associated with class of Binding DTO which + * represents target for augmentations. + * + */ @SuppressWarnings({ "rawtypes", "unchecked" }) static class AugmentableDispatchCodec extends LocationAwareDispatchCodec { private final Class augmentableType; + /** + * Construct augmetable dispatch codec. + * + * @param type Class representing augmentation target + * @param registry Registry with which this codec is associated. + */ public AugmentableDispatchCodec(final Class type, final LazyGeneratedCodecRegistry registry) { super(registry); Preconditions.checkArgument(Augmentable.class.isAssignableFrom(type)); augmentableType = type; } + + + /** + * Serializes object to list of values which needs to be injected + * into resulting DOM Node. Injection of data to parent DOM Node + * is handled by caller (in this case generated codec). + * + * TODO: Deprecate use of augmentation codec without instance + * instance identifier + * + * @return list of nodes, which needs to be added to parent node. + * + */ @Override - // TODO deprecate use without iid public Object serialize(final Object input) { + Preconditions.checkArgument(augmentableType.isInstance(input), "Object %s is not instance of %s ",input,augmentableType); if (input instanceof Augmentable) { Map augmentations = getAugmentations(input); return serializeImpl(augmentations); @@ -1040,6 +1082,15 @@ class LazyGeneratedCodecRegistry implements // return null; } + /** + * + * Extracts augmentation from Binding DTO field using reflection + * + * @param input Instance of DataObject which is augmentable and + * may contain augmentation + * @return Map of augmentations if read was successful, otherwise + * empty map. + */ private Map getAugmentations(final Object input) { Field augmentationField; try { @@ -1053,6 +1104,14 @@ class LazyGeneratedCodecRegistry implements // return Collections.emptyMap(); } + /** + * + * Serialization of augmentations, returns list of composite nodes, + * which needs to be injected to parent node. + * + * @param input Map of classes to augmentations + * @return List of nodes, which should be added to parent node. + */ @SuppressWarnings("deprecation") private List serializeImpl(final Map input) { List ret = new ArrayList<>(); @@ -1064,6 +1123,26 @@ class LazyGeneratedCodecRegistry implements // return ret; } + /** + * + * Deserialization of augmentation which is location aware. + * + * Note: In case of composite nodes as an input, each codec + * is invoked since there is no augmentation identifier + * and we need to look for concrete classes. + * FIXME: Maybe faster variation will be by extending + * {@link AugmentationCodecWrapper} to look for particular QNames, + * which will filter incoming set of codecs. + * + * + * @param input Input representation of data + * @param path Wildcarded instance identifier representing location of augmentation parent + * in conceptual schema tree + * @param codecs Set of codecs which are applicable for supplied path, + * selected by caller to be used by deserialization + * + * + */ @Override public Map deserializeImpl(final CompositeNode input, final InstanceIdentifier path, final Iterable codecs) { @@ -1082,6 +1161,17 @@ class LazyGeneratedCodecRegistry implements // return ret; } + /** + * + * Tries to load implementation of concrete augmentation codec for supplied type + * + * Loading of codec may fail, because of supplied type may not be visible + * by classloaders known by registry. If class was not found returns {@link Optional#absent()}. + * + * @param potential Augmentation class identifier for which codecs should be loaded. + * @return Optional with codec for supplied type + * + */ protected Optional tryToLoadImplementation(final Type potential) { try { Class> clazz = (Class>) getRegistry().classLoadingStrategy @@ -1292,9 +1382,14 @@ class LazyGeneratedCodecRegistry implements // @Override public Class deserialize(final QName input) { + if(input == null) { + return null; + } Type type = qnamesToIdentityMap.get(input); if (type == null) { - return null; + String packageName = BindingMapping.getRootPackageName(input); + String className = BindingMapping.getClassName(input); + type = new ReferencedTypeImpl(packageName, className); } ReferencedTypeImpl typeref = new ReferencedTypeImpl(type.getPackageName(), type.getName()); WeakReference softref = typeToClass.get(typeref); @@ -1319,7 +1414,7 @@ class LazyGeneratedCodecRegistry implements // public Object deserialize(final Object input, final InstanceIdentifier bindingIdentifier) { Type type = qnamesToIdentityMap.get(input); if (type == null) { - return null; + throw new IllegalArgumentException( "Invalid for \"" + input + "\"." ); } ReferencedTypeImpl typeref = new ReferencedTypeImpl(type.getPackageName(), type.getName()); WeakReference softref = typeToClass.get(typeref); @@ -1348,8 +1443,7 @@ class LazyGeneratedCodecRegistry implements // if (qname != null) { return qname; } - ConcreteType typeref = Types.typeForClass(input); - qname = typeToQname.get(typeref); + qname = BindingReflections.findQName(input); if (qname != null) { identityQNames.put(input, qname); }