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<Class<?>, DataContainerCodec<?>> containerCodecs = Collections
@SuppressWarnings("rawtypes")
private static final ConcurrentMap<Type, ChoiceCaseCodecImpl> typeToCaseCodecs = new ConcurrentHashMap<>();
- private final CaseClassMapFacade classToCaseRawCodec = new CaseClassMapFacade();
-
- private static final Map<SchemaPath, InstanceIdentifier<?>> pathToBindingIdentifier = new ConcurrentHashMap<>();
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 static final Multimap<Type, Type> choiceToCases = Multimaps.synchronizedMultimap(HashMultimap
.<Type, Type> 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 ClassLoadingStrategy classLoadingStrategy;
-
- LazyGeneratedCodecRegistry(final SchemaLock lock, final ClassLoadingStrategy 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(final TransformerGenerator generator) {
- this.generator = generator;
- }
-
@Override
public InstanceIdentifierCodec getInstanceIdentifierCodec() {
return instanceIdentifierCodec;
AugmentationCodecWrapper potentialCodec = augmentationCodecs.get(object);
if (potentialCodec != null) {
codec = potentialCodec;
- } else
+ } else {
try {
lock.waitForSchema(object);
Class<? extends BindingCodec<Map<QName, Object>, Object>> augmentRawCodec = generator
"Run-time consistency issue: constructor {} is not available. This indicates either a code generation bug or a misconfiguration of JVM.",
object.getSimpleName(), e);
}
+ }
Class<? extends Augmentable<?>> objectSupertype = getAugmentableArgumentFrom(object);
if (objectSupertype != null) {
getAugmentableCodec(objectSupertype).addImplementation(codec);
@Override
public Class<?> getClassForPath(final 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());
+ 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);
- }
- @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());
+ Preconditions.checkState(type != null, "Failed to lookup instantiated type for path %s", path);
}
+ @SuppressWarnings("rawtypes")
+ final WeakReference<Class> 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(final List<QName> names, final Class<?> cls) {
- Type reference = Types.typeForClass(cls);
+ final Type reference = Types.typeForClass(cls);
pathToInstantiatedType.put(names, reference);
+ LOG.trace("Path {} attached to class {} reference {}", names, cls, reference);
bindingClassEncountered(cls);
}
- public InstanceIdentifier<?> getBindingIdentifierByPath(final SchemaPath path) {
- return pathToBindingIdentifier.get(path);
- }
-
- public void putPathToBindingIdentifier(final SchemaPath path, final InstanceIdentifier<?> bindingIdentifier) {
- pathToBindingIdentifier.put(path, bindingIdentifier);
- }
-
- public InstanceIdentifier<?> putPathToBindingIdentifier(final SchemaPath path,
- final InstanceIdentifier<?> bindingIdentifier, final Class<?> childClass) {
- InstanceIdentifier<?> newId = bindingIdentifier.builder().child((Class) childClass).build();
- pathToBindingIdentifier.put(path, newId);
- return newId;
- }
-
@Override
public IdentifierCodec<?> getKeyCodecForPath(final List<QName> names) {
@SuppressWarnings("unchecked")
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);
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<DataNodeContainer> 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 {
}
}
- abstract protected T tryToLoadImplementation(Class<? extends DataContainer> inputType);
+ protected abstract T tryToLoadImplementation(Class<? extends DataContainer> inputType);
- abstract protected void tryToLoadImplementations();
+ protected abstract void tryToLoadImplementations();
- abstract protected void adaptForPathImpl(InstanceIdentifier<?> path, DataNodeContainer ctx);
+ protected abstract void adaptForPathImpl(InstanceIdentifier<?> path, DataNodeContainer ctx);
}
@SuppressWarnings("rawtypes")
* Key type
*/
@SuppressWarnings("rawtypes")
- private static abstract class MapFacadeBase<T> implements Map<T, BindingCodec<?, ?>> {
+ private abstract static class MapFacadeBase<T> implements Map<T, BindingCodec<?, ?>> {
@Override
public boolean containsKey(final Object key) {
}
- public boolean isCodecAvailable(final Class<? extends DataContainer> cls) {
+ public boolean isCodecAvailable(final Class<?> cls) {
+ // FIXME: enforce type?
+ // Preconditions.checkArgument(DataContainer.class.isAssignableFrom(cls));
+
if (containerCodecs.containsKey(cls)) {
return true;
}