import org.eclipse.xtext.xbase.lib.Extension;
import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy;
-import org.opendaylight.yangtools.sal.binding.generator.util.ClassLoaderUtils;
import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
import org.opendaylight.yangtools.yang.binding.BindingCodec;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
}
/**
- * Creates the name of the getter method from <code>methodName</code>.
+ * Creates the name of the getter method name from <code>localName</code>.
*
- * @param methodName
+ * @param localName
* string with the name of the getter method
* @param returnType return type
* @return string with the name of the getter method for
currentContainer = findNotification(ctx, currentQName);
} else if (BindingReflections.isRpcType(currentArg.getType())) {
currentContainer = findFirstDataNodeContainerInRpc(ctx, currentArg.getType());
+ if(currentQName == null && currentContainer.isPresent()) {
+ currentQName = ((DataSchemaNode) currentContainer.get()).getQName();
+ }
} else {
currentContainer = findDataNodeContainer(ctx, currentQName);
}
private static Optional<DataNodeContainer> findFirstDataNodeContainerInRpc(final SchemaContext ctx,
final Class<? extends DataObject> targetType) {
+ final YangModuleInfo moduleInfo;
try {
- YangModuleInfo moduleInfo = BindingReflections.getModuleInfo(targetType);
- for(RpcDefinition rpc : ctx.getOperations()) {
- String rpcNamespace = rpc.getQName().getNamespace().toString();
- String rpcRevision = rpc.getQName().getFormattedRevision();
- if(moduleInfo.getNamespace().equals(rpcNamespace) && moduleInfo.getRevision().equals(rpcRevision)) {
- Optional<DataNodeContainer> potential = findInputOutput(rpc,targetType.getSimpleName());
- if(potential.isPresent()) {
- return potential;
- }
+ moduleInfo = BindingReflections.getModuleInfo(targetType);
+ } catch (Exception e) {
+ throw new IllegalArgumentException(
+ String.format("Failed to load module information for class %s", targetType), e);
+ }
+
+ for(RpcDefinition rpc : ctx.getOperations()) {
+ String rpcNamespace = rpc.getQName().getNamespace().toString();
+ String rpcRevision = rpc.getQName().getFormattedRevision();
+ if(moduleInfo.getNamespace().equals(rpcNamespace) && moduleInfo.getRevision().equals(rpcRevision)) {
+ Optional<DataNodeContainer> potential = findInputOutput(rpc,targetType.getSimpleName());
+ if(potential.isPresent()) {
+ return potential;
}
}
- } catch (Exception e) {
- // FIXME: Add logging
}
return Optional.absent();
}
package org.opendaylight.yangtools.sal.binding.generator.impl;
import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy;
-import org.opendaylight.yangtools.sal.binding.generator.util.ClassLoaderUtils;
import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils;
public abstract class GeneratedClassLoadingStrategy implements ClassLoadingStrategy {
private static final GeneratedClassLoadingStrategy TCCL_STRATEGY = new TCCLClassLoadingStrategy();
private static final GeneratedClassLoadingStrategy ALWAYS_FAIL_STRATEGY = new GeneratedClassLoadingStrategy() {
-
@Override
- public Class<?> loadClass(String fullyQualifiedName) throws ClassNotFoundException {
+ public Class<?> loadClass(final String fullyQualifiedName) throws ClassNotFoundException {
throw new ClassNotFoundException(fullyQualifiedName);
}
};
- public Class<?> loadClass(Type type) throws ClassNotFoundException {
+ @Override
+ public Class<?> loadClass(final Type type) throws ClassNotFoundException {
return loadClass(type.getFullyQualifiedName());
}
+ @Override
public abstract Class<?> loadClass(String fullyQualifiedName) throws ClassNotFoundException;
public static final GeneratedClassLoadingStrategy getTCCLClassLoadingStrategy() {
}
private static final class TCCLClassLoadingStrategy extends GeneratedClassLoadingStrategy {
-
@Override
- public Class<?> loadClass(String fullyQualifiedName) throws ClassNotFoundException {
+ public Class<?> loadClass(final String fullyQualifiedName) throws ClassNotFoundException {
return ClassLoaderUtils.loadClassWithTCCL(fullyQualifiedName);
}
}
codec = new AugmentationCodecWrapper<T>(rawCodec, null, object);
augmentationCodecs.put(object, codec);
}
- Class<? extends Augmentable<?>> objectSupertype = getAugmentableArgumentFrom(object);
- if (objectSupertype != null) {
- getAugmentableCodec(objectSupertype).addImplementation(codec);
- } else {
- LOG.warn("Could not find augmentation target for augmentation {}", object);
+
+ final Class<? extends Augmentable<?>> objectSupertype;
+ try {
+ objectSupertype = BindingReflections.findAugmentationTarget(object);
+ } catch (Exception e) {
+ LOG.warn("Failed to find target for augmentation {}, ignoring it", object, e);
+ return codec;
+ }
+
+ if (objectSupertype == null) {
+ LOG.warn("Augmentation target for {} not found, ignoring it", object);
+ return codec;
}
+
+ getAugmentableCodec(objectSupertype).addImplementation(codec);
return codec;
}
return getCodecForAugmentation((Class<? extends Augmentation<?>>) cls).getAugmentationQName();
}
- private static Class<? extends Augmentable<?>> getAugmentableArgumentFrom(
- final Class<? extends Augmentation<?>> augmentation) {
- try {
- Class<? extends Augmentable<?>> ret = BindingReflections.findAugmentationTarget(augmentation);
- return ret;
-
- } catch (Exception e) {
- LOG.debug("Could not find augmentable for {} using {}", augmentation, augmentation.getClassLoader(), e);
- return null;
- }
- }
-
@Override
public Class<?> getClassForPath(final List<QName> names) {
final DataSchemaNode node = getSchemaNode(names);
private DataSchemaNode getSchemaNode(final List<QName> path) {
QName firstNode = path.get(0);
- DataNodeContainer previous = currentSchema.findModuleByNamespaceAndRevision(firstNode.getNamespace(),
- firstNode.getRevision());
+ DataNodeContainer previous = currentSchema.findModuleByNamespaceAndRevision(firstNode.getNamespace(), firstNode.getRevision());
+ Preconditions.checkArgument(previous != null, "Failed to find module %s for path %s", firstNode, path);
+
Iterator<QName> iterator = path.iterator();
while (iterator.hasNext()) {
QName arg = iterator.next();
.loadClass(potential);
return Optional.of(tryToLoadImplementation(clazz));
} catch (ClassNotFoundException e) {
- LOG.warn("Failed to find class for augmentation of {}, reason: {}", potential, e.toString());
+ LOG.warn("Failed to find class for augmentation of {}", potential, e);
}
return Optional.absent();
}
AugmentationCodecWrapper<? extends Augmentation<?>> potentialImpl = getCodecForAugmentation(inputType);
addImplementation(potentialImpl);
return potentialImpl;
-
}
@Override
try {
tryToLoadImplementation(potential);
} catch (CodeGenerationException e) {
- LOG.warn("Failed to proactively generate augment coded for {}, reason: {}", type, e.toString());
+ LOG.warn("Failed to proactively generate augment code for {}", type, e);
}
}
-
}
@Override
if (!availableAugmentations.isEmpty()) {
updateAugmentationMapping(path,availableAugmentations);
}
-
}
}
potentialImpl.get().addApplicableFor(path,aug);
}
} else {
- LOG.warn("Could not find generated type for augmentation {} with childs {}.",aug,aug.getChildNodes());
+ LOG.warn("Could not find generated type for augmentation {} with children {}", aug, aug.getChildNodes());
}
}
availableAugmentations.toString();
*/
package org.opendaylight.yangtools.sal.binding.generator.impl;
-import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.ref.WeakReference;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
import org.opendaylight.yangtools.concepts.ObjectRegistration;
import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy;
import org.opendaylight.yangtools.sal.binding.generator.api.ModuleInfoRegistry;
-import org.opendaylight.yangtools.sal.binding.generator.util.ClassLoaderUtils;
import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.ref.WeakReference;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
public class ModuleInfoBackedContext extends GeneratedClassLoadingStrategy //
implements //
AdvancedSchemaSourceProvider<InputStream>, ModuleInfoRegistry, SchemaContextProvider {
- private ModuleInfoBackedContext(ClassLoadingStrategy loadingStrategy) {
+ private ModuleInfoBackedContext(final ClassLoadingStrategy loadingStrategy) {
this.backingLoadingStrategy = loadingStrategy;
}
return new ModuleInfoBackedContext(getTCCLClassLoadingStrategy());
}
- public static ModuleInfoBackedContext create(ClassLoadingStrategy loadingStrategy) {
+ public static ModuleInfoBackedContext create(final ClassLoadingStrategy loadingStrategy) {
return new ModuleInfoBackedContext(loadingStrategy);
}
private final ClassLoadingStrategy backingLoadingStrategy;
@Override
- public Class<?> loadClass(String fullyQualifiedName) throws ClassNotFoundException {
+ public Class<?> loadClass(final String fullyQualifiedName) throws ClassNotFoundException {
String modulePackageName = BindingReflections.getModelRootPackageName(fullyQualifiedName);
WeakReference<ClassLoader> classLoaderRef = packageNameToClassLoader.get(modulePackageName);
return sourceStreams.build();
}
- private boolean resolveModuleInfo(Class<?> cls) {
+ private boolean resolveModuleInfo(final Class<?> cls) {
try {
return resolveModuleInfo(BindingReflections.getModuleInfo(cls));
} catch (Exception e) {
- throw new IllegalStateException(e);
+ throw new IllegalStateException(String.format("Failed to resolve module information for class %s", cls), e);
}
}
- private boolean resolveModuleInfo(YangModuleInfo moduleInfo) {
+ private boolean resolveModuleInfo(final YangModuleInfo moduleInfo) {
SourceIdentifier identifier = sourceIdentifierFrom(moduleInfo);
YangModuleInfo previous = sourceIdentifierToModuleInfo.putIfAbsent(identifier, moduleInfo);
return true;
}
- private SourceIdentifier sourceIdentifierFrom(YangModuleInfo moduleInfo) {
+ private SourceIdentifier sourceIdentifierFrom(final YangModuleInfo moduleInfo) {
return SourceIdentifier.create(moduleInfo.getName(), Optional.of(moduleInfo.getRevision()));
}
- public void addModuleInfos(Iterable<? extends YangModuleInfo> moduleInfos) {
+ public void addModuleInfos(final Iterable<? extends YangModuleInfo> moduleInfos) {
for (YangModuleInfo yangModuleInfo : moduleInfos) {
registerModuleInfo(yangModuleInfo);
}
}
@Override
- public ObjectRegistration<YangModuleInfo> registerModuleInfo(YangModuleInfo yangModuleInfo) {
+ public ObjectRegistration<YangModuleInfo> registerModuleInfo(final YangModuleInfo yangModuleInfo) {
YangModuleInfoRegistration registration = new YangModuleInfoRegistration(yangModuleInfo, this);
resolveModuleInfo(yangModuleInfo);
}
@Override
- public Optional<InputStream> getSchemaSource(SourceIdentifier sourceIdentifier) {
+ public Optional<InputStream> getSchemaSource(final SourceIdentifier sourceIdentifier) {
YangModuleInfo info = sourceIdentifierToModuleInfo.get(sourceIdentifier);
if (info == null) {
return Optional.absent();
}
@Override
- public Optional<InputStream> getSchemaSource(String moduleName, Optional<String> revision) {
+ public Optional<InputStream> getSchemaSource(final String moduleName, final Optional<String> revision) {
return getSchemaSource(SourceIdentifier.create(moduleName, revision));
}
private final ModuleInfoBackedContext context;
- public YangModuleInfoRegistration(YangModuleInfo instance, ModuleInfoBackedContext context) {
+ public YangModuleInfoRegistration(final YangModuleInfo instance, final ModuleInfoBackedContext context) {
super(instance);
this.context = context;
}
}
- private void remove(YangModuleInfoRegistration registration) {
+ private void remove(final YangModuleInfoRegistration registration) {
// FIXME implement
}
import com.google.common.base.Joiner;
import com.google.common.base.Optional;
+/**
+ * @deprecated Use {@link org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils} instead.
+ */
+@Deprecated
public final class ClassLoaderUtils {
private ClassLoaderUtils() {
* created if this is a new pool. If an instance already exists, is is
* returned.
*
- * @param pool
- * @return
+ * @param pool Backing class pool
+ * @return shared utility instance for specified pool
*/
public static synchronized JavassistUtils forClassPool(final ClassPool pool) {
- JavassistUtils ret = INSTANCES.get(pool);
+ JavassistUtils ret = INSTANCES.get(Preconditions.checkNotNull(pool));
if (ret == null) {
ret = new JavassistUtils(pool, null);
INSTANCES.put(pool, ret);
import java.util.concurrent.Callable;
import java.util.concurrent.locks.Lock;
-
+/**
+ * @deprecated Use {@link org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils} instead.
+ */
+@Deprecated
public final class ClassLoaderUtils {
private ClassLoaderUtils() {
throw new UnsupportedOperationException("Utility class");
}
- public static <V> V withClassLoader(ClassLoader cls, Callable<V> function) throws Exception {
+ public static <V> V withClassLoader(final ClassLoader cls, final Callable<V> function) throws Exception {
return withClassLoaderAndLock(cls, null, function);
}
- public static <V> V withClassLoaderAndLock(ClassLoader cls, Lock lock, Callable<V> function) throws Exception {
+ public static <V> V withClassLoaderAndLock(final ClassLoader cls, final Lock lock, final Callable<V> function) throws Exception {
if (cls == null) {
throw new IllegalArgumentException("Classloader should not be null");
}
}
}
- public static ParameterizedType findParameterizedType(Class<?> subclass, Class<?> genericType) {
+ public static ParameterizedType findParameterizedType(final Class<?> subclass, final Class<?> genericType) {
if(subclass == null || genericType == null) {
throw new IllegalArgumentException("Class was not specified.");
}
return null;
}
}
-
+
private static <S,G,P> Callable<Class<P>> findFirstGenericArgumentTask(final Class<S> scannedClass, final Class<G> genericType) {
return new Callable<Class<P>>() {
@Override
};
}
- public static Type getFirstGenericParameter(Type type) {
+ public static Type getFirstGenericParameter(final Type type) {
if(type instanceof ParameterizedType) {
return ((ParameterizedType) type).getActualTypeArguments()[0];
}
<artifactId>jsr305</artifactId>
<scope>provided</scope>
</dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>
+ org.opendaylight.yangtools.objcache.impl;resolution:=optional,
+ *
+ </Import-Package>
+ </instructions>
+ </configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
import org.opendaylight.yangtools.objcache.impl.StaticObjectCacheBinder;
import org.opendaylight.yangtools.objcache.spi.IObjectCacheFactory;
+import org.opendaylight.yangtools.objcache.spi.NoopObjectCacheBinder;
import com.google.common.base.Preconditions;
* Point of entry for acquiring an {@link ObjectCache} instance.
*/
public final class ObjectCacheFactory {
- private static IObjectCacheFactory FACTORY;
-
- private static synchronized IObjectCacheFactory initialize() {
- // Double-check under lock
- if (FACTORY != null) {
- return FACTORY;
- }
-
- final IObjectCacheFactory f = StaticObjectCacheBinder.getInstance().getProductCacheFactory();
- FACTORY = f;
- return f;
- }
-
- public static synchronized void reset() {
- FACTORY = null;
- }
-
- /**
- * Get an ObjectCache for caching a particular object class. Note
- * that it may be shared for multiple classes.
- *
- * @param objClass Class of objects which are to be cached
- * @return Object cache instance.
- */
- public static ObjectCache getObjectCache(@Nonnull final Class<?> objClass) {
- IObjectCacheFactory f = FACTORY;
- if (f == null) {
- f = initialize();
- }
-
- return f.getObjectCache(Preconditions.checkNotNull(objClass));
- }
+ private static IObjectCacheFactory FACTORY;
+
+ private static synchronized IObjectCacheFactory initialize() {
+ // Double-check under lock
+ if (FACTORY != null) {
+ return FACTORY;
+ }
+
+ IObjectCacheFactory f;
+ try {
+ f = StaticObjectCacheBinder.getInstance().getProductCacheFactory();
+ FACTORY = f;
+ } catch (NoClassDefFoundError e) {
+ f = NoopObjectCacheBinder.INSTANCE.getProductCacheFactory();
+ }
+
+ return f;
+ }
+
+ public static synchronized void reset() {
+ FACTORY = null;
+ }
+
+ /**
+ * Get an ObjectCache for caching a particular object class. Note
+ * that it may be shared for multiple classes.
+ *
+ * @param objClass Class of objects which are to be cached
+ * @return Object cache instance.
+ */
+ public static ObjectCache getObjectCache(@Nonnull final Class<?> objClass) {
+ IObjectCacheFactory f = FACTORY;
+ if (f == null) {
+ f = initialize();
+ }
+
+ return f.getObjectCache(Preconditions.checkNotNull(objClass));
+ }
}
*/
package org.opendaylight.yangtools.objcache.spi;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+
import org.opendaylight.yangtools.concepts.ProductAwareBuilder;
import org.opendaylight.yangtools.objcache.ObjectCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.FinalizableReferenceQueue;
import com.google.common.base.FinalizableSoftReference;
import com.google.common.base.Preconditions;
* a backing {@link Cache} instance and provide the
*/
public abstract class AbstractObjectCache implements ObjectCache {
- /**
- * Key used when looking up a ProductAwareBuilder product. We assume
- * the builder is not being modified for the duration of the lookup,
- * anything else is the user's fault.
- */
- private static final class BuilderKey {
- private final ProductAwareBuilder<?> builder;
-
- private BuilderKey(final ProductAwareBuilder<?> builder) {
- this.builder = Preconditions.checkNotNull(builder);
- }
-
- @Override
- public int hashCode() {
- return builder.productHashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- /*
- * We can tolerate null objects coming our way, but we need
- * to be on the lookout for WeakKeys, as we cannot pass them
- * directly to productEquals().
- */
- if (obj != null && obj instanceof SoftKey) {
- obj = ((SoftKey)obj).get();
- }
-
- return builder.productEquals(obj);
- }
- }
-
- /**
- * Key used in the underlying map. It is essentially a soft reference, with
- * slightly special properties.
- *
- * It acts as a proxy for the object it refers to and essentially delegates
- * to it. There are three exceptions here:
- *
- * 1) This key needs to have a cached hash code. The requirement is that the
- * key needs to be able to look itself up after the reference to the object
- * has been cleared (and thus we can no longer look it up from there). One
- * typical container where we are stored are HashMaps -- and they need it
- * to be constant.
- * 2) This key does not tolerate checks to see if its equal to null. While we
- * could return false, we want to catch offenders who try to store nulls
- * in the cache.
- * 3) This key inverts the check for equality, e.g. it calls equals() on the
- * object which was passed to its equals(). Instead of supplying itself,
- * it supplies the referent. If the soft reference is cleared, such check
- * will return false, which is fine as it prevents normal lookup from
- * seeing the cleared key. Removal is handled by the explicit identity
- * check.
- */
- private static abstract class SoftKey extends FinalizableSoftReference<Object> {
- private final int hashCode;
-
- public SoftKey(final Object referent, final FinalizableReferenceQueue q) {
- super(Preconditions.checkNotNull(referent), q);
- hashCode = referent.hashCode();
- }
-
- @Override
- public boolean equals(final Object obj) {
- Preconditions.checkState(obj != null);
-
- // Order is important: we do not want to call equals() on ourselves!
- return this == obj || obj.equals(get());
- }
-
- @Override
- public int hashCode() {
- return hashCode;
- }
- }
-
- private static final Logger LOG = LoggerFactory.getLogger(AbstractObjectCache.class);
- private final FinalizableReferenceQueue queue;
- private final Cache<Object, Object> cache;
-
- protected AbstractObjectCache(final Cache<Object, Object> cache, final FinalizableReferenceQueue queue) {
- this.queue = Preconditions.checkNotNull(queue);
- this.cache = Preconditions.checkNotNull(cache);
- }
-
- private <T> T put(final T object) {
- /*
- * This may look like a race (having a soft reference and not have
- * it in the cache). In fact this is protected by the fact we still
- * have a strong reference on the object in our arguments and that
- * reference survives past method return since we return it.
- */
- final Object key = new SoftKey(object, queue) {
- @Override
- public void finalizeReferent() {
- /*
- * NOTE: while it may be tempting to add "object" into this
- * trace message, do not ever do that: it would retain
- * a strong reference, preventing collection.
- */
- LOG.trace("Invalidating key {} for object {}", this);
- cache.invalidate(this);
- }
- };
- cache.put(key, object);
- LOG.debug("Cached key {} to object {}", key, object);
- return object;
- }
-
- @Override
- public final <B extends ProductAwareBuilder<P>, P> P getProduct(final B builder) {
- LOG.debug("Looking up product for {}", builder);
-
- @SuppressWarnings("unchecked")
- final P ret = (P) cache.getIfPresent(new BuilderKey(builder));
- return ret == null ? put(Preconditions.checkNotNull(builder.toInstance())) : ret;
- }
-
- @Override
- public final <T> T getReference(final T object) {
- LOG.debug("Looking up reference for {}", object);
- if (object == null) {
- return null;
- }
-
- @SuppressWarnings("unchecked")
- final T ret = (T) cache.getIfPresent(object);
- return ret == null ? put(object) : ret;
- }
+ /**
+ * Key used when looking up a ProductAwareBuilder product. We assume
+ * the builder is not being modified for the duration of the lookup,
+ * anything else is the user's fault.
+ */
+ @VisibleForTesting
+ static final class BuilderKey {
+ private final ProductAwareBuilder<?> builder;
+
+ private BuilderKey(final ProductAwareBuilder<?> builder) {
+ this.builder = Preconditions.checkNotNull(builder);
+ }
+
+ @Override
+ public int hashCode() {
+ return builder.productHashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ /*
+ * We can tolerate null objects coming our way, but we need
+ * to be on the lookout for WeakKeys, as we cannot pass them
+ * directly to productEquals().
+ */
+ if (obj != null && obj instanceof SoftKey) {
+ obj = ((SoftKey<?>)obj).get();
+ }
+
+ return builder.productEquals(obj);
+ }
+ }
+
+ /**
+ * Key used in the underlying map. It is essentially a soft reference, with
+ * slightly special properties.
+ *
+ * It acts as a proxy for the object it refers to and essentially delegates
+ * to it. There are three exceptions here:
+ *
+ * 1) This key needs to have a cached hash code. The requirement is that the
+ * key needs to be able to look itself up after the reference to the object
+ * has been cleared (and thus we can no longer look it up from there). One
+ * typical container where we are stored are HashMaps -- and they need it
+ * to be constant.
+ * 2) This key does not tolerate checks to see if its equal to null. While we
+ * could return false, we want to catch offenders who try to store nulls
+ * in the cache.
+ * 3) This key inverts the check for equality, e.g. it calls equals() on the
+ * object which was passed to its equals(). Instead of supplying itself,
+ * it supplies the referent. If the soft reference is cleared, such check
+ * will return false, which is fine as it prevents normal lookup from
+ * seeing the cleared key. Removal is handled by the explicit identity
+ * check.
+ */
+ protected abstract static class SoftKey<T> extends FinalizableSoftReference<T> {
+ private final int hashCode;
+
+ public SoftKey(final T referent, final FinalizableReferenceQueue q) {
+ super(Preconditions.checkNotNull(referent), q);
+ hashCode = referent.hashCode();
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+
+ // Order is important: we do not want to call equals() on ourselves!
+ return this == obj || obj.equals(get());
+ }
+
+ @Override
+ public int hashCode() {
+ return hashCode;
+ }
+ }
+
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractObjectCache.class);
+ private final FinalizableReferenceQueue queue;
+ private final Cache<SoftKey<?>, Object> cache;
+
+ protected AbstractObjectCache(final Cache<SoftKey<?>, Object> cache, final FinalizableReferenceQueue queue) {
+ this.queue = Preconditions.checkNotNull(queue);
+ this.cache = Preconditions.checkNotNull(cache);
+ }
+
+ protected <T> SoftKey<T> createSoftKey(final T object) {
+ /*
+ * This may look like a race (having a soft reference and not have
+ * it in the cache). In fact this is protected by the fact we still
+ * have a strong reference on the object in our arguments and that
+ * reference survives past method return since we return it.
+ */
+ return new SoftKey<T>(object, queue) {
+ @Override
+ public void finalizeReferent() {
+ /*
+ * NOTE: while it may be tempting to add "object" into this
+ * trace message, do not ever do that: it would retain
+ * a strong reference, preventing collection.
+ */
+ LOG.trace("Invalidating key {}", this);
+ cache.invalidate(this);
+ }
+ };
+ }
+
+ @Override
+ public final <B extends ProductAwareBuilder<P>, P> P getProduct(final B builder) {
+ throw new UnsupportedOperationException();
+// LOG.debug("Looking up product for {}", builder);
+//
+// @SuppressWarnings("unchecked")
+// final P ret = (P) cache.getIfPresent(new BuilderKey(builder));
+// return ret == null ? put(Preconditions.checkNotNull(builder.toInstance())) : ret;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public final <T> T getReference(final T object) {
+ LOG.debug("Looking up reference for {}", object);
+ if (object == null) {
+ return null;
+ }
+
+ final SoftKey<T> key = createSoftKey(object);
+ try {
+ return (T) cache.get(key, new Callable<T>() {
+ @Override
+ public T call() {
+ return object;
+ }
+ });
+ } catch (ExecutionException e) {
+ throw new IllegalStateException("Failed to load value", e);
+ }
+ }
}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.objcache.spi;
+
+import org.opendaylight.yangtools.objcache.ObjectCache;
+
+public final class NoopObjectCacheBinder extends AbstractObjectCacheBinder {
+ public static final NoopObjectCacheBinder INSTANCE = new NoopObjectCacheBinder();
+
+ private NoopObjectCacheBinder() {
+ super(new IObjectCacheFactory() {
+ @Override
+ public ObjectCache getObjectCache(final Class<?> objClass) {
+ return NoopObjectCache.getInstance();
+ }
+ });
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.objcache.spi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.objcache.ObjectCache;
+import org.opendaylight.yangtools.objcache.ObjectCacheFactory;
+
+public class CacheFactoryTest {
+
+ @Test
+ public void testInvalidEnvironment() {
+ final ObjectCache oc = ObjectCacheFactory.getObjectCache(String.class);
+
+ assertNotNull(oc);
+ assertEquals(NoopObjectCache.class, oc.getClass());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.objcache.spi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yangtools.objcache.ObjectCache;
+import org.opendaylight.yangtools.objcache.spi.AbstractObjectCache.SoftKey;
+
+import com.google.common.base.FinalizableReferenceQueue;
+import com.google.common.cache.CacheBuilder;
+
+public class CacheTest {
+ private FinalizableReferenceQueue queue;
+ private ObjectCache oc;
+
+ @Before
+ public void setUp() {
+ queue = new FinalizableReferenceQueue();
+ oc = new AbstractObjectCache(CacheBuilder.newBuilder().softValues().<SoftKey<?>, Object>build(), queue) {
+ };
+ }
+
+ @After
+ public void tearDown() {
+ queue.close();
+ }
+
+ @Test
+ public void testMissingKey() {
+ final String key1 = "abcd";
+ final String key2 = "efgh";
+
+ assertSame(key1, oc.getReference(key1));
+ assertSame(key2, oc.getReference(key2));
+ }
+
+ @Test
+ public void testPresentKey() {
+ final String key1 = new String("abcd");
+ final String key2 = new String("abcd");
+
+ assertSame(key1, oc.getReference(key1));
+
+ final String key3 = oc.getReference(key2);
+ assertEquals(key2, key3);
+ assertNotSame(key2, key3);
+ assertSame(key1, key3);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.objcache.spi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yangtools.objcache.spi.AbstractObjectCache.SoftKey;
+
+import com.google.common.base.FinalizableReferenceQueue;
+
+public class SoftKeyTest {
+ private FinalizableReferenceQueue queue;
+
+
+ @Before
+ public void setUp() {
+ queue = new FinalizableReferenceQueue();
+ }
+
+ @After
+ public void tearDown() {
+ queue.close();
+ }
+
+ @Test
+ public void testEquals() {
+ final String str = "foo";
+
+ final SoftKey<?> key = new SoftKey<String>(str, queue) {
+ @Override
+ public void finalizeReferent() {
+
+ }
+ };
+
+ assertSame(str, key.get());
+ assertEquals(str.hashCode(), key.hashCode());
+ assertTrue(key.equals(str));
+ key.clear();
+ assertNull(key.get());
+ assertEquals(str.hashCode(), key.hashCode());
+ assertFalse(key.equals(str));
+ }
+}
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Export-Package>
+ org.opendaylight.yangtools.objcache.impl
+ </Export-Package>
+ <Private-Package>
+ org.opendaylight.yangtools.objcache.guava
+ </Private-Package>
+ </instructions>
+ </configuration>
</plugin>
</plugins>
</build>
import com.google.common.cache.CacheBuilderSpec;
final class GuavaObjectCache extends AbstractObjectCache {
- public GuavaObjectCache(final FinalizableReferenceQueue queue, final CacheBuilderSpec spec) {
- super(CacheBuilder.from(spec).softValues().build(), queue);
- }
+ public GuavaObjectCache(final FinalizableReferenceQueue queue) {
+ super(CacheBuilder.newBuilder().softValues().<SoftKey<?>, Object>build(), queue);
+ }
+
+ public GuavaObjectCache(final FinalizableReferenceQueue queue, final CacheBuilderSpec spec) {
+ super(CacheBuilder.from(spec).<SoftKey<?>, Object>build(), queue);
+ }
}
import com.google.common.base.FinalizableReferenceQueue;
-public final class GuavaObjectCacheFactory implements IObjectCacheFactory {
- private static final GuavaObjectCacheFactory INSTANCE = new GuavaObjectCacheFactory();
- private final FinalizableReferenceQueue queue = new FinalizableReferenceQueue();
- private final ObjectCache cache;
+public final class GuavaObjectCacheFactory implements AutoCloseable, IObjectCacheFactory {
+ private static final GuavaObjectCacheFactory INSTANCE = new GuavaObjectCacheFactory();
+ private final FinalizableReferenceQueue queue = new FinalizableReferenceQueue();
+ private final ObjectCache cache;
- private GuavaObjectCacheFactory() {
- // FIXME: make this more dynamic
- this.cache = new GuavaObjectCache(queue, null);
- }
+ private GuavaObjectCacheFactory() {
+ // FIXME: make this more dynamic using a spec
+ this.cache = new GuavaObjectCache(queue);
+ }
- @Override
- public void finalize() throws Throwable {
- try {
- queue.close();
- } finally {
- super.finalize();
- }
- }
+ @Override
+ public ObjectCache getObjectCache(final Class<?> objClass) {
+ return cache;
+ }
- @Override
- public ObjectCache getObjectCache(final Class<?> objClass) {
- return cache;
- }
+ @Override
+ public void close() {
+ queue.close();
+ }
- public static GuavaObjectCacheFactory getInstance() {
- return INSTANCE;
- }
+ public static GuavaObjectCacheFactory getInstance() {
+ return INSTANCE;
+ }
}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.objcache.guava;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yangtools.objcache.ObjectCache;
+import org.opendaylight.yangtools.objcache.ObjectCacheFactory;
+
+public class GuavaObjectCacheTest {
+ private ObjectCache cache;
+
+ @Before
+ public void setUp() {
+ cache = ObjectCacheFactory.getObjectCache(String.class);
+ }
+
+ @Test
+ public void testCorrectWiring() {
+ assertEquals(GuavaObjectCache.class, cache.getClass());
+ }
+
+ @Test
+ public void testInitialReference() {
+ final String s1 = "abcd";
+ final String s2 = cache.getReference(s1);
+ assertSame(s1, s2);
+ }
+
+ @Test
+ public void testMultipleReferences() {
+ final String s1 = "abcd";
+ final String s2 = new String(s1);
+
+ // Preliminary check
+ assertEquals(s1, s2);
+ assertNotSame(s1, s2);
+
+ assertSame(s1, cache.getReference(s1));
+ assertSame(s1, cache.getReference(s2));
+ assertNotSame(s2, cache.getReference(s2));
+ }
+
+}
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Export-Package>
+ org.opendaylight.yangtools.objcache.impl
+ </Export-Package>
+ <Private-Package>
+ org.opendaylight.yangtools.objcache.noop
+ </Private-Package>
+ </instructions>
+ </configuration>
</plugin>
</plugins>
</build>
import org.opendaylight.yangtools.objcache.spi.NoopObjectCache;
public final class StaticObjectCacheBinder extends AbstractObjectCacheBinder {
- private static final StaticObjectCacheBinder INSTANCE = new StaticObjectCacheBinder();
+ private static final StaticObjectCacheBinder INSTANCE = new StaticObjectCacheBinder();
- private StaticObjectCacheBinder() {
- super(new IObjectCacheFactory() {
- @Override
- public ObjectCache getObjectCache(final Class<?> objClass) {
- return NoopObjectCache.getInstance();
- }
- });
- }
+ private StaticObjectCacheBinder() {
+ super(new IObjectCacheFactory() {
+ @Override
+ public ObjectCache getObjectCache(final Class<?> objClass) {
+ return NoopObjectCache.getInstance();
+ }
+ });
+ }
- public static StaticObjectCacheBinder getInstance() {
- return INSTANCE;
- }
+ public static StaticObjectCacheBinder getInstance() {
+ return INSTANCE;
+ }
}
<artifactId>concepts</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>object-cache-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>object-cache-guava</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>object-cache-noop</artifactId>
+ <version>${project.version}</version>
+ </dependency>
</dependencies>
</dependencyManagement>
private final SchemaContext schcemaContext;
private final Module module;
- public BindingToRestRpc(Class<?> proxiedInterface,BindingIndependentMappingService mappingService,RestconfClientImpl client,SchemaContext schemaContext) throws Exception {
+ public BindingToRestRpc(final Class<?> proxiedInterface,final BindingIndependentMappingService mappingService,final RestconfClientImpl client,final SchemaContext schemaContext) throws Exception {
this.mappingService = mappingService;
this.client = client;
this.schcemaContext = schemaContext;
}
@Override
- public Object invoke(Object o,final Method method, Object[] objects) throws Throwable {
+ public Object invoke(final Object o,final Method method, final Object[] objects) throws Exception {
for (RpcDefinition rpcDef:module.getRpcs()){
if (method.getName().equals(BindingMapping.getMethodName(rpcDef.getQName()))){
final DataSchemaNode rpcOutputSchema = rpcDef.getOutput();
return client.post(ResourceUri.OPERATIONS.getPath() + "/" + moduleName + ":" + rpcMethodName,payloadString,new Function<ClientResponse, Object>() {
@Override
- public Object apply(ClientResponse clientResponse) {
+ public Object apply(final ClientResponse clientResponse) {
if (clientResponse.getStatus() != 200) {
throw new IllegalStateException("Can't get data from restconf. "+clientResponse.getClientResponseStatus());
}
throw new IllegalStateException("Unexpected state of proxy method.");
}
- public static<T> T getProxy(Class<T> proxiedInterface,
- BindingIndependentMappingService mappingService,
- RestconfClientImpl restconfClient,
- SchemaContext schemaContext) {
+ public static<T> T getProxy(final Class<T> proxiedInterface,
+ final BindingIndependentMappingService mappingService,
+ final RestconfClientImpl restconfClient,
+ final SchemaContext schemaContext) {
T proxiedType = null;
try {
proxiedType = (T) Proxy.newProxyInstance
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
-import static org.opendaylight.yangtools.concepts.util.ClassLoaderUtils.withClassLoader;
import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ServiceLoader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import org.opendaylight.yangtools.concepts.util.ClassLoaderUtils;
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.YangModelBindingProvider;
import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
import org.opendaylight.yangtools.yang.common.QName;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
YangModuleInfo moduleInfo = getModuleInfo(key);
return Optional.of(QName.create(moduleInfo.getNamespace(), moduleInfo.getRevision(), moduleInfo.getName()));
}
-
} catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
// NOOP
}
checkArgument(cls != null);
String packageName = getModelRootPackageName(cls.getPackage());
final String potentialClassName = getModuleInfoClassName(packageName);
- return withClassLoader(cls.getClassLoader(), new Callable<YangModuleInfo>() {
-
+ return ClassLoaderUtils.withClassLoader(cls.getClassLoader(), new Callable<YangModuleInfo>() {
@Override
- public YangModuleInfo call() throws Exception {
+ public YangModuleInfo call() throws ClassNotFoundException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
Class<?> moduleInfoClass = Thread.currentThread().getContextClassLoader().loadClass(potentialClassName);
return (YangModuleInfo) moduleInfoClass.getMethod("getInstance").invoke(null);
}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.binding.util;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.locks.Lock;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Supplier;
+
+public final class ClassLoaderUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(ClassLoaderUtils.class);
+
+ private ClassLoaderUtils() {
+ throw new UnsupportedOperationException("Utility class");
+ }
+
+ public static <V> V withClassLoader(final ClassLoader cls, final Supplier<V> function) {
+ checkNotNull(cls, "Classloader should not be null");
+ checkNotNull(function, "Function should not be null");
+
+ final ClassLoader oldCls = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(cls);
+ return function.get();
+ } finally {
+ Thread.currentThread().setContextClassLoader(oldCls);
+ }
+ }
+
+ public static <V> V withClassLoader(final ClassLoader cls, final Callable<V> function) throws Exception {
+ checkNotNull(cls, "Classloader should not be null");
+ checkNotNull(function, "Function should not be null");
+
+ final ClassLoader oldCls = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(cls);
+ return function.call();
+ } finally {
+ Thread.currentThread().setContextClassLoader(oldCls);
+ }
+ }
+
+ public static <V> V withClassLoaderAndLock(final ClassLoader cls, final Lock lock, final Supplier<V> function) {
+ checkNotNull(lock, "Lock should not be null");
+
+ lock.lock();
+ try {
+ return withClassLoader(cls, function);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public static Object construct(final Constructor<? extends Object> constructor, final List<Object> objects)
+ throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+ final Object[] initargs = objects.toArray();
+ return constructor.newInstance(initargs);
+ }
+
+ public static Class<?> loadClass(final ClassLoader cls, final String name) throws ClassNotFoundException {
+ if ("byte[]".equals(name)) {
+ return byte[].class;
+ }
+ if ("char[]".equals(name)) {
+ return char[].class;
+ }
+
+ try {
+ return cls.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 cls.loadClass(innerName);
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ public static Class<?> loadClassWithTCCL(final String name) throws ClassNotFoundException {
+ return loadClass(Thread.currentThread().getContextClassLoader(), name);
+ }
+
+ public static Class<?> tryToLoadClassWithTCCL(final String fullyQualifiedName) {
+ try {
+ return loadClassWithTCCL(fullyQualifiedName);
+ } catch (ClassNotFoundException e) {
+ LOG.debug("Failed to load class {}", fullyQualifiedName, e);
+ return null;
+ }
+ }
+
+ public static <S,G,P> Class<P> findFirstGenericArgument(final Class<S> scannedClass, final Class<G> genericType) {
+ return withClassLoader(scannedClass.getClassLoader(), ClassLoaderUtils.<S,G,P>findFirstGenericArgumentTask(scannedClass, genericType));
+ }
+
+ private static <S,G,P> Supplier<Class<P>> findFirstGenericArgumentTask(final Class<S> scannedClass, final Class<G> genericType) {
+ return new Supplier<Class<P>>() {
+ @Override
+ @SuppressWarnings("unchecked")
+ public Class<P> get() {
+ final ParameterizedType augmentationGeneric = findParameterizedType(scannedClass, genericType);
+ if (augmentationGeneric != null) {
+ return (Class<P>) augmentationGeneric.getActualTypeArguments()[0];
+ }
+ return null;
+ }
+ };
+ }
+
+ public static ParameterizedType findParameterizedType(final Class<?> subclass, final Class<?> genericType) {
+ Preconditions.checkNotNull(subclass);
+ Preconditions.checkNotNull(genericType);
+
+ for (Type type : subclass.getGenericInterfaces()) {
+ if (type instanceof ParameterizedType && genericType.equals(((ParameterizedType) type).getRawType())) {
+ return (ParameterizedType) type;
+ }
+ }
+
+ LOG.debug("Class {} does not declare interface {}", subclass, genericType);
+ return null;
+ }
+
+ public static Type getFirstGenericParameter(final Type type) {
+ if (type instanceof ParameterizedType) {
+ return ((ParameterizedType) type).getActualTypeArguments()[0];
+ }
+ return null;
+ }
+}
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
+import java.util.Set;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.*;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.ModuleImport;
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
+import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.UsesNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.google.common.base.Preconditions;
-import java.util.Set;
-
/**
* The Schema Context Util contains support methods for searching through Schema
* Context modules for specified schema nodes via Schema Path or Revision Aware
* instantiable.
*
*/
-public class SchemaContextUtil {
+public final class SchemaContextUtil {
+ private static final Logger LOG = LoggerFactory.getLogger(SchemaContextUtil.class);
private SchemaContextUtil() {
}
* @return SchemaNode from the end of the Schema Path or <code>null</code>
* if the Node is not present.
*/
- public static SchemaNode findDataSchemaNode(SchemaContext context, SchemaPath schemaPath) {
+ public static SchemaNode findDataSchemaNode(final SchemaContext context, final SchemaPath schemaPath) {
Preconditions.checkArgument(context != null, "Schema Context reference cannot be NULL");
Preconditions.checkArgument(schemaPath != null, "Schema Path reference cannot be NULL");
- List<QName> prefixedPath = (schemaPath.getPath());
- if (prefixedPath != null) {
- return findNodeInSchemaContext(context, prefixedPath);
+
+ final List<QName> prefixedPath = (schemaPath.getPath());
+ if (prefixedPath == null) {
+ LOG.debug("Schema path {} has null path", schemaPath);
+ return null;
}
- return null;
+
+ LOG.trace("Looking for path {} in context {}", schemaPath, context);
+ return findNodeInSchemaContext(context, prefixedPath);
}
/**
* Non-conditional Revision Aware XPath, or <code>null</code> if the
* DataSchemaNode is not present in Schema Context.
*/
- public static SchemaNode findDataSchemaNode(SchemaContext context, Module module, RevisionAwareXPath nonCondXPath) {
+ public static SchemaNode findDataSchemaNode(final SchemaContext context, final Module module, final RevisionAwareXPath nonCondXPath) {
Preconditions.checkArgument(context != null, "Schema Context reference cannot be NULL");
Preconditions.checkArgument(module != null, "Module reference cannot be NULL");
Preconditions.checkArgument(nonCondXPath != null, "Non Conditional Revision Aware XPath cannot be NULL");
String strXPath = nonCondXPath.toString();
if (strXPath != null) {
- if (strXPath.contains("[")) {
- throw new IllegalArgumentException("Revision Aware XPath cannot contains condition");
- }
+ Preconditions.checkArgument(strXPath.indexOf('[') == -1, "Revision Aware XPath may not contain a condition");
if (nonCondXPath.isAbsolute()) {
List<QName> qnamedPath = xpathToQNamePath(context, module, strXPath);
if (qnamedPath != null) {
* given relative Revision Aware XPath, otherwise will return
* <code>null</code>.
*/
- public static SchemaNode findDataSchemaNodeForRelativeXPath(SchemaContext context, Module module,
- SchemaNode actualSchemaNode, RevisionAwareXPath relativeXPath) {
+ public static SchemaNode findDataSchemaNodeForRelativeXPath(final SchemaContext context, final Module module,
+ final SchemaNode actualSchemaNode, final RevisionAwareXPath relativeXPath) {
Preconditions.checkArgument(context != null, "Schema Context reference cannot be NULL");
Preconditions.checkArgument(module != null, "Module reference cannot be NULL");
Preconditions.checkArgument(actualSchemaNode != null, "Actual Schema Node reference cannot be NULL");
* Schema Node is NOT present, the method will returns
* <code>null</code>
*/
- public static Module findParentModule(SchemaContext context, SchemaNode schemaNode) {
+ public static Module findParentModule(final SchemaContext context, final SchemaNode schemaNode) {
Preconditions.checkArgument(context != null, "Schema Context reference cannot be NULL!");
Preconditions.checkArgument(schemaNode != null, "Schema Node cannot be NULL!");
Preconditions.checkState(schemaNode.getPath() != null, "Schema Path for Schema Node is not "
return context.findModuleByNamespaceAndRevision(qname.getNamespace(), qname.getRevision());
}
- public static SchemaNode findNodeInSchemaContext(SchemaContext context, List<QName> path) {
- QName current = path.get(0);
- Module module = context.findModuleByNamespaceAndRevision(current.getNamespace(), current.getRevision());
- if (module == null)
+ public static SchemaNode findNodeInSchemaContext(final SchemaContext context, final List<QName> path) {
+ final QName current = path.get(0);
+
+ LOG.trace("Looking up module {} in context {}", current, path);
+ final Module module = context.findModuleByNamespaceAndRevision(current.getNamespace(), current.getRevision());
+ if (module == null) {
+ LOG.debug("Module {} not found", current);
return null;
+ }
+
return findNodeInModule(module, path);
}
- public static GroupingDefinition findGrouping(SchemaContext context, Module module, List<QName> path) {
+ public static GroupingDefinition findGrouping(final SchemaContext context, final Module module, final List<QName> path) {
QName first = path.get(0);
Module m = context.findModuleByNamespace(first.getNamespace()).iterator().next();
DataNodeContainer currentParent = m;
found = true;
currentParent = node;
}
- if (!found) {
- throw new IllegalArgumentException("Failed to find referenced grouping: " + path + "("
- + qname.getLocalName() + ")");
- }
+
+ Preconditions.checkArgument(found, "Failed to find referenced grouping: %s(%s)", path, qname.getLocalName());
}
return (GroupingDefinition) currentParent;
}
- private static SchemaNode findNodeInModule(Module module, List<QName> path) {
- QName current = path.get(0);
- SchemaNode node = module.getDataChildByName(current);
- if (node != null)
- return findNode((DataSchemaNode) node, nextLevel(path));
- node = getRpcByName(module, current);
- if (node != null)
- return findNodeInRpc((RpcDefinition) node, nextLevel(path));
- node = getNotificationByName(module, current);
- if (node != null)
- return findNodeInNotification((NotificationDefinition) node, nextLevel(path));
- node = getGroupingByName(module, current);
- if (node != null)
- return findNodeInGrouping((GroupingDefinition) node, nextLevel(path));
- return node;
+ private static SchemaNode findNodeInModule(final Module module, final List<QName> path) {
+ final QName current = path.get(0);
+
+ LOG.trace("Looking for data container {} in module {}", current, module);
+ SchemaNode parent = module.getDataChildByName(current);
+ if (parent != null) {
+ final SchemaNode ret = findNode((DataSchemaNode) parent, nextLevel(path));
+ if (ret != null) {
+ return ret;
+ }
+ }
+
+ LOG.trace("Looking for RPC {} in module {}", current, module);
+ parent = getRpcByName(module, current);
+ if (parent != null) {
+ final SchemaNode ret = findNodeInRpc((RpcDefinition) parent, nextLevel(path));
+ if (ret != null) {
+ return ret;
+ }
+ }
+
+ LOG.trace("Looking for notification {} in module {}", current, module);
+ parent = getNotificationByName(module, current);
+ if (parent != null) {
+ final SchemaNode ret = findNodeInNotification((NotificationDefinition) parent, nextLevel(path));
+ if (ret != null) {
+ return ret;
+ }
+ }
+
+ LOG.trace("Looking for grouping {} in module {}", current, module);
+ parent = getGroupingByName(module, current);
+ if (parent != null) {
+ final SchemaNode ret = findNodeInGrouping((GroupingDefinition) parent, nextLevel(path));
+ if (ret != null) {
+ return ret;
+ }
+ }
+
+ LOG.debug("No node matching {} found in module {}", path, module);
+ return null;
}
- private static SchemaNode findNodeInGrouping(GroupingDefinition grouping, List<QName> path) {
- if (path.isEmpty())
+ private static SchemaNode findNodeInGrouping(final GroupingDefinition grouping, final List<QName> path) {
+ if (path.isEmpty()) {
+ LOG.debug("Found grouping {}", grouping);
return grouping;
- QName current = path.get(0);
- DataSchemaNode node = grouping.getDataChildByName(current);
- if (node != null)
- return findNode(node, nextLevel(path));
- return null;
+ }
+
+ LOG.trace("Looking for path {} in grouping {}", path, grouping);
+ final QName current = path.get(0);
+ final DataSchemaNode node = grouping.getDataChildByName(current);
+ if (node == null) {
+ LOG.debug("No node matching {} found in grouping {}", current, grouping);
+ return null;
+ }
+
+ return findNode(node, nextLevel(path));
}
- private static SchemaNode findNodeInRpc(RpcDefinition rpc, List<QName> path) {
- if (path.isEmpty())
+ private static SchemaNode findNodeInRpc(final RpcDefinition rpc, final List<QName> path) {
+ if (path.isEmpty()) {
+ LOG.debug("Found RPC {}", rpc);
return rpc;
- QName current = path.get(0);
+ }
+
+ LOG.trace("Looking for path {} in rpc {}", path, rpc);
+ final QName current = path.get(0);
switch (current.getLocalName()) {
case "input":
return findNode(rpc.getInput(), nextLevel(path));
case "output":
return findNode(rpc.getOutput(), nextLevel(path));
+ default:
+ LOG.debug("Invalid component {} of path {} in RPC {}", current, path, rpc);
+ return null;
}
- return null;
}
- private static SchemaNode findNodeInNotification(NotificationDefinition rpc, List<QName> path) {
- if (path.isEmpty())
- return rpc;
- QName current = path.get(0);
- DataSchemaNode node = rpc.getDataChildByName(current);
- if (node != null)
- return findNode(node, nextLevel(path));
- return null;
+ private static SchemaNode findNodeInNotification(final NotificationDefinition ntf, final List<QName> path) {
+ if (path.isEmpty()) {
+ LOG.debug("Found notification {}", ntf);
+ return ntf;
+ }
+
+ LOG.trace("Looking for path {} in notification {}", path, ntf);
+ final QName current = path.get(0);
+ DataSchemaNode node = ntf.getDataChildByName(current);
+ if (node == null) {
+ LOG.debug("No node matching {} found in notification {}", current, ntf);
+ return null;
+ }
+
+ return findNode(node, nextLevel(path));
}
- private static SchemaNode findNode(ChoiceNode parent, List<QName> path) {
- if (path.isEmpty())
+ private static SchemaNode findNode(final ChoiceNode parent, final List<QName> path) {
+ if (path.isEmpty()) {
return parent;
+ }
QName current = path.get(0);
ChoiceCaseNode node = parent.getCaseNodeByName(current);
- if (node != null)
+ if (node != null) {
return findNodeInCase(node, nextLevel(path));
+ }
return null;
}
- private static SchemaNode findNode(ContainerSchemaNode parent, List<QName> path) {
- if (path.isEmpty())
+ private static SchemaNode findNode(final ContainerSchemaNode parent, final List<QName> path) {
+ if (path.isEmpty()) {
return parent;
- QName current = path.get(0);
- DataSchemaNode node = parent.getDataChildByName(current);
- if (node != null)
- return findNode(node, nextLevel(path));
- return null;
+ }
+
+ final QName current = path.get(0);
+ final DataSchemaNode node = parent.getDataChildByName(current);
+ if (node == null) {
+ LOG.debug("Failed to find {} in parent {}", path, parent);
+ return null;
+ }
+
+ return findNode(node, nextLevel(path));
}
- private static SchemaNode findNode(ListSchemaNode parent, List<QName> path) {
- if (path.isEmpty())
+ private static SchemaNode findNode(final ListSchemaNode parent, final List<QName> path) {
+ if (path.isEmpty()) {
return parent;
+ }
+
QName current = path.get(0);
DataSchemaNode node = parent.getDataChildByName(current);
- if (node != null)
- return findNode(node, nextLevel(path));
- return null;
+ if (node == null) {
+ LOG.debug("Failed to find {} in parent {}", path, parent);
+ return null;
+ }
+ return findNode(node, nextLevel(path));
}
- private static SchemaNode findNode(DataSchemaNode parent, List<QName> path) {
- SchemaNode result = null;
- if (path.isEmpty()) {
- result = parent;
- } else {
+ private static SchemaNode findNode(final DataSchemaNode parent, final List<QName> path) {
+ final SchemaNode node;
+ if (!path.isEmpty()) {
if (parent instanceof ContainerSchemaNode) {
- result = findNode((ContainerSchemaNode) parent, path);
+ node = findNode((ContainerSchemaNode) parent, path);
} else if (parent instanceof ListSchemaNode) {
- result = findNode((ListSchemaNode) parent, path);
+ node = findNode((ListSchemaNode) parent, path);
} else if (parent instanceof ChoiceNode) {
- result = findNode((ChoiceNode) parent, path);
+ node = findNode((ChoiceNode) parent, path);
} else {
- throw new IllegalArgumentException("Path nesting violation");
+ throw new IllegalArgumentException(
+ String.format("Path nesting violation in parent %s path %s", parent, path));
}
+ } else {
+ node = parent;
}
- return result;
+
+ if (node == null) {
+ LOG.debug("Failed to find {} in parent {}", path, parent);
+ return null;
+ }
+ return node;
}
- public static SchemaNode findNodeInCase(ChoiceCaseNode parent, List<QName> path) {
- if (path.isEmpty())
+ public static SchemaNode findNodeInCase(final ChoiceCaseNode parent, final List<QName> path) {
+ if (path.isEmpty()) {
return parent;
+ }
+
QName current = path.get(0);
DataSchemaNode node = parent.getDataChildByName(current);
- if (node != null)
- return findNode(node, nextLevel(path));
- return null;
+ if (node == null) {
+ LOG.debug("Failed to find {} in parent {}", path, parent);
+ return null;
+ }
+ return findNode(node, nextLevel(path));
}
- public static RpcDefinition getRpcByName(Module module, QName name) {
+ public static RpcDefinition getRpcByName(final Module module, final QName name) {
for (RpcDefinition rpc : module.getRpcs()) {
if (rpc.getQName().equals(name)) {
return rpc;
return null;
}
- private static List<QName> nextLevel(List<QName> path) {
+ private static List<QName> nextLevel(final List<QName> path) {
return path.subList(1, path.size());
}
- public static NotificationDefinition getNotificationByName(Module module, QName name) {
+ public static NotificationDefinition getNotificationByName(final Module module, final QName name) {
for (NotificationDefinition notification : module.getNotifications()) {
if (notification.getQName().equals(name)) {
return notification;
return null;
}
- public static GroupingDefinition getGroupingByName(Module module, QName name) {
+ public static GroupingDefinition getGroupingByName(final Module module, final QName name) {
for (GroupingDefinition grouping : module.getGroupings()) {
if (grouping.getQName().equals(name)) {
return grouping;
* @param node
* @return
*/
- public static DataSchemaNode findOriginal(DataSchemaNode node, SchemaContext ctx) {
+ public static DataSchemaNode findOriginal(final DataSchemaNode node, final SchemaContext ctx) {
DataSchemaNode result = findCorrectTargetFromGrouping(node, ctx);
if (result == null) {
result = findCorrectTargetFromAugment(node, ctx);
return result;
}
- private static DataSchemaNode findCorrectTargetFromGrouping(DataSchemaNode node, SchemaContext ctx) {
+ private static DataSchemaNode findCorrectTargetFromGrouping(final DataSchemaNode node, final SchemaContext ctx) {
if (node.getPath().getPath().size() == 1) {
// uses is under module statement
Module m = findParentModule(ctx, node);
for (UsesNode u : m.getUses()) {
SchemaNode targetGrouping = findNodeInSchemaContext(ctx, u.getGroupingPath().getPath());
if (!(targetGrouping instanceof GroupingDefinition)) {
- throw new IllegalArgumentException("Failed to generate code for augment in " + u);
+ throw new IllegalArgumentException(String.format("Failed to generate code for augment in %s", u));
}
GroupingDefinition gr = (GroupingDefinition) targetGrouping;
result = gr.getDataChildByName(node.getQName().getLocalName());
}
}
- private static DataSchemaNode findCorrectTargetFromAugment(DataSchemaNode node, SchemaContext ctx) {
+ private static DataSchemaNode findCorrectTargetFromAugment(final DataSchemaNode node, final SchemaContext ctx) {
if (!node.isAugmenting()) {
return null;
}
}
}
- private static DataSchemaNode getResultFromUses(UsesNode u, String currentName, SchemaContext ctx) {
+ private static DataSchemaNode getResultFromUses(final UsesNode u, final String currentName, final SchemaContext ctx) {
SchemaNode targetGrouping = findNodeInSchemaContext(ctx, u.getGroupingPath().getPath());
- if (!(targetGrouping instanceof GroupingDefinition)) {
- throw new IllegalArgumentException("Failed to generate code for augment in " + u);
- }
+
+ Preconditions.checkArgument(targetGrouping instanceof GroupingDefinition,
+ "Failed to generate code for augment in %s", u);
GroupingDefinition gr = (GroupingDefinition) targetGrouping;
return gr.getDataChildByName(currentName);
}
- private static Module getParentModule(SchemaNode node, SchemaContext ctx) {
+ private static Module getParentModule(final SchemaNode node, final SchemaContext ctx) {
QName qname = node.getPath().getPath().get(0);
URI namespace = qname.getNamespace();
Date revision = qname.getRevision();
return ctx.findModuleByNamespaceAndRevision(namespace, revision);
}
- private static DataSchemaNode getTargetNode(List<QName> tmpPath, DataSchemaNode node, SchemaContext ctx) {
+ private static DataSchemaNode getTargetNode(final List<QName> tmpPath, final DataSchemaNode node, final SchemaContext ctx) {
DataSchemaNode result = node;
if (tmpPath.size() == 1) {
if (result != null && result.isAddedByUses()) {
}
}
- private static AugmentationSchema findNodeInAugment(Collection<AugmentationSchema> augments, QName name) {
+ private static AugmentationSchema findNodeInAugment(final Collection<AugmentationSchema> augments, final QName name) {
for (AugmentationSchema augment : augments) {
DataSchemaNode node = augment.getDataChildByName(name);
if (node != null) {
return null;
}
- private static DataSchemaNode findCorrectTargetFromAugmentGrouping(DataSchemaNode node,
- AugmentationSchema parentNode, List<SchemaNode> dataTree, SchemaContext ctx) {
+ private static DataSchemaNode findCorrectTargetFromAugmentGrouping(final DataSchemaNode node,
+ final AugmentationSchema parentNode, final List<SchemaNode> dataTree, final SchemaContext ctx) {
DataSchemaNode result = null;
QName currentName = node.getQName();
* XPath String
* @return return a list of QName
*/
- private static List<QName> xpathToQNamePath(SchemaContext context, Module parentModule, String xpath) {
+ private static List<QName> xpathToQNamePath(final SchemaContext context, final Module parentModule, final String xpath) {
Preconditions.checkArgument(context != null, "Schema Context reference cannot be NULL");
Preconditions.checkArgument(parentModule != null, "Parent Module reference cannot be NULL");
Preconditions.checkArgument(xpath != null, "XPath string reference cannot be NULL");
* Prefixed Path Part string
* @return QName from prefixed Path Part String.
*/
- private static QName stringPathPartToQName(SchemaContext context, Module parentModule, String prefixedPathPart) {
+ private static QName stringPathPartToQName(final SchemaContext context, final Module parentModule, final String prefixedPathPart) {
Preconditions.checkArgument(context != null, "Schema Context reference cannot be NULL");
Preconditions.checkArgument(parentModule != null, "Parent Module reference cannot be NULL");
Preconditions.checkArgument(prefixedPathPart != null, "Prefixed Path Part cannot be NULL!");
if (prefixedPathPart.contains(":")) {
String[] prefixedName = prefixedPathPart.split(":");
Module module = resolveModuleForPrefix(context, parentModule, prefixedName[0]);
- if (module == null) {
- throw new IllegalArgumentException("Failed to resolve xpath: no module found for prefix "
- + prefixedName[0] + " in module " + parentModule.getName());
- } else {
- return new QName(module.getNamespace(), module.getRevision(), prefixedName[1]);
- }
+ Preconditions.checkArgument(module != null, "Failed to resolve xpath: no module found for prefix %s in module %s",
+ prefixedName[0], parentModule.getName());
+ return new QName(module.getNamespace(), module.getRevision(), prefixedName[1]);
} else {
return new QName(parentModule.getNamespace(), parentModule.getRevision(), prefixedPathPart);
}
* @return Module for given prefix in specified Schema Context if is
* present, otherwise returns <code>null</code>
*/
- private static Module resolveModuleForPrefix(SchemaContext context, Module module, String prefix) {
+ private static Module resolveModuleForPrefix(final SchemaContext context, final Module module, final String prefix) {
Preconditions.checkArgument(context != null, "Schema Context reference cannot be NULL");
Preconditions.checkArgument(module != null, "Module reference cannot be NULL");
Preconditions.checkArgument(prefix != null, "Prefix string cannot be NULL");
* Schema Path for Leafref
* @return list of QName
*/
- private static List<QName> resolveRelativeXPath(SchemaContext context, Module module,
- RevisionAwareXPath relativeXPath, SchemaNode leafrefParentNode) {
+ private static List<QName> resolveRelativeXPath(final SchemaContext context, final Module module,
+ final RevisionAwareXPath relativeXPath, final SchemaNode leafrefParentNode) {
Preconditions.checkArgument(context != null, "Schema Context reference cannot be NULL");
Preconditions.checkArgument(module != null, "Module reference cannot be NULL");
Preconditions.checkArgument(relativeXPath != null, "Non Conditional Revision Aware XPath cannot be NULL");