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);
}
}
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
private final CodecRegistry codecRegistry;
+ private final Map<Class<?>,Set<List<QName>>> augmentationAdapted = new WeakHashMap<>();
+
private final Map<Class<?>, Map<List<QName>, Class<?>>> classToPreviousAugment = Collections
.synchronizedMap(new WeakHashMap<Class<?>, Map<List<QName>, Class<?>>>());
}
Map<List<QName>, Class<?>> injectAugment = classToPreviousAugment.get(baType);
if (injectAugment != null) {
+ @SuppressWarnings("unchecked")
Class<? extends DataObject> augment = (Class<? extends DataObject>) injectAugment.get(scannedPath);
if (augment != null) {
baArgs.add(new Item(augment));
}
baArgs.add(baArg);
}
- InstanceIdentifier ret = InstanceIdentifier.create(baArgs);
+ InstanceIdentifier<?> ret = InstanceIdentifier.create(baArgs);
LOG.debug("DOM Instance Identifier {} deserialized to {}", input, ret);
return ret;
}
@Override
public InstanceIdentifier<? extends Object> deserialize(
final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier input,
- InstanceIdentifier<?> bindingIdentifier) {
+ final InstanceIdentifier<?> bindingIdentifier) {
return deserialize(input);
}
- private org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument _deserializePathArgument(
+ private InstanceIdentifier.PathArgument deserializeNodeIdentifier(
final NodeIdentifier argument, final List<QName> processedPath) {
+ @SuppressWarnings("rawtypes")
final Class cls = codecRegistry.getClassForPath(processedPath);
+ @SuppressWarnings("unchecked")
Item<DataObject> item = new Item<>(cls);
return item;
}
- private org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument _deserializePathArgument(
+ private InstanceIdentifier.PathArgument deserializeNodeIdentifierWithPrecicates(
final NodeIdentifierWithPredicates argument, final List<QName> processedPath) {
+ @SuppressWarnings("rawtypes")
final Class type = codecRegistry.getClassForPath(processedPath);
+ @SuppressWarnings({ "unchecked", "rawtypes" })
final IdentifierCodec codec = codecRegistry
.<Identifiable<? extends Object>> getIdentifierCodecForIdentifiable(type);
CompositeNode _compositeNode = this.toCompositeNode(argument);
+ @SuppressWarnings("unchecked")
ValueWithQName<CompositeNode> deserialize = codec.deserialize(_compositeNode);
Object value = null;
if (deserialize != null) {
@Override
public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier serialize(final InstanceIdentifier<?> input) {
Class<?> previousAugmentation = null;
- List<InstanceIdentifier.PathArgument> pathArgs = input.getPath();
+ Iterable<InstanceIdentifier.PathArgument> pathArgs = input.getPathArguments();
QName previousQName = null;
- List<PathArgument> components = new ArrayList<>(pathArgs.size());
- List<QName> qnamePath = new ArrayList<>(pathArgs.size());
+ List<PathArgument> components = new ArrayList<>();
+ List<QName> qnamePath = new ArrayList<>();
for (InstanceIdentifier.PathArgument baArg : pathArgs) {
-
if (!Augmentation.class.isAssignableFrom(baArg.getType())) {
- org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument biArg = serializePathArgument(
- baArg, previousQName);
- previousQName = biArg.getNodeType();
+ PathArgument biArg = serializePathArgumentAndUpdateMapping(qnamePath, baArg, previousQName,previousAugmentation);
components.add(biArg);
qnamePath.add(biArg.getNodeType());
- ImmutableList<QName> immutableList = ImmutableList.copyOf(qnamePath);
- codecRegistry.putPathToClass(immutableList, baArg.getType());
- if (previousAugmentation != null) {
- updateAugmentationInjection(baArg.getType(), immutableList, previousAugmentation);
- }
+ previousQName = biArg.getNodeType();
previousAugmentation = null;
} else {
previousQName = codecRegistry.getQNameForAugmentation(baArg.getType());
previousAugmentation = baArg.getType();
+ ensureAugmentation(qnamePath,previousQName,baArg.getType());
}
}
org.opendaylight.yangtools.yang.data.api.InstanceIdentifier ret = new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(
return ret;
}
+ private synchronized void ensureAugmentation(final List<QName> augPath, final QName augQName, final Class<? extends DataObject> type) {
+ Set<List<QName>> augPotential = augmentationAdapted.get(type);
+ if(augPotential == null) {
+ augPotential = new HashSet<>();
+ augmentationAdapted.put(type, augPotential);
+ }
+ ImmutableList<QName> augTargetPath = ImmutableList.copyOf(augPath);
+ if(augPotential.contains(augPath)) {
+ return;
+ }
+
+ for(Class<? extends DataObject> child : BindingReflections.getChildrenClasses(type)) {
+ Item<? extends DataObject> baArg = new Item<>(child);
+ PathArgument biArg = serializePathArgumentAndUpdateMapping(augPath, baArg, augQName,type);
+ }
+ augPotential.add(augTargetPath);
+ }
+
+
public Class<? extends Object> updateAugmentationInjection(final Class<? extends DataObject> class1,
- final ImmutableList<QName> list, final Class<?> augmentation) {
+ final List<QName> list, final Class<?> augmentation) {
if (classToPreviousAugment.get(class1) == null) {
classToPreviousAugment.put(class1, new ConcurrentHashMap<List<QName>, Class<?>>());
}
return classToPreviousAugment.get(class1).put(list, augmentation);
}
- private PathArgument _serializePathArgument(final Item<?> argument, final QName previousQname) {
+ private PathArgument serializeItem(final Item<?> argument, final QName previousQname) {
Class<?> type = argument.getType();
QName qname = BindingReflections.findQName(type);
if (previousQname == null || (BindingReflections.isAugmentationChild(argument.getType()))) {
return new NodeIdentifier(QName.create(previousQname, qname.getLocalName()));
}
- private PathArgument _serializePathArgument(final IdentifiableItem argument, final QName previousQname) {
+ private PathArgument serializeIdentifiableItem(final IdentifiableItem<?,?> argument, final QName previousQname) {
Map<QName, Object> predicates = new HashMap<>();
+ @SuppressWarnings("rawtypes")
Class type = argument.getType();
+ @SuppressWarnings("unchecked")
IdentifierCodec<? extends Object> keyCodec = codecRegistry.getIdentifierCodecForIdentifiable(type);
QName qname = BindingReflections.findQName(type);
if (previousQname != null && !(BindingReflections.isAugmentationChild(argument.getType()))) {
qname = QName.create(previousQname, qname.getLocalName());
}
+ @SuppressWarnings({ "rawtypes", "unchecked" })
ValueWithQName combinedInput = new ValueWithQName(previousQname, argument.getKey());
+ @SuppressWarnings("unchecked")
CompositeNode compositeOutput = keyCodec.serialize(combinedInput);
for (Node<?> outputValue : compositeOutput.getValue()) {
predicates.put(outputValue.getNodeType(), outputValue.getValue());
private org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument deserializePathArgument(
final PathArgument argument, final List<QName> processedPath) {
if (argument instanceof NodeIdentifier) {
- return _deserializePathArgument((NodeIdentifier) argument, processedPath);
+ return deserializeNodeIdentifier((NodeIdentifier) argument, processedPath);
} else if (argument instanceof NodeIdentifierWithPredicates) {
- return _deserializePathArgument((NodeIdentifierWithPredicates) argument, processedPath);
+ return deserializeNodeIdentifierWithPrecicates((NodeIdentifierWithPredicates) argument, processedPath);
} else {
throw new IllegalArgumentException("Unhandled parameter types: "
+ Arrays.<Object> asList(argument, processedPath).toString());
}
}
+ private PathArgument serializePathArgumentAndUpdateMapping(final List<QName> parentPath, final InstanceIdentifier.PathArgument baArg, final QName previousQName, final Class<?> previousAugmentation) {
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument biArg = serializePathArgument(baArg, previousQName);
+ List<QName> qnamePath = new ArrayList<>(parentPath);
+ qnamePath.add(biArg.getNodeType());
+ ImmutableList<QName> currentPath = ImmutableList.copyOf(qnamePath);
+ codecRegistry.putPathToClass(currentPath, baArg.getType());
+ if (previousAugmentation != null) {
+ updateAugmentationInjection(baArg.getType(), currentPath, previousAugmentation);
+ }
+ return biArg;
+ }
+
private PathArgument serializePathArgument(
- final org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument argument,
+ final InstanceIdentifier.PathArgument argument,
final QName previousQname) {
if (argument instanceof IdentifiableItem) {
- return _serializePathArgument((IdentifiableItem) argument, previousQname);
+ return serializeIdentifiableItem((IdentifiableItem<?,?>) argument, previousQname);
} else if (argument instanceof Item) {
- return _serializePathArgument((Item<?>) argument, previousQname);
+ return serializeItem((Item<?>) argument, previousQname);
} else {
throw new IllegalArgumentException("Unhandled parameter types: "
+ Arrays.<Object> asList(argument, previousQname).toString());
}
}
+
+
}
@SuppressWarnings("rawtypes")
private static final ConcurrentMap<Type, ChoiceCaseCodecImpl> typeToCaseCodecs = new ConcurrentHashMap<>();
- private static final Map<SchemaPath, GeneratedTypeBuilder> pathToType = new ConcurrentHashMap<>();
+ private static final Map<SchemaPath, Type> 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 BiMap<Type, AugmentationSchema> typeToAugment = HashBiMap
@SuppressWarnings("unchecked")
@Override
- public <T extends Augmentation<?>> AugmentationCodecWrapper<T> getCodecForAugmentation(final Class<T> object) {
+ public <T extends Augmentation<?>> AugmentationCodecWrapper<T> getCodecForAugmentation(final Class<T> augClass) {
AugmentationCodecWrapper<T> codec = null;
@SuppressWarnings("rawtypes")
- AugmentationCodecWrapper potentialCodec = augmentationCodecs.get(object);
+ AugmentationCodecWrapper potentialCodec = augmentationCodecs.get(augClass);
if (potentialCodec != null) {
codec = potentialCodec;
} else {
- lock.waitForSchema(object);
+ lock.waitForSchema(augClass);
Class<? extends BindingCodec<Map<QName, Object>, Object>> augmentRawCodec = generator
- .augmentationTransformerFor(object);
+ .augmentationTransformerFor(augClass);
BindingCodec<Map<QName, Object>, Object> rawCodec = newInstanceOf(augmentRawCodec);
- codec = new AugmentationCodecWrapper<T>(rawCodec, null, object);
- augmentationCodecs.put(object, codec);
+ codec = new AugmentationCodecWrapper<T>(rawCodec, augClass);
+ augmentationCodecs.put(augClass, 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(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;
}
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);
@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());
+ Preconditions.checkState(weakRef != null, "Could not find loaded class for path: %s and type: %s", path,
+ type.getFullyQualifiedName());
return weakRef.get();
}
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<QName> iterator = path.iterator();
while (iterator.hasNext()) {
QName arg = iterator.next();
LOG.error("Failed to instantiate codec {}", cls.getSimpleName(), e);
throw new IllegalStateException(String.format("Failed to instantiate codec %s", cls), e);
} catch (IllegalAccessException e) {
- LOG.debug("Run-time consistency issue: constructor for {} is not available. This indicates either a code generation bug or a misconfiguration of JVM.",
+ 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);
}
identity.getKey());
}
- synchronized(augmentableToAugmentations) {
+ synchronized (augmentableToAugmentations) {
augmentableToAugmentations.putAll(context.getAugmentableToAugmentations());
}
- synchronized(choiceToCases) {
+ synchronized (choiceToCases) {
choiceToCases.putAll(context.getChoiceToCases());
}
captureCases(context.getCases(), schemaContext);
}
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")
}
}
- public AugmentableDispatchCodec getAugmentableCodec(final Class<?> dataClass) {
+ public synchronized AugmentableDispatchCodec getAugmentableCodec(final Class<?> dataClass) {
AugmentableDispatchCodec ret = augmentableCodecs.get(dataClass);
if (ret != null) {
return ret;
return implementation;
}
- protected final void adaptForPath(final InstanceIdentifier<?> path) {
+ 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)
+ * 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);
+ Optional<DataNodeContainer> contextNode = BindingSchemaContextUtils.findDataNodeContainer(currentSchema,
+ path);
/**
- * If context node is present, this codec makes sense on provided location.
+ * 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.
+ * We adapt (turn on / off) possible implementations of
+ * child codecs (augmentations, cases) based on this
+ * location.
*
*
*/
+
adaptForPathImpl(path, contextNode.get());
- try {
+ try {
/**
- * We trigger serialization of instance identifier, to make sure instance identifier
- * codec is aware of combination of this path / augmentation / case
+ * 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);
+ 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);
+ LOG.debug("Context node (parent node) not found for {}", path);
}
}
}
}
- private static class PublicChoiceCodecImpl<T> implements ChoiceCodec<T>, Delegator<BindingCodec<Map<QName, Object>, Object>> {
+ private static class PublicChoiceCodecImpl<T> implements ChoiceCodec<T>,
+ Delegator<BindingCodec<Map<QName, Object>, Object>> {
private final BindingCodec<Map<QName, Object>, Object> delegate;
private class DispatchChoiceCodecImpl extends LocationAwareDispatchCodec<ChoiceCaseCodecImpl<?>> {
@Override
- public Object deserialize(final Object input, @SuppressWarnings("rawtypes") final InstanceIdentifier bindingIdentifier) {
+ public Object deserialize(final Object input,
+ @SuppressWarnings("rawtypes") final InstanceIdentifier bindingIdentifier) {
// TODO Auto-generated method stub
return null;
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
- private class AugmentableDispatchCodec extends LocationAwareDispatchCodec<AugmentationCodecWrapper> {
+ class AugmentableDispatchCodec extends LocationAwareDispatchCodec<AugmentationCodecWrapper> {
private final Class augmentableType;
.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
protected void tryToLoadImplementations() {
Type type = referencedType(augmentableType);
Collection<Type> potentialAugmentations;
- synchronized(augmentableToAugmentations) {
+ 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 coded for {}, reason: {}", type, e.toString());
+ LOG.warn("Failed to proactively generate augment code for {}", type, e);
}
}
-
}
@Override
- protected void adaptForPathImpl(final InstanceIdentifier<?> path, final DataNodeContainer ctxNode) {
+ protected void adaptForPathImpl(final InstanceIdentifier<?> augTarget, final DataNodeContainer ctxNode) {
if (ctxNode instanceof AugmentationTarget) {
Set<AugmentationSchema> availableAugmentations = ((AugmentationTarget) ctxNode)
.getAvailableAugmentations();
if (!availableAugmentations.isEmpty()) {
- updateAugmentationMapping(path,availableAugmentations);
+ updateAugmentationMapping(augTarget, availableAugmentations);
}
-
}
}
- private void updateAugmentationMapping(final InstanceIdentifier<?> path, final Set<AugmentationSchema> 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:
+ * <ol>
+ * <li> scan of available (valid) augmentations for
+ * current location
+ * <li>lookup for Java classes derived from this augmentations
+ * <li>generation of missing codecs
+ * <li>updating Augmentation codecs to work with new location
+ * <li>updating Instance Identifier to work with new location
+ *
+ */
+ private void updateAugmentationMapping(final InstanceIdentifier<?> augTarget,
+ final Set<AugmentationSchema> availableAugmentations) {
for (AugmentationSchema aug : availableAugmentations) {
Type potentialType = getTypeForAugmentation(aug);
if (potentialType != null) {
Optional<AugmentationCodecWrapper> potentialImpl = tryToLoadImplementation(potentialType);
if (potentialImpl.isPresent()) {
- potentialImpl.get().addApplicableFor(path,aug);
+ 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 {
- LOG.warn("Could not find generated type for augmentation {} with childs {}.",aug,aug.getChildNodes());
+ // 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());
+ }
}
}
- availableAugmentations.toString();
}
+
+
private Type getTypeForAugmentation(final AugmentationSchema aug) {
Optional<AugmentationSchema> currentAug = Optional.of(aug);
- while(currentAug.isPresent()) {
+ while (currentAug.isPresent()) {
Type potentialType = typeToAugment.inverse().get(currentAug.get());
- if(potentialType != null) {
+ if (potentialType != null) {
return potentialType;
}
currentAug = currentAug.get().getOriginalDefinition();
private final BindingCodec delegate;
private final QName augmentationQName;
- private final Multimap<InstanceIdentifier<?>,QName> validAugmentationTargets;
+ private final Multimap<InstanceIdentifier<?>, QName> validAugmentationTargets;
private final Class<?> augmentationType;
- public AugmentationCodecWrapper(final BindingCodec<Map<QName, Object>, Object> rawCodec,
- final InstanceIdentifier<?> targetId, final Class<?> dataType) {
+ public AugmentationCodecWrapper(final BindingCodec<Map<QName, Object>, Object> rawCodec, final Class<?> dataType) {
this.delegate = rawCodec;
this.augmentationType = dataType;
this.augmentationQName = BindingReflections.findQName(rawCodec.getClass());
- this.validAugmentationTargets = Multimaps.synchronizedSetMultimap(HashMultimap.<InstanceIdentifier<?>,QName>create());
+ this.validAugmentationTargets = Multimaps.synchronizedSetMultimap(HashMultimap
+ .<InstanceIdentifier<?>, QName> create());
}
public void addApplicableFor(final InstanceIdentifier<?> path, final AugmentationSchema aug) {
- for(DataSchemaNode child : aug.getChildNodes()) {
- validAugmentationTargets.put(path,child.getQName());
+ for (DataSchemaNode child : aug.getChildNodes()) {
+ validAugmentationTargets.put(path, child.getQName());
}
}
}
@Override
- public Object deserialize(final Object input,final InstanceIdentifier bindingIdentifier) {
+ public Object deserialize(final Object input, final InstanceIdentifier bindingIdentifier) {
Type type = qnamesToIdentityMap.get(input);
if (type == null) {
return null;
*/
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);
private final List<GeneratedProperty> properties;
private final boolean isAbstract;
- public AbstractGeneratedType(AbstractGeneratedTypeBuilder<?> builder) {
+ public AbstractGeneratedType(final AbstractGeneratedTypeBuilder<?> builder) {
super(builder.getPackageName(), builder.getName());
this.parent = builder.getParent();
this.comment = builder.getComment();
this.annotations = toUnmodifiableAnnotations(builder.getAnnotations());
- this.implementsTypes = Collections.unmodifiableList(builder.getImplementsTypes());
- this.constants = Collections.unmodifiableList(builder.getConstants());
+ this.implementsTypes = makeUnmodifiable(builder.getImplementsTypes());
+ this.constants = makeUnmodifiable(builder.getConstants());
this.enumerations = toUnmodifiableEnumerations(builder.getEnumerations());
this.methodSignatures = toUnmodifiableMethods(builder.getMethodDefinitions());
this.enclosedTypes = toUnmodifiableEnclosedTypes(builder.getEnclosedTypes(),
this.parent = parent;
this.comment = comment;
this.annotations = toUnmodifiableAnnotations(annotationBuilders);
- this.implementsTypes = Collections.unmodifiableList(implementsTypes);
- this.constants = Collections.unmodifiableList(constants);
+ this.implementsTypes = makeUnmodifiable(implementsTypes);
+ this.constants = makeUnmodifiable(constants);
this.enumerations = toUnmodifiableEnumerations(enumBuilders);
this.methodSignatures = toUnmodifiableMethods(methodBuilders);
this.enclosedTypes = toUnmodifiableEnclosedTypes(enclosedGenTypeBuilders, enclosedGenTOBuilders);
this.properties = toUnmodifiableProperties(propertyBuilders);
this.isAbstract = isAbstract;
+ }
+ protected static final <T> List<T> makeUnmodifiable(final List<T> list) {
+ switch (list.size()) {
+ case 0:
+ return Collections.emptyList();
+ case 1:
+ return Collections.singletonList(list.get(0));
+ default:
+ return Collections.unmodifiableList(list);
+ }
}
- private List<GeneratedType> toUnmodifiableEnclosedTypes(final List<GeneratedTypeBuilder> enclosedGenTypeBuilders,
+ private static List<GeneratedType> toUnmodifiableEnclosedTypes(final List<GeneratedTypeBuilder> enclosedGenTypeBuilders,
final List<GeneratedTOBuilder> enclosedGenTOBuilders) {
- final List<GeneratedType> enclosedTypesList = new ArrayList<>();
+ final ArrayList<GeneratedType> enclosedTypesList = new ArrayList<>(enclosedGenTypeBuilders.size() + enclosedGenTOBuilders.size());
for (final GeneratedTypeBuilder builder : enclosedGenTypeBuilders) {
if (builder != null) {
enclosedTypesList.add(builder.toInstance());
enclosedTypesList.add(builder.toInstance());
}
}
- return enclosedTypesList;
+
+ return makeUnmodifiable(enclosedTypesList);
}
- protected final List<AnnotationType> toUnmodifiableAnnotations(final List<AnnotationTypeBuilder> annotationBuilders) {
- final List<AnnotationType> annotationList = new ArrayList<>();
+ protected static final List<AnnotationType> toUnmodifiableAnnotations(final List<AnnotationTypeBuilder> annotationBuilders) {
+ final List<AnnotationType> annotationList = new ArrayList<>(annotationBuilders.size());
for (final AnnotationTypeBuilder builder : annotationBuilders) {
annotationList.add(builder.toInstance());
}
- return Collections.unmodifiableList(annotationList);
+ return makeUnmodifiable(annotationList);
}
- protected final List<MethodSignature> toUnmodifiableMethods(List<MethodSignatureBuilder> methodBuilders) {
- final List<MethodSignature> methods = new ArrayList<>();
+ protected final List<MethodSignature> toUnmodifiableMethods(final List<MethodSignatureBuilder> methodBuilders) {
+ final List<MethodSignature> methods = new ArrayList<>(methodBuilders.size());
for (final MethodSignatureBuilder methodBuilder : methodBuilders) {
methods.add(methodBuilder.toInstance(this));
}
- return Collections.unmodifiableList(methods);
+ return makeUnmodifiable(methods);
}
- protected final List<Enumeration> toUnmodifiableEnumerations(List<EnumBuilder> enumBuilders) {
- final List<Enumeration> enums = new ArrayList<>();
+ protected final List<Enumeration> toUnmodifiableEnumerations(final List<EnumBuilder> enumBuilders) {
+ final List<Enumeration> enums = new ArrayList<>(enumBuilders.size());
for (final EnumBuilder enumBuilder : enumBuilders) {
enums.add(enumBuilder.toInstance(this));
}
- return Collections.unmodifiableList(enums);
+ return makeUnmodifiable(enums);
}
- protected final List<GeneratedProperty> toUnmodifiableProperties(List<GeneratedPropertyBuilder> methodBuilders) {
- final List<GeneratedProperty> methods = new ArrayList<>();
+ protected final List<GeneratedProperty> toUnmodifiableProperties(final List<GeneratedPropertyBuilder> methodBuilders) {
+ final List<GeneratedProperty> methods = new ArrayList<>(methodBuilders.size());
for (final GeneratedPropertyBuilder methodBuilder : methodBuilders) {
methods.add(methodBuilder.toInstance(this));
}
- return Collections.unmodifiableList(methods);
+ return makeUnmodifiable(methods);
}
@Override
protected abstract T thisInstance();
@Override
- public GeneratedTOBuilder addEnclosingTransferObject(String name) {
+ public GeneratedTOBuilder addEnclosingTransferObject(final String name) {
if (name == null) {
throw new IllegalArgumentException("Name for Enclosing Generated Transfer Object cannot be null!");
}
}
@Override
- public T addComment(String comment) {
+ public T addComment(final String comment) {
this.comment = comment;
return thisInstance();
}
}
@Override
- public T setAbstract(boolean isAbstract) {
+ public T setAbstract(final boolean isAbstract) {
this.isAbstract = isAbstract;
return thisInstance();
}
@Override
- public T addImplementsType(Type genType) {
+ public T addImplementsType(final Type genType) {
if (genType == null) {
throw new IllegalArgumentException("Type cannot be null");
}
}
@Override
- public Constant addConstant(Type type, String name, Object value) {
+ public Constant addConstant(final Type type, final String name, final Object value) {
if (type == null) {
throw new IllegalArgumentException("Returning Type for Constant cannot be null!");
}
}
@Override
- public EnumBuilder addEnumeration(String name) {
+ public EnumBuilder addEnumeration(final String name) {
if (name == null) {
throw new IllegalArgumentException("Name of enumeration cannot be null!");
}
}
@Override
- public MethodSignatureBuilder addMethod(String name) {
+ public MethodSignatureBuilder addMethod(final String name) {
if (name == null) {
throw new IllegalArgumentException("Name of method cannot be null!");
}
}
@Override
- public boolean containsMethod(String name) {
+ public boolean containsMethod(final String name) {
if (name == null) {
throw new IllegalArgumentException("Parameter name can't be null");
}
}
@Override
- public GeneratedPropertyBuilder addProperty(String name) {
+ public GeneratedPropertyBuilder addProperty(final String name) {
final GeneratedPropertyBuilder builder = new GeneratedPropertyBuilderImpl(name);
builder.setAccessModifier(AccessModifier.PUBLIC);
properties.add(builder);
}
@Override
- public boolean containsProperty(String name) {
+ public boolean containsProperty(final String name) {
if (name == null) {
throw new IllegalArgumentException("Parameter name can't be null");
}
}
@Override
- public boolean equals(Object obj) {
+ public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (getClass() != obj.getClass()) {
return false;
}
- AbstractGeneratedTypeBuilder<T> other = (AbstractGeneratedTypeBuilder<T>) obj;
+ AbstractGeneratedTypeBuilder<?> other = (AbstractGeneratedTypeBuilder<?>) obj;
if (getName() == null) {
if (other.getName() != null) {
return false;
public AbstractTypeMember(final Type definingType, final String name, final List<AnnotationType> annotations,
final String comment, final AccessModifier accessModifier, final Type returnType,
- boolean isFinal, boolean isStatic) {
+ final boolean isFinal, final boolean isStatic) {
super();
this.definingType = definingType;
this.name = name;
- this.annotations = Collections.unmodifiableList(annotations);
+ this.annotations = annotations.isEmpty() ? Collections.<AnnotationType>emptyList() : Collections.unmodifiableList(annotations);
this.comment = comment;
this.accessModifier = accessModifier;
this.returnType = returnType;
}
@Override
- public boolean equals(Object obj) {
+ public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
GeneratedTOBuilder {
private GeneratedTransferObject extendsType;
- private final List<GeneratedPropertyBuilder> equalsProperties = new ArrayList<>();
- private final List<GeneratedPropertyBuilder> hashProperties = new ArrayList<>();
- private final List<GeneratedPropertyBuilder> toStringProperties = new ArrayList<>();
+ private final ArrayList<GeneratedPropertyBuilder> equalsProperties = new ArrayList<>();
+ private final ArrayList<GeneratedPropertyBuilder> hashProperties = new ArrayList<>();
+ private final ArrayList<GeneratedPropertyBuilder> toStringProperties = new ArrayList<>();
private boolean isTypedef = false;
private boolean isUnionType = false;
private boolean isUnionTypeBuilder = false;
private Restrictions restrictions;
private GeneratedPropertyBuilder SUID;
- public GeneratedTOBuilderImpl(String packageName, String name) {
+ public GeneratedTOBuilderImpl(final String packageName, final String name) {
super(packageName, name);
setAbstract(false);
}
* @return <code>new</code> instance of Method Signature Builder.
*/
@Override
- public MethodSignatureBuilder addMethod(String name) {
+ public MethodSignatureBuilder addMethod(final String name) {
final MethodSignatureBuilder builder = super.addMethod(name);
builder.setAbstract(false);
return builder;
}
@Override
- public GeneratedTOBuilder addEqualsIdentity(GeneratedPropertyBuilder property) {
+ public GeneratedTOBuilder addEqualsIdentity(final GeneratedPropertyBuilder property) {
equalsProperties.add(property);
return this;
}
@Override
- public GeneratedTOBuilder addHashIdentity(GeneratedPropertyBuilder property) {
+ public GeneratedTOBuilder addHashIdentity(final GeneratedPropertyBuilder property) {
hashProperties.add(property);
return this;
}
@Override
- public GeneratedTOBuilder addToStringProperty(GeneratedPropertyBuilder property) {
+ public GeneratedTOBuilder addToStringProperty(final GeneratedPropertyBuilder property) {
toStringProperties.add(property);
return this;
}
}
@Override
- public void setRestrictions(Restrictions restrictions) {
+ public void setRestrictions(final Restrictions restrictions) {
this.restrictions = restrictions;
}
@Override
- public void setSUID(GeneratedPropertyBuilder suid) {
+ public void setSUID(final GeneratedPropertyBuilder suid) {
this.SUID = suid;
}
@Override
public GeneratedTransferObject toInstance() {
+ // FIXME: can we compact the arrays now? It needs to be thread-safe, though
return new GeneratedTransferObjectImpl(this);
}
}
@Override
- public void setTypedef(boolean isTypedef) {
+ public void setTypedef(final boolean isTypedef) {
this.isTypedef = isTypedef;
}
@Override
- public void setIsUnion(boolean isUnion) {
+ public void setIsUnion(final boolean isUnion) {
this.isUnionType = isUnion;
}
@Override
- public void setIsUnionBuilder(boolean isUnionTypeBuilder) {
+ public void setIsUnionBuilder(final boolean isUnionTypeBuilder) {
this.isUnionTypeBuilder = isUnionTypeBuilder;
}
private final Restrictions restrictions;
private final GeneratedProperty SUID;
- public GeneratedTransferObjectImpl(GeneratedTOBuilderImpl builder) {
+ public GeneratedTransferObjectImpl(final GeneratedTOBuilderImpl builder) {
super(builder);
this.extendsType = builder.extendsType;
this.equalsProperties = toUnmodifiableProperties(builder.equalsProperties);
return builder.toString();
}
- public String serializeTypedef(Type type) {
+ public String serializeTypedef(final Type type) {
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
StringBuffer sb = new StringBuffer();
«generateFields(false)»
+ «generateAugmentField(true)»
+
«generateConstructorsFromIfcs(type)»
«generateMethodFieldsFrom(type)»
«generateFields(true)»
+ «generateAugmentField(false)»
+
«generateConstructor»
«generateGetters(true)»
/**
* Generate constructor with argument of given type.
*/
- def private generateConstructorFromIfc(Type impl) '''
+ def private Object generateConstructorFromIfc(Type impl) '''
«IF (impl instanceof GeneratedType)»
«val implType = impl as GeneratedType»
«ENDIF»
'''
- def private printConstructorPropertySetter(Type implementedIfc) '''
+ def private Object printConstructorPropertySetter(Type implementedIfc) '''
«IF (implementedIfc instanceof GeneratedType && !(implementedIfc instanceof GeneratedTransferObject))»
«val ifc = implementedIfc as GeneratedType»
«FOR getter : ifc.methodDefinitions»
private«IF _final» final«ENDIF» «f.returnType.importedName» «f.fieldName»;
«ENDFOR»
«ENDIF»
+ '''
+
+ def private generateAugmentField(boolean init) '''
«IF augmentField != null»
- private «Map.importedName»<Class<? extends «augmentField.returnType.importedName»>, «augmentField.returnType.importedName»> «augmentField.name» = new «HashMap.importedName»<>();
+ private final «Map.importedName»<Class<? extends «augmentField.returnType.importedName»>, «augmentField.returnType.importedName»> «augmentField.name»«IF init» = new «HashMap.importedName»<>()«ENDIF»;
«ENDIF»
'''
this.«field.fieldName» = builder.«field.getterMethodName»();
«ENDFOR»
«IF augmentField != null»
- this.«augmentField.name».putAll(builder.«augmentField.name»);
+ switch (builder.«augmentField.name».size()) {
+ case 0:
+ this.«augmentField.name» = «Collections.importedName».emptyMap();
+ break;
+ case 1:
+ final «Map.importedName».Entry<Class<? extends «augmentField.returnType.importedName»>, «augmentField.returnType.importedName»> e = builder.«augmentField.name».entrySet().iterator().next();
+ this.«augmentField.name» = «Collections.importedName».<Class<? extends «augmentField.returnType.importedName»>, «augmentField.returnType.importedName»>singletonMap(e.getKey(), e.getValue());
+ break;
+ default :
+ this.«augmentField.name» = new «HashMap.importedName»<>(builder.«augmentField.name»);
+ }
«ENDIF»
}
'''
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.LinkedList;
+import java.util.List;
import java.util.ServiceLoader;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
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;
.expireAfterAccess(EXPIRATION_TIME, TimeUnit.SECONDS) //
.build(new ClassToQNameLoader());
+
+ private BindingReflections() {
+ throw new UnsupportedOperationException("Utility class.");
+ }
+
/**
+ *
+ * Find augmentation target class from concrete Augmentation class
+ *
+ * This method uses first generic argument of
+ * implemented {@link Augmentation} interface.
*
* @param augmentation
* {@link Augmentation} subclass for which we want to determine
}
/**
+ * Find data hierarchy parent from concrete Data class
+ *
+ * This method uses first generic argument of
+ * implemented {@link ChildOf} interface.
*
* @param augmentation
* {@link Augmentation} subclass for which we want to determine
}
/**
+ * Find data hierarchy parent from concrete Data class
*
- * @param augmentation
+ * This method is shorthand which gets DataObject class by invoking
+ * {@link DataObject#getImplementedInterface()} and uses {@link #findHierarchicalParent(Class)}.
+ *
+ * @param childClass
* {@link Augmentation} subclass for which we want to determine
* augmentation target.
* @return Augmentation target - class which augmentation provides
* additional extensions.
*/
- public static Class<?> findHierarchicalParent(final DataObject childClass) {
- if (childClass instanceof ChildOf) {
- return ClassLoaderUtils.findFirstGenericArgument(childClass.getImplementedInterface(), ChildOf.class);
+ public static Class<?> findHierarchicalParent(final DataObject child) {
+ if (child instanceof ChildOf) {
+ return ClassLoaderUtils.findFirstGenericArgument(child.getImplementedInterface(), ChildOf.class);
}
return null;
}
* Returns a QName associated to supplied type
*
* @param dataType
- * @return QName associated to supplied dataType. If dataType is Augmentation
- * method does not return canonical QName, but QName with correct namespace
- * revision, but virtual local name, since augmentations do not have name.
+ * @return QName associated to supplied dataType. If dataType is
+ * Augmentation method does not return canonical QName, but QName
+ * with correct namespace revision, but virtual local name, since
+ * augmentations do not have name.
+ *
+ * May return null if QName is not present.
*/
public static final QName findQName(final Class<?> dataType) {
return classToQName.getUnchecked(dataType).orNull();
}
- private static class ClassToQNameLoader extends CacheLoader<Class<?>, Optional<QName>> {
-
- @Override
- public Optional<QName> load(final Class<?> key) throws Exception {
- try {
- Field field = key.getField(BindingMapping.QNAME_STATIC_FIELD_NAME);
- Object obj = field.get(null);
- if (obj instanceof QName) {
- return Optional.of((QName) obj);
- }
- } catch (NoSuchFieldException e) {
- if(Augmentation.class.isAssignableFrom(key)) {
- YangModuleInfo moduleInfo = getModuleInfo(key);
- return Optional.of(QName.create(moduleInfo.getNamespace(), moduleInfo.getRevision(), moduleInfo.getName()));
- }
-
- } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
- // NOOP
- }
- return Optional.absent();
- }
- }
-
+ /**
+ * Checks if method is RPC invocation
+ *
+ *
+ *
+ * @param possibleMethod Method to check
+ * @return true if method is RPC invocation, false otherwise.
+ */
public static boolean isRpcMethod(final Method possibleMethod) {
return possibleMethod != null && RpcService.class.isAssignableFrom(possibleMethod.getDeclaringClass())
&& Future.class.isAssignableFrom(possibleMethod.getReturnType())
&& possibleMethod.getParameterTypes().length <= 1;
}
+ /**
+ *
+ * Extracts Output class for RPC method
+ *
+ * @param targetMethod method to scan
+ * @return Optional.absent() if result type could not be get,
+ * or return type is Void.
+ */
@SuppressWarnings("rawtypes")
public static Optional<Class<?>> resolveRpcOutputClass(final Method targetMethod) {
checkState(isRpcMethod(targetMethod), "Supplied method is not Rpc invocation method");
return Optional.absent();
}
+ /**
+ *
+ * Extracts input class for RPC method
+ *
+ * @param targetMethod method to scan
+ * @return Optional.absent() if rpc has no input, Rpc input type otherwise.
+ */
@SuppressWarnings("unchecked")
public static Optional<Class<? extends DataContainer>> resolveRpcInputClass(final Method targetMethod) {
@SuppressWarnings("rawtypes")
return findQName(context);
}
+ /**
+ *
+ * Checks if class is child of augmentation.
+ *
+ *
+ * @param clazz
+ * @return
+ */
public static boolean isAugmentationChild(final Class<?> clazz) {
// FIXME: Current resolver could be still confused when
// child node was added by grouping
return !clazzModelPackage.equals(parentModelPackage);
}
+ /**
+ * Returns root package name for suplied package.
+ *
+ * @param pkg Package for which find model root package.
+ * @return Package of model root.
+ */
public static String getModelRootPackageName(final Package pkg) {
return getModelRootPackageName(pkg.getName());
}
+ /**
+ * Returns root package name for suplied package name.
+ *
+ * @param pkg Package for which find model root package.
+ * @return Package of model root.
+ */
public static String getModelRootPackageName(final String name) {
checkArgument(name != null, "Package name should not be null.");
checkArgument(name.startsWith(BindingMapping.PACKAGE_PREFIX), "Package name not starting with %s, is: %s",
BindingMapping.PACKAGE_PREFIX, name);
Matcher match = ROOT_PACKAGE_PATTERN.matcher(name);
- checkArgument(match.find(),"Package name '%s' does not match required pattern '%s'",name,ROOT_PACKAGE_PATTERN_STRING);
+ checkArgument(match.find(), "Package name '%s' does not match required pattern '%s'", name,
+ ROOT_PACKAGE_PATTERN_STRING);
return match.group(0);
}
+ /**
+ *
+ * Returns instance of {@link YangModuleInfo} of declaring model for specific class.
+ *
+ * @param cls
+ * @return Instance of {@link YangModuleInfo} associated with model, from which this class was derived.
+ * @throws Exception
+ */
public static YangModuleInfo getModuleInfo(final Class<?> cls) throws Exception {
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);
}
return packageName + "." + BindingMapping.MODULE_INFO_CLASS_NAME;
}
+ /**
+ *
+ * Check if supplied class is derived from YANG model.
+ *
+ * @param cls Class to check
+ * @return true if class is derived from YANG model.
+ */
public static boolean isBindingClass(final Class<?> cls) {
if (DataContainer.class.isAssignableFrom(cls) || Augmentation.class.isAssignableFrom(cls)) {
return true;
return (cls.getName().startsWith(BindingMapping.PACKAGE_PREFIX));
}
+ /**
+ *
+ * Checks if supplied method is callback for notifications.
+ *
+ * @param method
+ * @return true if method is notification callback.
+ */
public static boolean isNotificationCallback(final Method method) {
checkArgument(method != null);
if (method.getName().startsWith("on") && method.getParameterTypes().length == 1) {
return false;
}
+ /**
+ *
+ * Checks is supplied class is Notification.
+ *
+ * @param potentialNotification
+ * @return
+ */
public static boolean isNotification(final Class<?> potentialNotification) {
- checkArgument(potentialNotification != null);
+ checkArgument(potentialNotification != null,"potentialNotification must not be null.");
return Notification.class.isAssignableFrom(potentialNotification);
}
+ /**
+ *
+ * Loads {@link YangModuleInfo} infos available on current classloader.
+ *
+ * This method is shorthand for {@link #loadModuleInfos(ClassLoader)} with
+ * {@link Thread#getContextClassLoader()} for current thread.
+ *
+ * @return Set of {@link YangModuleInfo} available for current classloader.
+ */
public static ImmutableSet<YangModuleInfo> loadModuleInfos() {
return loadModuleInfos(Thread.currentThread().getContextClassLoader());
}
+ /**
+ *
+ * Loads {@link YangModuleInfo} infos available on supplied classloader.
+ *
+ * {@link YangModuleInfo} are discovered using {@link ServiceLoader}
+ * for {@link YangModelBindingProvider}. {@link YangModelBindingProvider}
+ * are simple classes which holds only pointers to actual instance
+ * {@link YangModuleInfo}.
+ *
+ * When {@link YangModuleInfo} is available, all dependencies are recursivelly collected
+ * into returning set by collecting results of {@link YangModuleInfo#getImportedModules()}.
+ *
+ *
+ * @param loader Classloader for which {@link YangModuleInfo} should be retrieved.
+ * @return Set of {@link YangModuleInfo} available for supplied classloader.
+ */
public static ImmutableSet<YangModuleInfo> loadModuleInfos(final ClassLoader loader) {
- Builder<YangModuleInfo> moduleInfoSet = ImmutableSet.<YangModuleInfo>builder();
- ServiceLoader<YangModelBindingProvider> serviceLoader = ServiceLoader.load(YangModelBindingProvider.class, loader);
- for(YangModelBindingProvider bindingProvider : serviceLoader) {
+ Builder<YangModuleInfo> moduleInfoSet = ImmutableSet.<YangModuleInfo> builder();
+ ServiceLoader<YangModelBindingProvider> serviceLoader = ServiceLoader.load(YangModelBindingProvider.class,
+ loader);
+ for (YangModelBindingProvider bindingProvider : serviceLoader) {
YangModuleInfo moduleInfo = bindingProvider.getModuleInfo();
- checkState(moduleInfo != null, "Module Info for %s is not available.",bindingProvider.getClass());
- collectYangModuleInfo(bindingProvider.getModuleInfo(),moduleInfoSet);
+ checkState(moduleInfo != null, "Module Info for %s is not available.", bindingProvider.getClass());
+ collectYangModuleInfo(bindingProvider.getModuleInfo(), moduleInfoSet);
}
- return moduleInfoSet.build();
+ return moduleInfoSet.build();
}
- private static void collectYangModuleInfo(final YangModuleInfo moduleInfo, final Builder<YangModuleInfo> moduleInfoSet) {
+ private static void collectYangModuleInfo(final YangModuleInfo moduleInfo,
+ final Builder<YangModuleInfo> moduleInfoSet) {
moduleInfoSet.add(moduleInfo);
- for(YangModuleInfo dependency : moduleInfo.getImportedModules()) {
+ for (YangModuleInfo dependency : moduleInfo.getImportedModules()) {
collectYangModuleInfo(dependency, moduleInfoSet);
}
}
+ /**
+ *
+ * Checks if supplied class represents RPC Input / RPC Output.
+ *
+ * @param targetType Class to be checked
+ * @return true if class represents RPC Input or RPC Output class.
+ */
public static boolean isRpcType(final Class<? extends DataObject> targetType) {
- return DataContainer.class.isAssignableFrom(targetType) //
+ return DataContainer.class.isAssignableFrom(targetType) //
&& !ChildOf.class.isAssignableFrom(targetType) //
&& !Notification.class.isAssignableFrom(targetType) //
&& (targetType.getName().endsWith("Input") || targetType.getName().endsWith("Output"));
}
+ /**
+ *
+ * Scans supplied class and returns an iterable of all data children classes.
+ *
+ * @param type YANG Modeled Entity derived from DataContainer
+ * @return Iterable of all data children, which have YANG modeled entity
+ */
+ @SuppressWarnings("unchecked")
+ public static Iterable<Class<? extends DataObject>> getChildrenClasses(final Class<? extends DataContainer> type) {
+ checkArgument(type != null, "Target type must not be null");
+ checkArgument(DataContainer.class.isAssignableFrom(type), "Supplied type must be derived from DataContainer");
+ List<Class<? extends DataObject>> ret = new LinkedList<>();
+ for (Method method : type.getMethods()) {
+ Optional<Class<? extends DataContainer>> entity = getYangModeledReturnType(method);
+ if (entity.isPresent()) {
+ ret.add((Class<? extends DataObject>) entity.get());
+ }
+ }
+ return ret;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static Optional<Class<? extends DataContainer>> getYangModeledReturnType(final Method method) {
+ if (method.getName().equals("getClass") || !method.getName().startsWith("get")
+ || method.getParameterTypes().length > 0) {
+ return Optional.absent();
+ }
+
+ @SuppressWarnings("rawtypes")
+ Class returnType = method.getReturnType();
+ if (DataContainer.class.isAssignableFrom(returnType)) {
+ return Optional.<Class<? extends DataContainer>> of(returnType);
+ } else if (List.class.isAssignableFrom(returnType)) {
+ try {
+ return ClassLoaderUtils.withClassLoader(method.getDeclaringClass().getClassLoader(),
+ new Callable<Optional<Class<? extends DataContainer>>>() {
+ @SuppressWarnings("rawtypes")
+ @Override
+ public Optional<Class<? extends DataContainer>> call() {
+ Type listResult = ClassLoaderUtils.getFirstGenericParameter(method
+ .getGenericReturnType());
+ if (listResult instanceof Class
+ && DataContainer.class.isAssignableFrom((Class) listResult)) {
+ return Optional.<Class<? extends DataContainer>> of((Class) listResult);
+ }
+ return Optional.absent();
+ }
+
+ });
+ } catch (Exception e) {
+ /*
+ *
+ * It is safe to log this this exception on debug, since
+ * this method should not fail. Only failures are possible if
+ * the runtime / backing.
+ *
+ */
+ LOG.debug("Unable to find YANG modeled return type for {}", method, e);
+ }
+ }
+ return Optional.absent();
+ }
+
+ private static class ClassToQNameLoader extends CacheLoader<Class<?>, Optional<QName>> {
+
+ @Override
+ public Optional<QName> load(final Class<?> key) throws Exception {
+ try {
+ Field field = key.getField(BindingMapping.QNAME_STATIC_FIELD_NAME);
+ Object obj = field.get(null);
+ if (obj instanceof QName) {
+ return Optional.of((QName) obj);
+ }
+ } catch (NoSuchFieldException e) {
+ if (Augmentation.class.isAssignableFrom(key)) {
+ YangModuleInfo moduleInfo = getModuleInfo(key);
+ return Optional.of(QName.create(moduleInfo.getNamespace(), moduleInfo.getRevision(),
+ moduleInfo.getName()));
+ }
+ } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
+ /*
+ *
+ * It is safe to log this this exception on debug, since
+ * this method should not fail. Only failures are possible if
+ * the runtime / backing.
+ *
+ */
+ LOG.debug("Unexpected exception during extracting QName for {}",key,e);
+ }
+ return Optional.absent();
+ }
+ }
}
--- /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");
+ }
+
+ /**
+ *
+ * Runs {@link Supplier} with provided {@link ClassLoader}.
+ *
+ * Invokes supplies function and makes sure that original {@link ClassLoader}
+ * is context {@link ClassLoader} after execution.
+ *
+ * @param cls {@link ClassLoader} to be used.
+ * @param function Function to be executed.
+ * @return Result of supplier invocation.
+ *
+ */
+ 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);
+ }
+ }
+
+ /**
+ *
+ * Runs {@link Callable} with provided {@link ClassLoader}.
+ *
+ * Invokes supplies function and makes sure that original {@link ClassLoader}
+ * is context {@link ClassLoader} after execution.
+ *
+ * @param cls {@link ClassLoader} to be used.
+ * @param function Function to be executed.
+ * @return Result of callable invocation.
+ *
+ */
+ 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);
+ }
+ }
+
+ /**
+ *
+ * Runs {@link Callable} with provided {@link ClassLoader} and Lock.
+ *
+ * Invokes supplies function after acquiring lock
+ * and makes sure that original {@link ClassLoader}
+ * is context {@link ClassLoader} and lock is unlocked
+ * after execution.
+ *
+ * @param cls {@link ClassLoader} to be used.
+ * @param function Function to be executed.
+ * @return Result of Callable invocation.
+ *
+ */
+ 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);
+ }
+
+ /**
+ *
+ * Loads class using this supplied classloader.
+ *
+ *
+ * @param cls
+ * @param name String name of class.
+ * @return
+ * @throws ClassNotFoundException
+ */
+ 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 org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
/**
* Simple path argument identifying a {@link ContainerNode} or {@link LeafNode} leaf
- * overal data tree.
- *
+ * overall data tree.
*/
- public static final class NodeIdentifier implements PathArgument {
-
- /**
- *
- */
+ public static final class NodeIdentifier implements PathArgument, Comparable<NodeIdentifier> {
private static final long serialVersionUID = -2255888212390871347L;
-
private final QName nodeType;
public NodeIdentifier(final QName node) {
- this.nodeType = node;
+ this.nodeType = Preconditions.checkNotNull(node);
}
@Override
@Override
public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((nodeType == null) ? 0 : nodeType.hashCode());
- return result;
+ return 31 + nodeType.hashCode();
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
- return true;
- }
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
- return false;
- }
- NodeIdentifier other = (NodeIdentifier) obj;
- if (nodeType == null) {
- if (other.nodeType != null) {
- return false;
- }
- } else if (!nodeType.equals(other.nodeType)) {
- return false;
- }
- return true;
+ return true;
+ }
+ if (!(obj instanceof NodeIdentifier)) {
+ return false;
+ }
+ final NodeIdentifier other = (NodeIdentifier) obj;
+ return nodeType.equals(other.nodeType);
}
@Override
public String toString() {
return nodeType.toString();
}
+
+ @Override
+ public int compareTo(final NodeIdentifier o) {
+ return nodeType.compareTo(o.nodeType);
+ }
}
/**
- *
* Composite path argument identifying a {@link MapEntryNode} leaf
- * overal data tree.
- *
+ * overall data tree.
*/
public static final class NodeIdentifierWithPredicates implements PathArgument {
-
- /**
- *
- */
private static final long serialVersionUID = -4787195606494761540L;
private final QName nodeType;
private final Map<QName, Object> keyValues;
public NodeIdentifierWithPredicates(final QName node, final Map<QName, Object> keyValues) {
- this.nodeType = node;
+ this.nodeType = Preconditions.checkNotNull(node);
this.keyValues = ImmutableMap.copyOf(keyValues);
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
- return true;
- }
+ return true;
+ }
if (obj == null) {
- return false;
- }
+ return false;
+ }
if (getClass() != obj.getClass()) {
- return false;
- }
+ return false;
+ }
NodeIdentifierWithPredicates other = (NodeIdentifierWithPredicates) obj;
if (keyValues == null) {
if (other.keyValues != null) {
- return false;
- }
+ return false;
+ }
} else if (!keyValues.equals(other.keyValues)) {
- return false;
- }
+ return false;
+ }
if (nodeType == null) {
if (other.nodeType != null) {
- return false;
- }
+ return false;
+ }
} else if (!nodeType.equals(other.nodeType)) {
- return false;
- }
+ return false;
+ }
return true;
}
/**
* Simple path argument identifying a {@link LeafSetEntryNode} leaf
- * overal data tree.
- *
+ * overall data tree.
*/
public static final class NodeWithValue implements PathArgument {
-
- /**
- *
- * Composite path argument identifying a {@link AugmentationNode} leaf
- * overal data tree.
- *
- */
private static final long serialVersionUID = -3637456085341738431L;
private final QName nodeType;
private final Object value;
public NodeWithValue(final QName node, final Object value) {
- this.nodeType = node;
+ this.nodeType = Preconditions.checkNotNull(node);
this.value = value;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
- return true;
- }
+ return true;
+ }
if (obj == null) {
- return false;
- }
+ return false;
+ }
if (getClass() != obj.getClass()) {
- return false;
- }
+ return false;
+ }
NodeWithValue other = (NodeWithValue) obj;
if (value == null) {
if (other.value != null) {
- return false;
- }
+ return false;
+ }
} else if (!value.equals(other.value)) {
- return false;
- }
+ return false;
+ }
if (nodeType == null) {
if (other.nodeType != null) {
- return false;
- }
+ return false;
+ }
} else if (!nodeType.equals(other.nodeType)) {
- return false;
- }
+ return false;
+ }
return true;
}
}
-
+ /**
+ * Composite path argument identifying a {@link AugmentationNode} leaf
+ * overall data tree.
+ */
public static final class AugmentationIdentifier implements PathArgument {
-
private static final long serialVersionUID = -8122335594681936939L;
private final ImmutableSet<QName> childNames;
@Override
public boolean equals(final Object o) {
if (this == o) {
- return true;
- }
+ return true;
+ }
if (!(o instanceof AugmentationIdentifier)) {
- return false;
- }
+ return false;
+ }
AugmentationIdentifier that = (AugmentationIdentifier) o;
if (!childNames.equals(that.childNames)) {
- return false;
- }
+ return false;
+ }
return true;
}
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");