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=e62f28e6469f2ad1f9a2af9e319b7ca92650ec4a;hb=85c0405ed187f2d00d47c12c20f3c5ab8029cd2f;hp=1fb88990bf5e60fc3f4e8fce067d554418900b9b;hpb=529b11b4a77d377f94ff595208b32836fd31b720;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 1fb88990bf..e62f28e646 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 @@ -9,7 +9,6 @@ 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.ArrayList; import java.util.Collection; import java.util.Collections; @@ -22,7 +21,6 @@ import java.util.Map.Entry; import java.util.Objects; import java.util.Set; import java.util.WeakHashMap; -import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -30,7 +28,8 @@ 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.generator.util.ClassLoaderUtils; +import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy; +import org.opendaylight.yangtools.sal.binding.generator.util.CodeGenerationException; 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; @@ -42,6 +41,7 @@ import org.opendaylight.yangtools.yang.binding.BindingCodec; import org.opendaylight.yangtools.yang.binding.DataContainer; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.Identifier; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.util.BindingReflections; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.CompositeNode; @@ -68,40 +68,40 @@ 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.SchemaContextUtil; 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.Multimap; +import com.google.common.collect.Multimaps; -public class LazyGeneratedCodecRegistry implements // +class LazyGeneratedCodecRegistry implements // CodecRegistry, // SchemaContextListener, // 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; + private static final Logger LOG = LoggerFactory.getLogger(LazyGeneratedCodecRegistry.class); + private static final LateMixinCodec NOT_READY_CODEC = new LateMixinCodec(); // Concrete class to codecs private static final Map, DataContainerCodec> containerCodecs = Collections .synchronizedMap(new WeakHashMap, DataContainerCodec>()); private static final Map, IdentifierCodec> identifierCodecs = Collections .synchronizedMap(new WeakHashMap, IdentifierCodec>()); - private static final Map, ChoiceCodecImpl> choiceCodecs = Collections - .synchronizedMap(new WeakHashMap, ChoiceCodecImpl>()); + private static final Map, PublicChoiceCodecImpl> choiceCodecs = Collections + .synchronizedMap(new WeakHashMap, PublicChoiceCodecImpl>()); private static final Map, ChoiceCaseCodecImpl> caseCodecs = Collections .synchronizedMap(new WeakHashMap, ChoiceCaseCodecImpl>()); - private static final Map, AugmentableCompositeCodec> augmentableCodecs = Collections - .synchronizedMap(new WeakHashMap, AugmentableCompositeCodec>()); - private static final Map, AugmentationCodec> augmentationCodecs = Collections - .synchronizedMap(new WeakHashMap, AugmentationCodec>()); + private static final Map, AugmentableDispatchCodec> augmentableCodecs = Collections + .synchronizedMap(new WeakHashMap, AugmentableDispatchCodec>()); + private static final Map, AugmentationCodecWrapper> augmentationCodecs = Collections + .synchronizedMap(new WeakHashMap, AugmentationCodecWrapper>()); private static final Map, QName> identityQNames = Collections .synchronizedMap(new WeakHashMap, QName>()); private static final Map qnamesToIdentityMap = new ConcurrentHashMap<>(); @@ -112,138 +112,123 @@ public class LazyGeneratedCodecRegistry implements // @SuppressWarnings("rawtypes") private static final ConcurrentMap typeToCaseCodecs = new ConcurrentHashMap<>(); - private final CaseClassMapFacade classToCaseRawCodec = new CaseClassMapFacade(); - - private static final Map pathToType = new ConcurrentHashMap<>(); + private static final Map pathToType = new ConcurrentHashMap<>(); private static final Map, Type> pathToInstantiatedType = new ConcurrentHashMap<>(); private static final Map typeToQname = new ConcurrentHashMap<>(); - private static final Map augmentToType = new ConcurrentHashMap<>(); + private static final BiMap typeToAugment = HashBiMap + .create(new ConcurrentHashMap()); + private static final Multimap augmentableToAugmentations = Multimaps.synchronizedMultimap(HashMultimap + . create()); + private static final Multimap choiceToCases = Multimaps.synchronizedMultimap(HashMultimap + . create()); + + private final InstanceIdentifierCodec instanceIdentifierCodec = new InstanceIdentifierCodecImpl(this); + private final CaseClassMapFacade classToCaseRawCodec = new CaseClassMapFacade(); + private final IdentityCompositeCodec identityRefCodec = new IdentityCompositeCodec(); + private final ClassLoadingStrategy classLoadingStrategy; + private final AbstractTransformerGenerator generator; private final SchemaLock lock; + // FIXME: how is this protected? private SchemaContext currentSchema; - private final GeneratedClassLoadingStrategy classLoadingStrategy; - - LazyGeneratedCodecRegistry(SchemaLock lock, GeneratedClassLoadingStrategy identityClassLoadingStrategy) { + LazyGeneratedCodecRegistry(final SchemaLock lock, final AbstractTransformerGenerator generator, + final ClassLoadingStrategy classLoadingStrategy) { this.lock = Preconditions.checkNotNull(lock); - this.classLoadingStrategy = identityClassLoadingStrategy; + this.classLoadingStrategy = Preconditions.checkNotNull(classLoadingStrategy); + this.generator = Preconditions.checkNotNull(generator); } public SchemaLock getLock() { return lock; } - public TransformerGenerator getGenerator() { - return generator; - } - - public void setGenerator(TransformerGenerator generator) { - this.generator = generator; - } - @Override public InstanceIdentifierCodec getInstanceIdentifierCodec() { return instanceIdentifierCodec; } + @SuppressWarnings("unchecked") @Override - public > AugmentationCodec getCodecForAugmentation(Class object) { - AugmentationCodec codec = null; + public > AugmentationCodecWrapper getCodecForAugmentation(final Class augClass) { + AugmentationCodecWrapper codec = null; @SuppressWarnings("rawtypes") - AugmentationCodec potentialCodec = augmentationCodecs.get(object); + AugmentationCodecWrapper potentialCodec = augmentationCodecs.get(augClass); if (potentialCodec != null) { codec = potentialCodec; - } else - try { - lock.waitForSchema(object); - Class, Object>> augmentRawCodec = generator - .augmentationTransformerFor(object); - BindingCodec, Object> rawCodec = augmentRawCodec.newInstance(); - codec = new AugmentationCodecWrapper(rawCodec); - augmentationCodecs.put(object, codec); - } catch (InstantiationException e) { - LOG.error("Can not instantiate raw augmentation codec {}", object.getSimpleName(), e); - } catch (IllegalAccessException e) { - LOG.debug( - "Run-time consistency issue: constructor {} is not available. This indicates either a code generation bug or a misconfiguration of JVM.", - object.getSimpleName(), e); - } - Class> objectSupertype = getAugmentableArgumentFrom(object); - if (objectSupertype != null) { - getAugmentableCodec(objectSupertype).addAugmentationCodec(object, codec); } else { - LOG.warn("Could not find augmentation target for augmentation {}", object); + lock.waitForSchema(augClass); + Class, Object>> augmentRawCodec = generator + .augmentationTransformerFor(augClass); + + BindingCodec, Object> rawCodec = newInstanceOf(augmentRawCodec); + codec = new AugmentationCodecWrapper(rawCodec, augClass); + augmentationCodecs.put(augClass, codec); + } + + final Class> objectSupertype; + try { + objectSupertype = BindingReflections.findAugmentationTarget(augClass); + } catch (Exception e) { + LOG.warn("Failed to find target for augmentation {}, ignoring it", augClass, e); + return codec; + } + + if (objectSupertype == null) { + LOG.warn("Augmentation target for {} not found, ignoring it", augClass); + return codec; } + + getAugmentableCodec(objectSupertype).addImplementation(codec); return codec; } + @SuppressWarnings("unchecked") @Override - public QName getQNameForAugmentation(Class cls) { + public QName getQNameForAugmentation(final Class cls) { Preconditions.checkArgument(Augmentation.class.isAssignableFrom(cls)); - return getCodecForAugmentation((Class) cls).getAugmentationQName(); - } - - private static Class> getAugmentableArgumentFrom( - final Class> augmentation) { - try { - Class> ret = ClassLoaderUtils.withClassLoader(augmentation.getClassLoader(), - new Callable>>() { - @Override - @SuppressWarnings("unchecked") - public Class> 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>) augmentationGeneric - .getActualTypeArguments()[0]; - } - } - return null; - } - }); - return ret; - } catch (Exception e) { - LOG.debug("Could not find augmentable for {} using {}", augmentation, augmentation.getClassLoader(), e); - return null; - } + return getCodecForAugmentation((Class>) cls).getAugmentationQName(); } @Override - public Class getClassForPath(List names) { - DataSchemaNode node = getSchemaNode(names); - SchemaPath path = node.getPath(); - Type type = pathToType.get(path); - if (type != null) { - type = new ReferencedTypeImpl(type.getPackageName(), type.getName()); + public Class getClassForPath(final List names) { + final DataSchemaNode node = getSchemaNode(names); + final SchemaPath path = node.getPath(); + final Type t = pathToType.get(path); + + final Type type; + if (t != null) { + type = new ReferencedTypeImpl(t.getPackageName(), t.getName()); } else { type = pathToInstantiatedType.get(names); + Preconditions.checkState(type != null, "Failed to lookup instantiated type for path %s", path); } + @SuppressWarnings("rawtypes") - WeakReference weakRef = typeToClass.get(type); - if (weakRef == null) { - LOG.error("Could not find loaded class for path: {} and type: {}", path, type.getFullyQualifiedName()); - } + 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(); } @Override - public void putPathToClass(List names, Class cls) { - Type reference = Types.typeForClass(cls); + public void putPathToClass(final List names, final Class cls) { + final Type reference = Types.typeForClass(cls); pathToInstantiatedType.put(names, reference); + LOG.trace("Path {} attached to class {} reference {}", names, cls, reference); bindingClassEncountered(cls); } @Override - public IdentifierCodec getKeyCodecForPath(List names) { + public IdentifierCodec getKeyCodecForPath(final List names) { @SuppressWarnings("unchecked") Class> cls = (Class>) getClassForPath(names); return getIdentifierCodecForIdentifiable(cls); } @Override - public DataContainerCodec getCodecForDataObject(Class type) { + public DataContainerCodec getCodecForDataObject(final Class type) { @SuppressWarnings("unchecked") DataContainerCodec ret = (DataContainerCodec) containerCodecs.get(type); if (ret != null) { @@ -258,7 +243,7 @@ public class LazyGeneratedCodecRegistry implements // @Override @SuppressWarnings("rawtypes") - public void bindingClassEncountered(Class cls) { + public void bindingClassEncountered(final Class cls) { ConcreteType typeRef = Types.typeForClass(cls); if (typeToClass.containsKey(typeRef)) { @@ -276,7 +261,7 @@ public class LazyGeneratedCodecRegistry implements // } @Override - public void onClassProcessed(Class cls) { + public void onClassProcessed(final Class cls) { ConcreteType typeRef = Types.typeForClass(cls); if (typeToClass.containsKey(typeRef)) { return; @@ -287,10 +272,12 @@ public class LazyGeneratedCodecRegistry implements // typeToClass.put(typeRef, weakRef); } - private DataSchemaNode getSchemaNode(List path) { + private DataSchemaNode getSchemaNode(final List path) { QName firstNode = path.get(0); DataNodeContainer previous = currentSchema.findModuleByNamespaceAndRevision(firstNode.getNamespace(), firstNode.getRevision()); + Preconditions.checkArgument(previous != null, "Failed to find module %s for path %s", firstNode, path); + Iterator iterator = path.iterator(); while (iterator.hasNext()) { QName arg = iterator.next(); @@ -308,7 +295,7 @@ public class LazyGeneratedCodecRegistry implements // return (DataSchemaNode) previous; } - private DataSchemaNode searchInChoices(DataNodeContainer node, QName arg) { + private DataSchemaNode searchInChoices(final DataNodeContainer node, final QName arg) { Set children = node.getChildNodes(); for (DataSchemaNode child : children) { if (child instanceof ChoiceNode) { @@ -322,7 +309,7 @@ public class LazyGeneratedCodecRegistry implements // return null; } - private DataSchemaNode searchInCases(ChoiceNode choiceNode, QName arg) { + private DataSchemaNode searchInCases(final ChoiceNode choiceNode, final QName arg) { Set cases = choiceNode.getCases(); for (ChoiceCaseNode caseNode : cases) { DataSchemaNode node = caseNode.getDataChildByName(arg); @@ -333,20 +320,24 @@ public class LazyGeneratedCodecRegistry implements // return null; } - private T newInstanceOf(Class newType) { + private static T newInstanceOf(final Class cls) { try { @SuppressWarnings("unchecked") - T ret = (T) newType.newInstance(); + T ret = (T) cls.newInstance(); return ret; } catch (InstantiationException e) { - throw new IllegalStateException(e); + LOG.error("Failed to instantiate codec {}", cls.getSimpleName(), e); + throw new IllegalStateException(String.format("Failed to instantiate codec %s", cls), e); } catch (IllegalAccessException e) { - throw new IllegalStateException(e); + LOG.debug( + "Run-time consistency issue: constructor for {} is not available. This indicates either a code generation bug or a misconfiguration of JVM.", + cls.getSimpleName(), e); + throw new IllegalStateException(String.format("Cannot access contructor of %s", cls), e); } } @Override - public > IdentifierCodec getIdentifierCodecForIdentifiable(Class type) { + public > IdentifierCodec getIdentifierCodecForIdentifiable(final Class type) { IdentifierCodec obj = identifierCodecs.get(type); if (obj != null) { return obj; @@ -365,20 +356,21 @@ public class LazyGeneratedCodecRegistry implements // return identityRefCodec; } + @SuppressWarnings("unchecked") @Override - public IdentityCodec getCodecForIdentity(Class codec) { + public IdentityCodec getCodecForIdentity(final Class codec) { bindingClassEncountered(codec); return identityRefCodec; } @Override - public void onCodecCreated(Class cls) { + public void onCodecCreated(final Class cls) { CodecMapping.setIdentifierCodec(cls, instanceIdentifierCodec); CodecMapping.setIdentityRefCodec(cls, identityRefCodec); } @Override - public > IdentifierCodec getCodecForIdentifier(Class object) { + public > IdentifierCodec getCodecForIdentifier(final Class object) { @SuppressWarnings("unchecked") IdentifierCodec obj = (IdentifierCodec) identifierCodecs.get(object); if (obj != null) { @@ -394,7 +386,7 @@ public class LazyGeneratedCodecRegistry implements // } @SuppressWarnings("rawtypes") - public ChoiceCaseCodecImpl getCaseCodecFor(Class caseClass) { + public ChoiceCaseCodecImpl getCaseCodecFor(final Class caseClass) { ChoiceCaseCodecImpl potential = caseCodecs.get(caseClass); if (potential != null) { return potential; @@ -406,13 +398,12 @@ public class LazyGeneratedCodecRegistry implements // caseClass.getName()); Preconditions.checkState(caseCodec.getSchema() != null, "Case schema is not available for %s", caseClass.getName()); - @SuppressWarnings("unchecked") Class newCodec = generator.caseCodecFor(caseClass, caseCodec.getSchema()); BindingCodec newInstance = newInstanceOf(newCodec); caseCodec.setDelegate(newInstance); caseCodecs.put(caseClass, caseCodec); - for (Entry, ChoiceCodecImpl> choice : choiceCodecs.entrySet()) { + for (Entry, PublicChoiceCodecImpl> choice : choiceCodecs.entrySet()) { if (choice.getKey().isAssignableFrom(caseClass)) { choice.getValue().cases.put(caseClass, caseCodec); } @@ -420,19 +411,36 @@ public class LazyGeneratedCodecRegistry implements // return caseCodec; } - public void onModuleContextAdded(SchemaContext schemaContext, Module module, ModuleContext context) { + public void onModuleContextAdded(final SchemaContext schemaContext, final Module module, final ModuleContext context) { pathToType.putAll(context.getChildNodes()); - augmentToType.putAll(context.getTypeToAugmentation().inverse()); + + BiMap bimap = context.getTypeToAugmentation(); + for (Map.Entry entry : bimap.entrySet()) { + Type key = entry.getKey(); + AugmentationSchema value = entry.getValue(); + Set augmentedNodes = value.getChildNodes(); + if (augmentedNodes != null && !(augmentedNodes.isEmpty())) { + typeToAugment.put(key, value); + } + } + qnamesToIdentityMap.putAll(context.getIdentities()); for (Entry identity : context.getIdentities().entrySet()) { typeToQname.put( new ReferencedTypeImpl(identity.getValue().getPackageName(), identity.getValue().getName()), identity.getKey()); } + + synchronized (augmentableToAugmentations) { + augmentableToAugmentations.putAll(context.getAugmentableToAugmentations()); + } + synchronized (choiceToCases) { + choiceToCases.putAll(context.getChoiceToCases()); + } captureCases(context.getCases(), schemaContext); } - private void captureCases(Map cases, SchemaContext module) { + private void captureCases(final Map cases, final SchemaContext module) { for (Entry caseNode : cases.entrySet()) { ReferencedTypeImpl typeref = new ReferencedTypeImpl(caseNode.getValue().getPackageName(), caseNode .getValue().getName()); @@ -456,18 +464,18 @@ public class LazyGeneratedCodecRegistry implements // } @Override - public void onGlobalContextUpdated(SchemaContext context) { + public void onGlobalContextUpdated(final SchemaContext context) { currentSchema = context; } @SuppressWarnings({ "unchecked", "rawtypes" }) @Override - public void onChoiceCodecCreated(Class choiceClass, - Class, Object>> choiceCodec, ChoiceNode schema) { + public void onChoiceCodecCreated(final Class choiceClass, + final Class, Object>> choiceCodec, final ChoiceNode schema) { ChoiceCodec oldCodec = choiceCodecs.get(choiceClass); Preconditions.checkState(oldCodec == null); BindingCodec, Object> delegate = newInstanceOf(choiceCodec); - ChoiceCodecImpl newCodec = new ChoiceCodecImpl(delegate); + PublicChoiceCodecImpl newCodec = new PublicChoiceCodecImpl(delegate); choiceCodecs.put(choiceClass, newCodec); CodecMapping.setClassToCaseMap(choiceCodec, classToCaseRawCodec); CodecMapping.setCompositeNodeToCaseMap(choiceCodec, newCodec.getCompositeToCase()); @@ -476,12 +484,22 @@ public class LazyGeneratedCodecRegistry implements // } - private void tryToCreateCasesCodecs(ChoiceNode schema) { - for (ChoiceCaseNode caseNode : schema.getCases()) { + @Deprecated + private void tryToCreateCasesCodecs(final ChoiceNode schema) { + for (ChoiceCaseNode choiceCase : schema.getCases()) { + ChoiceCaseNode caseNode = choiceCase; + if (caseNode.isAddedByUses()) { + DataSchemaNode origCaseNode = SchemaContextUtil.findOriginal(caseNode, currentSchema); + if (origCaseNode instanceof ChoiceCaseNode) { + caseNode = (ChoiceCaseNode) origCaseNode; + } + } SchemaPath path = caseNode.getPath(); - GeneratedTypeBuilder type; + + Type type; if (path != null && (type = pathToType.get(path)) != null) { ReferencedTypeImpl typeref = new ReferencedTypeImpl(type.getPackageName(), type.getName()); + @SuppressWarnings("rawtypes") ChoiceCaseCodecImpl partialCodec = typeToCaseCodecs.get(typeref); if (partialCodec.getSchema() == null) { partialCodec.setSchema(caseNode); @@ -498,73 +516,34 @@ public class LazyGeneratedCodecRegistry implements // } @Override - public void onValueCodecCreated(Class valueClass, Class valueCodec) { + public void onValueCodecCreated(final Class valueClass, final Class valueCodec) { } @Override - public void onCaseCodecCreated(Class choiceClass, - Class, Object>> choiceCodec) { + public void onCaseCodecCreated(final Class choiceClass, + final Class, Object>> choiceCodec) { } @Override - public void onDataContainerCodecCreated(Class dataClass, Class> dataCodec) { + public void onDataContainerCodecCreated(final Class dataClass, + final Class> dataCodec) { if (Augmentable.class.isAssignableFrom(dataClass)) { - AugmentableCompositeCodec augmentableCodec = getAugmentableCodec(dataClass); + AugmentableDispatchCodec augmentableCodec = getAugmentableCodec(dataClass); CodecMapping.setAugmentationCodec(dataCodec, augmentableCodec); } - } - public AugmentableCompositeCodec getAugmentableCodec(Class dataClass) { - AugmentableCompositeCodec ret = augmentableCodecs.get(dataClass); + public synchronized AugmentableDispatchCodec getAugmentableCodec(final Class dataClass) { + AugmentableDispatchCodec ret = augmentableCodecs.get(dataClass); if (ret != null) { return ret; } - ret = new AugmentableCompositeCodec(dataClass); + ret = new AugmentableDispatchCodec(dataClass); augmentableCodecs.put(dataClass, ret); - - Map typeToSchemaNode = generator.getTypeToSchemaNode(); - Type refType = new ReferencedTypeImpl(dataClass.getPackage().getName(), dataClass.getSimpleName()); - SchemaNode node = typeToSchemaNode.get(refType); - tryToLoadAugmentations(node); - + ret.tryToLoadImplementations(); return ret; } - private void tryToLoadAugmentations(SchemaNode schemaNode) { - if (schemaNode instanceof AugmentationTarget) { - AugmentationTarget augmentationTarget = (AugmentationTarget) schemaNode; - Set augments = augmentationTarget.getAvailableAugmentations(); - Set augmentTypes = new HashSet<>(); - if (augments != null) { - for (AugmentationSchema augment : augments) { - Type augmentType = augmentToType.get(augment); - if (augmentType == null) { - LOG.warn("Failed to find type for augmentation of " + augment); - } else { - augmentTypes.add(augmentType); - } - } - for (Type augmentType : augmentTypes) { - Class> clazz = null; - try { - clazz = (Class>) classLoadingStrategy.loadClass(augmentType); - } catch (ClassNotFoundException e) { - LOG.warn("Failed to find class for augmentation of " + augmentType); - } - getCodecForAugmentation(clazz); - } - } - } - - if (schemaNode instanceof DataNodeContainer) { - Set childNodes = ((DataNodeContainer) schemaNode).getChildNodes(); - for (DataSchemaNode child : childNodes) { - tryToLoadAugmentations(child); - } - } - } - private static abstract class IntermediateCodec implements // DomCodec, Delegator, Object>> { @@ -575,27 +554,28 @@ public class LazyGeneratedCodecRegistry implements // return delegate; } - public IntermediateCodec(BindingCodec, Object> delegate) { + public IntermediateCodec(final BindingCodec, Object> delegate) { this.delegate = delegate; } @Override - public Node serialize(ValueWithQName input) { + public Node serialize(final ValueWithQName input) { Map intermediateOutput = delegate.serialize(input); return IntermediateMapping.toNode(intermediateOutput); } + } private static class IdentifierCodecImpl> // extends IntermediateCodec // implements IdentifierCodec { - public IdentifierCodecImpl(BindingCodec, Object> delegate) { + public IdentifierCodecImpl(final BindingCodec, Object> delegate) { super(delegate); } @Override - public ValueWithQName deserialize(Node input) { + public ValueWithQName deserialize(final Node input) { QName qname = input.getNodeType(); @SuppressWarnings("unchecked") T value = (T) getDelegate().deserialize((Map) input); @@ -603,7 +583,15 @@ public class LazyGeneratedCodecRegistry implements // } @Override - public CompositeNode serialize(ValueWithQName input) { + public ValueWithQName deserialize(final Node input, final InstanceIdentifier bindingIdentifier) { + QName qname = input.getNodeType(); + @SuppressWarnings("unchecked") + T value = (T) getDelegate().deserialize((Map) input, bindingIdentifier); + return new ValueWithQName(qname, value); + } + + @Override + public CompositeNode serialize(final ValueWithQName input) { return (CompositeNode) super.serialize(input); } } @@ -612,12 +600,12 @@ public class LazyGeneratedCodecRegistry implements // extends IntermediateCodec // implements DataContainerCodec { - public DataContainerCodecImpl(BindingCodec, Object> delegate) { + public DataContainerCodecImpl(final BindingCodec, Object> delegate) { super(delegate); } @Override - public ValueWithQName deserialize(Node input) { + public ValueWithQName deserialize(final Node input) { if (input == null) { return null; } @@ -628,22 +616,139 @@ public class LazyGeneratedCodecRegistry implements // } @Override - public CompositeNode serialize(ValueWithQName input) { + public ValueWithQName deserialize(final Node input, final InstanceIdentifier bindingIdentifier) { + if (input == null) { + return null; + } + QName qname = input.getNodeType(); + @SuppressWarnings("unchecked") + T value = (T) getDelegate().deserialize((Map) input, bindingIdentifier); + return new ValueWithQName(qname, value); + } + + @Override + public CompositeNode serialize(final ValueWithQName input) { return (CompositeNode) super.serialize(input); } } + private interface LocationAwareBindingCodec extends BindingCodec { + + boolean isApplicable(InstanceIdentifier location); + + public Class getDataType(); + + } + + @SuppressWarnings("rawtypes") + private abstract class LocationAwareDispatchCodec implements BindingCodec { + + private final Map implementations = Collections.synchronizedMap(new WeakHashMap()); + private final Set> adaptedForPaths = new HashSet<>(); + + protected Map getImplementations() { + return implementations; + } + + protected void addImplementation(final T implementation) { + implementations.put(implementation.getDataType(), implementation); + } + + @Override + public final Object deserialize(final Object input) { + throw new UnsupportedOperationException("Invocation of deserialize without Tree location is unsupported"); + } + + @Override + public Object serialize(final Object input) { + Preconditions.checkArgument(input instanceof DataContainer); + Class inputType = ((DataContainer) input).getImplementedInterface(); + T implementation = implementations.get(inputType); + if (implementation == null) { + implementation = tryToLoadImplementationImpl(inputType); + } + + return null; + } + + private T tryToLoadImplementationImpl(final Class inputType) { + T implementation = tryToLoadImplementation(inputType); + Preconditions.checkArgument(implementation != null, "Data type %s is not supported.", inputType); + addImplementation(implementation); + return implementation; + } + + protected final synchronized void adaptForPath(final InstanceIdentifier path) { + if (adaptedForPaths.contains(path)) { + return; + } + /** + * We search in schema context if the use of this location aware + * codec (augmentable codec, case codec) makes sense on provided + * location (path) + * + */ + Optional contextNode = BindingSchemaContextUtils.findDataNodeContainer(currentSchema, + path); + /** + * If context node is present, this codec makes sense on provided + * location. + * + */ + if (contextNode.isPresent()) { + synchronized (this) { + /** + * + * We adapt (turn on / off) possible implementations of + * child codecs (augmentations, cases) based on this + * location. + * + * + */ + + adaptForPathImpl(path, contextNode.get()); + try { + /** + * We trigger serialization of instance identifier, to + * make sure instance identifier codec is aware of + * combination of this path / augmentation / case + */ + instanceIdentifierCodec.serialize(path); + } catch (Exception e) { + LOG.warn("Exception during preparation of instance identifier codec for path {}.", path, e); + } + adaptedForPaths.add(path); + } + } else { + LOG.debug("Context node (parent node) not found for {}", path); + } + } + + protected abstract T tryToLoadImplementation(Class inputType); + + protected abstract void tryToLoadImplementations(); + + protected abstract void adaptForPathImpl(InstanceIdentifier path, DataNodeContainer ctx); + } + @SuppressWarnings("rawtypes") private static class ChoiceCaseCodecImpl implements ChoiceCaseCodec, // - Delegator { + Delegator, LocationAwareBindingCodec, ValueWithQName> { private boolean augmenting; + private boolean uses; private BindingCodec delegate; private Set validNames; private Set validQNames; private ChoiceCaseNode schema; + private Set> applicableLocations; + + @Override + public boolean isApplicable(final InstanceIdentifier location) { + return applicableLocations.contains(location); + } - public void setSchema(ChoiceCaseNode caseNode) { + public void setSchema(final ChoiceCaseNode caseNode) { this.schema = caseNode; validNames = new HashSet<>(); validQNames = new HashSet<>(); @@ -653,24 +758,31 @@ public class LazyGeneratedCodecRegistry implements // validNames.add(qname.getLocalName()); } augmenting = caseNode.isAugmenting(); + uses = caseNode.isAddedByUses(); + applicableLocations = new HashSet<>(); } public ChoiceCaseCodecImpl() { this.delegate = NOT_READY_CODEC; } - public ChoiceCaseCodecImpl(ChoiceCaseNode caseNode) { + public ChoiceCaseCodecImpl(final ChoiceCaseNode caseNode) { this.delegate = NOT_READY_CODEC; setSchema(caseNode); } @Override - public ValueWithQName deserialize(Node input) { + public ValueWithQName deserialize(final Node input) { throw new UnsupportedOperationException("Direct invocation of this codec is not allowed."); } @Override - public CompositeNode serialize(ValueWithQName input) { + public ValueWithQName deserialize(final Node input, final InstanceIdentifier bindingIdentifier) { + throw new UnsupportedOperationException("Direct invocation of this codec is not allowed."); + } + + @Override + public CompositeNode serialize(final ValueWithQName input) { throw new UnsupportedOperationException("Direct invocation of this codec is not allowed."); } @@ -679,7 +791,7 @@ public class LazyGeneratedCodecRegistry implements // return delegate; } - public void setDelegate(BindingCodec delegate) { + public void setDelegate(final BindingCodec delegate) { this.delegate = delegate; } @@ -688,9 +800,9 @@ public class LazyGeneratedCodecRegistry implements // } @Override - public boolean isAcceptable(Node input) { + public boolean isAcceptable(final Node input) { if (input instanceof CompositeNode) { - if (augmenting) { + if (augmenting && !uses) { return checkAugmenting((CompositeNode) input); } else { return checkLocal((CompositeNode) input); @@ -699,7 +811,8 @@ public class LazyGeneratedCodecRegistry implements // return false; } - private boolean checkLocal(CompositeNode input) { + @SuppressWarnings("deprecation") + private boolean checkLocal(final CompositeNode input) { QName parent = input.getNodeType(); for (Node childNode : input.getChildren()) { QName child = childNode.getNodeType(); @@ -714,7 +827,8 @@ public class LazyGeneratedCodecRegistry implements // return false; } - private boolean checkAugmenting(CompositeNode input) { + @SuppressWarnings("deprecation") + private boolean checkAugmenting(final CompositeNode input) { for (Node child : input.getChildren()) { if (validQNames.contains(child.getNodeType())) { return true; @@ -722,9 +836,16 @@ public class LazyGeneratedCodecRegistry implements // } return false; } + + @Override + public Class getDataType() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Not implemented Yet."); + } } - private static class ChoiceCodecImpl implements ChoiceCodec { + private static class PublicChoiceCodecImpl implements ChoiceCodec, + Delegator, Object>> { private final BindingCodec, Object> delegate; @@ -734,35 +855,71 @@ public class LazyGeneratedCodecRegistry implements // private final CaseCompositeNodeMapFacade CompositeToCase; - public ChoiceCodecImpl(BindingCodec, Object> delegate) { + public PublicChoiceCodecImpl(final BindingCodec, Object> delegate) { this.delegate = delegate; this.CompositeToCase = new CaseCompositeNodeMapFacade(cases); } @Override - public ValueWithQName deserialize(Node input) { + public ValueWithQName deserialize(final Node input) { throw new UnsupportedOperationException("Direct invocation of this codec is not allowed."); } @Override - public Node serialize(ValueWithQName input) { + public ValueWithQName deserialize(final Node input, final InstanceIdentifier bindingIdentifier) { throw new UnsupportedOperationException("Direct invocation of this codec is not allowed."); } - public CaseCompositeNodeMapFacade getCompositeToCase() { - return CompositeToCase; + @Override + public Node serialize(final ValueWithQName input) { + throw new UnsupportedOperationException("Direct invocation of this codec is not allowed."); } - public Map> getCases() { - return cases; + public CaseCompositeNodeMapFacade getCompositeToCase() { + return CompositeToCase; } + @Override public BindingCodec, Object> getDelegate() { return delegate; } } + @SuppressWarnings("unused") + private class DispatchChoiceCodecImpl extends LocationAwareDispatchCodec> { + + @Override + public Object deserialize(final Object input, + @SuppressWarnings("rawtypes") final InstanceIdentifier bindingIdentifier) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Object serialize(final Object input) { + // TODO Auto-generated method stub + return null; + } + + @Override + protected ChoiceCaseCodecImpl tryToLoadImplementation(final Class inputType) { + return getCaseCodecFor(inputType); + } + + @Override + protected void tryToLoadImplementations() { + // TODO Auto-generated method stub + + } + + @Override + protected void adaptForPathImpl(final InstanceIdentifier path, final DataNodeContainer ctx) { + // TODO Auto-generated method stub + + } + } + @SuppressWarnings("rawtypes") private class CaseClassMapFacade extends MapFacadeBase { @@ -772,7 +929,7 @@ public class LazyGeneratedCodecRegistry implements // } @Override - public BindingCodec get(Object key) { + public BindingCodec get(final Object key) { if (key instanceof Class) { Class cls = (Class) key; // bindingClassEncountered(cls); @@ -788,12 +945,12 @@ public class LazyGeneratedCodecRegistry implements // final Map> choiceCases; - public CaseCompositeNodeMapFacade(Map> choiceCases) { + public CaseCompositeNodeMapFacade(final Map> choiceCases) { this.choiceCases = choiceCases; } @Override - public BindingCodec get(Object key) { + public BindingCodec get(final Object key) { if (!(key instanceof CompositeNode)) { return null; } @@ -817,10 +974,10 @@ public class LazyGeneratedCodecRegistry implements // * Key type */ @SuppressWarnings("rawtypes") - private static abstract class MapFacadeBase implements Map> { + private abstract static class MapFacadeBase implements Map> { @Override - public boolean containsKey(Object key) { + public boolean containsKey(final Object key) { return get(key) != null; } @@ -830,12 +987,12 @@ public class LazyGeneratedCodecRegistry implements // } @Override - public boolean equals(Object obj) { + public boolean equals(final Object obj) { return super.equals(obj); } @Override - public BindingCodec remove(Object key) { + public BindingCodec remove(final Object key) { return null; } @@ -854,12 +1011,12 @@ public class LazyGeneratedCodecRegistry implements // } @Override - public BindingCodec, Object> put(T key, BindingCodec value) { + public BindingCodec, Object> put(final T key, final BindingCodec value) { throw notModifiable(); } @Override - public void putAll(Map> m) { + public void putAll(final Map> m) { throw notModifiable(); } @@ -884,35 +1041,32 @@ public class LazyGeneratedCodecRegistry implements // } @Override - public boolean containsValue(Object value) { + public boolean containsValue(final Object value) { return false; } } @SuppressWarnings({ "rawtypes", "unchecked" }) - private class AugmentableCompositeCodec implements BindingCodec { + class AugmentableDispatchCodec extends LocationAwareDispatchCodec { private final Class augmentableType; - Map> localAugmentationCodecs = Collections - .synchronizedMap(new WeakHashMap>()); - - public AugmentableCompositeCodec(Class type) { + public AugmentableDispatchCodec(final Class type) { Preconditions.checkArgument(Augmentable.class.isAssignableFrom(type)); augmentableType = type; } @Override - public Object serialize(Object input) { + // TODO deprecate use without iid + public Object serialize(final Object input) { if (input instanceof Augmentable) { - Map augmentations = getAugmentations(input); return serializeImpl(augmentations); } return null; } - private Map getAugmentations(Object input) { + private Map getAugmentations(final Object input) { Field augmentationField; try { augmentationField = input.getClass().getDeclaredField("augmentation"); @@ -925,7 +1079,8 @@ public class LazyGeneratedCodecRegistry implements // return Collections.emptyMap(); } - private List serializeImpl(Map input) { + @SuppressWarnings("deprecation") + private List serializeImpl(final Map input) { List ret = new ArrayList<>(); for (Entry entry : input.entrySet()) { AugmentationCodec codec = getCodecForAugmentation(entry.getKey()); @@ -935,28 +1090,137 @@ public class LazyGeneratedCodecRegistry implements // return ret; } - public synchronized > void addAugmentationCodec(Class augmentationClass, - AugmentationCodec value) { - localAugmentationCodecs.put(augmentationClass, value); - } - @Override - public Map deserialize(Object input) { + public Map deserialize(final Object input, final InstanceIdentifier path) { + adaptForPath(path); Map ret = new HashMap<>(); + if (input instanceof CompositeNode) { - List>> codecs = new ArrayList<>(localAugmentationCodecs.entrySet()); - for (Entry> codec : codecs) { - ValueWithQName value = codec.getValue().deserialize((CompositeNode) input); - if (value != null && value.getValue() != null) { - ret.put(codec.getKey(), (Augmentation) value.getValue()); + List> codecs = new ArrayList<>(getImplementations().entrySet()); + for (Entry codec : codecs) { + AugmentationCodec ac = codec.getValue(); + if (ac.isAcceptable(path)) { + // We add Augmentation Identifier to path, in order to + // correctly identify children. + InstanceIdentifier augmentPath = path.builder().augmentation(codec.getKey()).build(); + ValueWithQName value = codec.getValue().deserialize((CompositeNode) input, augmentPath); + if (value != null && value.getValue() != null) { + ret.put(codec.getKey(), (Augmentation) value.getValue()); + } } } } return ret; } - public Class getAugmentableType() { - return augmentableType; + protected Optional tryToLoadImplementation(final Type potential) { + try { + Class> clazz = (Class>) classLoadingStrategy + .loadClass(potential); + return Optional.of(tryToLoadImplementation(clazz)); + } catch (ClassNotFoundException e) { + LOG.warn("Failed to find class for augmentation of {}", potential, e); + } + return Optional.absent(); + } + + @Override + protected AugmentationCodecWrapper tryToLoadImplementation(final Class inputType) { + AugmentationCodecWrapper> potentialImpl = getCodecForAugmentation(inputType); + addImplementation(potentialImpl); + return potentialImpl; + } + + @Override + protected void tryToLoadImplementations() { + Type type = referencedType(augmentableType); + Collection potentialAugmentations; + synchronized (augmentableToAugmentations) { + potentialAugmentations = new ArrayList(augmentableToAugmentations.get(type)); + } + for (Type potential : potentialAugmentations) { + try { + tryToLoadImplementation(potential); + } catch (CodeGenerationException e) { + LOG.warn("Failed to proactively generate augment code for {}", type, e); + } + } + } + + @Override + protected void adaptForPathImpl(final InstanceIdentifier augTarget, final DataNodeContainer ctxNode) { + if (ctxNode instanceof AugmentationTarget) { + Set availableAugmentations = ((AugmentationTarget) ctxNode) + .getAvailableAugmentations(); + if (!availableAugmentations.isEmpty()) { + updateAugmentationMapping(augTarget, availableAugmentations); + } + } + } + + /** + * + * Adapts augmentation codec for specific provider location (target) + * + * Since augmentation are not forward-referencing and may be discovered + * during runtime, we need to adapt {@link AugmentableDispatchCodec}, + * {@link AugmentationCodecWrapper} and {@link InstanceIdentifierCodec} + * for this newly discovered location where augmentation may be used. + * + * Adaptation consists of: + *
    + *
  1. scan of available (valid) augmentations for + * current location + *
  2. lookup for Java classes derived from this augmentations + *
  3. generation of missing codecs + *
  4. updating Augmentation codecs to work with new location + *
  5. updating Instance Identifier to work with new location + * + */ + private void updateAugmentationMapping(final InstanceIdentifier augTarget, + final Set availableAugmentations) { + for (AugmentationSchema aug : availableAugmentations) { + + Type potentialType = getTypeForAugmentation(aug); + if (potentialType != null) { + Optional potentialImpl = tryToLoadImplementation(potentialType); + if (potentialImpl.isPresent()) { + potentialImpl.get().addApplicableFor(augTarget, aug); + Class augType = potentialImpl.get().getDataType(); + InstanceIdentifier augPath = augTarget.augmentation(augType); + try { + + org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = getInstanceIdentifierCodec().serialize(augPath); + if(domPath == null) { + LOG.error("Unable to serialize instance identifier for {}",augPath); + } + } catch (Exception e) { + LOG.error("Unable to serialize instance identifiers for {}",augPath,e); + } + + } + } else { + // Omits warning for empty augmentations since they are not represented in data + if(!aug.getChildNodes().isEmpty()) { + LOG.warn("Could not find generated type for augmentation {} with children {}", aug, + aug.getChildNodes()); + } + } + } + } + + + + private Type getTypeForAugmentation(final AugmentationSchema aug) { + Optional currentAug = Optional.of(aug); + while (currentAug.isPresent()) { + Type potentialType = typeToAugment.inverse().get(currentAug.get()); + if (potentialType != null) { + return potentialType; + } + currentAug = currentAug.get().getOriginalDefinition(); + } + return null; } } @@ -974,25 +1238,43 @@ public class LazyGeneratedCodecRegistry implements // } @Override - public Object deserialize(Object input) { + public Object deserialize(final Object input) { return getDelegate().deserialize(input); } @Override - public Object serialize(Object input) { + public Object deserialize(final Object input, final InstanceIdentifier bindingIdentifier) { + return getDelegate().deserialize(input, bindingIdentifier); + } + + @Override + public Object serialize(final Object input) { return getDelegate().serialize(input); } + } + @SuppressWarnings("rawtypes") private static class AugmentationCodecWrapper> implements AugmentationCodec, - Delegator { + Delegator, LocationAwareBindingCodec, ValueWithQName> { private final BindingCodec delegate; private final QName augmentationQName; + private final Multimap, QName> validAugmentationTargets; + private final Class augmentationType; - public AugmentationCodecWrapper(BindingCodec, Object> rawCodec) { + public AugmentationCodecWrapper(final BindingCodec, Object> rawCodec, final Class dataType) { this.delegate = rawCodec; + this.augmentationType = dataType; this.augmentationQName = BindingReflections.findQName(rawCodec.getClass()); + this.validAugmentationTargets = Multimaps.synchronizedSetMultimap(HashMultimap + ., QName> create()); + } + + public void addApplicableFor(final InstanceIdentifier path, final AugmentationSchema aug) { + for (DataSchemaNode child : aug.getChildNodes()) { + validAugmentationTargets.put(path, child.getQName()); + } } @Override @@ -1001,7 +1283,7 @@ public class LazyGeneratedCodecRegistry implements // } @Override - public CompositeNode serialize(ValueWithQName input) { + public CompositeNode serialize(final ValueWithQName input) { @SuppressWarnings("unchecked") List> rawValues = (List>) getDelegate().serialize(input); List> serialized = new ArrayList<>(rawValues.size()); @@ -1013,27 +1295,56 @@ public class LazyGeneratedCodecRegistry implements // @Override @SuppressWarnings("unchecked") - public ValueWithQName deserialize(Node input) { + public ValueWithQName deserialize(final Node input) { Object rawCodecValue = getDelegate().deserialize(input); return new ValueWithQName(input.getNodeType(), (T) rawCodecValue); } + @Override + @SuppressWarnings("unchecked") + public ValueWithQName deserialize(final Node input, final InstanceIdentifier bindingIdentifier) { + // if (!isAcceptable(bindingIdentifier)) { + // return null; + // } + Object rawCodecValue = getDelegate().deserialize(input, bindingIdentifier); + return new ValueWithQName(input.getNodeType(), (T) rawCodecValue); + } + @Override public QName getAugmentationQName() { return augmentationQName; } + + @Override + public boolean isAcceptable(final InstanceIdentifier path) { + if (path == null) { + return false; + } + return validAugmentationTargets.containsKey(path); + } + + @Override + public boolean isApplicable(final InstanceIdentifier location) { + return isAcceptable(location); + } + + @Override + public Class getDataType() { + return augmentationType; + } } + @SuppressWarnings("rawtypes") private class IdentityCompositeCodec implements IdentityCodec { @Override - public Object deserialize(Object input) { + public Object deserialize(final Object input) { Preconditions.checkArgument(input instanceof QName); return deserialize((QName) input); } @Override - public Class deserialize(QName input) { + public Class deserialize(final QName input) { Type type = qnamesToIdentityMap.get(input); if (type == null) { return null; @@ -1058,7 +1369,32 @@ public class LazyGeneratedCodecRegistry implements // } @Override - public QName serialize(Class input) { + public Object deserialize(final Object input, final InstanceIdentifier bindingIdentifier) { + Type type = qnamesToIdentityMap.get(input); + if (type == null) { + return null; + } + ReferencedTypeImpl typeref = new ReferencedTypeImpl(type.getPackageName(), type.getName()); + WeakReference softref = typeToClass.get(typeref); + if (softref == null) { + + try { + Class cls = classLoadingStrategy.loadClass(typeref.getFullyQualifiedName()); + if (cls != null) { + serialize(cls); + return cls; + } + } catch (Exception e) { + LOG.warn("Identity {} was not deserialized, because of missing class {}", input, + typeref.getFullyQualifiedName()); + } + return null; + } + return softref.get(); + } + + @Override + public QName serialize(final Class input) { Preconditions.checkArgument(BaseIdentity.class.isAssignableFrom(input)); bindingClassEncountered(input); QName qname = identityQNames.get(input); @@ -1074,31 +1410,14 @@ public class LazyGeneratedCodecRegistry implements // } @Override - public Object serialize(Object input) { + public Object serialize(final Object input) { Preconditions.checkArgument(input instanceof Class); return serialize((Class) input); } + } - public boolean isCodecAvailable(Class 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; + private static final Type referencedType(final Class augmentableType) { + return new ReferencedTypeImpl(augmentableType.getPackage().getName(), augmentableType.getSimpleName()); } }