package org.opendaylight.controller.config.manager.impl.dependencyresolver;
import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.IdentityAttributeRef;
import org.opendaylight.controller.config.api.JmxAttribute;
import org.opendaylight.controller.config.api.JmxAttributeValidationException;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.config.manager.impl.TransactionStatus;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
+import org.opendaylight.yangtools.yang.data.impl.codec.IdentityCodec;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import javax.annotation.concurrent.GuardedBy;
import javax.management.ObjectName;
* during validation. Tracks dependencies for ordering purposes.
*/
final class DependencyResolverImpl implements DependencyResolver,
- Comparable<DependencyResolverImpl> {
+ Comparable<DependencyResolverImpl> {
+ private static final Logger logger = LoggerFactory.getLogger(DependencyResolverImpl.class);
+
private final ModulesHolder modulesHolder;
private final ModuleIdentifier name;
private final TransactionStatus transactionStatus;
@GuardedBy("this")
private final Set<ModuleIdentifier> dependencies = new HashSet<>();
private final ServiceReferenceReadableRegistry readableRegistry;
+ private final CodecRegistry codecRegistry;
DependencyResolverImpl(ModuleIdentifier currentModule,
- TransactionStatus transactionStatus, ModulesHolder modulesHolder,
- ServiceReferenceReadableRegistry readableRegistry) {
-
+ TransactionStatus transactionStatus, ModulesHolder modulesHolder,
+ ServiceReferenceReadableRegistry readableRegistry, CodecRegistry codecRegistry) {
+ this.codecRegistry = codecRegistry;
this.name = currentModule;
this.transactionStatus = transactionStatus;
this.modulesHolder = modulesHolder;
throw new NullPointerException(
"Parameter 'expectedServiceInterface' is null");
}
- if (jmxAttribute == null)
+ if (jmxAttribute == null) {
throw new NullPointerException("Parameter 'jmxAttribute' is null");
+ }
JmxAttributeValidationException.checkNotNull(dependentReadOnlyON,
- "is null, " + "expected dependency implementing "
+ "is null, expected dependency implementing "
+ expectedServiceInterface, jmxAttribute);
-
// check that objectName belongs to this transaction - this should be
// stripped
// in DynamicWritableWrapper
}
}
- // transalate from serviceref to module ON
+ // translate from serviceref to module ON
private ObjectName translateServiceRefIfPossible(ObjectName dependentReadOnlyON) {
if (ObjectNameUtil.isServiceReference(dependentReadOnlyON)) {
String serviceQName = ObjectNameUtil.getServiceQName(dependentReadOnlyON);
//TODO: check for cycles
@Override
public <T> T resolveInstance(Class<T> expectedType, ObjectName dependentReadOnlyON,
- JmxAttribute jmxAttribute) {
+ JmxAttribute jmxAttribute) {
if (expectedType == null || dependentReadOnlyON == null || jmxAttribute == null) {
throw new IllegalArgumentException(format(
- "Null parameters not allowed, got {} {} {}", expectedType,
+ "Null parameters not allowed, got %s %s %s", expectedType,
dependentReadOnlyON, jmxAttribute));
}
dependentReadOnlyON = translateServiceRefIfPossible(dependentReadOnlyON);
throw new JmxAttributeValidationException(message, jmxAttribute);
}
try {
- T result = expectedType.cast(instance);
- return result;
+ return expectedType.cast(instance);
} catch (ClassCastException e) {
String message = format(
"Instance cannot be cast to expected type. Instance class is %s , "
}
}
+ @Override
+ public <T extends BaseIdentity> Class<? extends T> resolveIdentity(IdentityAttributeRef identityRef, Class<T> expectedBaseClass) {
+ final QName qName = QName.create(identityRef.getqNameOfIdentity());
+ IdentityCodec<?> identityCodec = codecRegistry.getIdentityCodec();
+ Class<? extends BaseIdentity> deserialized = identityCodec.deserialize(qName);
+ if (deserialized == null) {
+ throw new IllegalStateException("Unable to retrieve identity class for " + qName + ", null response from "
+ + codecRegistry);
+ }
+ if (expectedBaseClass.isAssignableFrom(deserialized)) {
+ return (Class<T>) deserialized;
+ } else {
+ logger.error("Cannot resolve class of identity {} : deserialized class {} is not a subclass of {}.",
+ identityRef, deserialized, expectedBaseClass);
+ throw new IllegalArgumentException("Deserialized identity " + deserialized + " cannot be cast to " + expectedBaseClass);
+ }
+ }
+
+ @Override
+ public <T extends BaseIdentity> void validateIdentity(IdentityAttributeRef identityRef, Class<T> expectedBaseClass, JmxAttribute jmxAttribute) {
+ try {
+ resolveIdentity(identityRef, expectedBaseClass);
+ } catch (Exception e) {
+ throw JmxAttributeValidationException.wrap(e, jmxAttribute);
+ }
+ }
+
@Override
public int compareTo(DependencyResolverImpl o) {
transactionStatus.checkCommitted();
return maxDependencyDepth;
}
- public void countMaxDependencyDepth(DependencyResolverManager manager) {
+ void countMaxDependencyDepth(DependencyResolverManager manager) {
transactionStatus.checkCommitted();
if (maxDependencyDepth == null) {
maxDependencyDepth = getMaxDepth(this, manager,
}
private static int getMaxDepth(DependencyResolverImpl impl,
- DependencyResolverManager manager,
- LinkedHashSet<ModuleIdentifier> chainForDetectingCycles) {
+ DependencyResolverManager manager,
+ LinkedHashSet<ModuleIdentifier> chainForDetectingCycles) {
int maxDepth = 0;
LinkedHashSet<ModuleIdentifier> chainForDetectingCycles2 = new LinkedHashSet<>(
chainForDetectingCycles);
.getOrCreate(dependencyName);
if (chainForDetectingCycles2.contains(dependencyName)) {
throw new IllegalStateException(format(
- "Cycle detected, {} contains {}",
+ "Cycle detected, %s contains %s",
chainForDetectingCycles2, dependencyName));
}
int subDepth;
public ModuleIdentifier getIdentifier() {
return name;
}
+
}