val caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode)
caseTypeBuilder.addImplementsType(refChoiceType)
genCtx.get(module).addCaseType(caseNode.path, caseTypeBuilder)
+ genCtx.get(module).addChoiceToCaseMapping(refChoiceType, caseTypeBuilder,caseNode)
val Set<DataSchemaNode> caseChildNodes = caseNode.childNodes
if (caseChildNodes !== null) {
var Object parentNode = null
throw new IllegalArgumentException("Failed to find parent type of choice " + targetNode);
}
- if (caseNode instanceof DataNodeContainer) {
- val DataNodeContainer dataNodeCase = caseNode as DataNodeContainer;
- val Set<DataSchemaNode> childNodes = dataNodeCase.childNodes;
- if (childNodes !== null) {
- resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, childNodes);
- }
- } else {
- val ChoiceCaseNode node = targetNode.getCaseNodeByName(caseNode.getQName().getLocalName());
- val Set<DataSchemaNode> childNodes = node.childNodes;
- if (childNodes !== null) {
- resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, childNodes);
- }
+ var ChoiceCaseNode node = null;
+ if (caseNode instanceof ChoiceCaseNode) {
+ node = caseNode as ChoiceCaseNode;
+ } else {
+ node = targetNode.getCaseNodeByName(caseNode.getQName().getLocalName());
+ }
+ val Set<DataSchemaNode> childNodes = node.childNodes;
+ if (childNodes !== null) {
+ resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, childNodes);
}
-
genCtx.get(module).addCaseType(caseNode.path, caseTypeBuilder)
+ genCtx.get(module).addChoiceToCaseMapping(targetType, caseTypeBuilder,node);
}
}
if(pathArguments.hasNext()) {
currentArg = pathArguments.next();
} else {
- return Optional.absent();
+ return currentContainer;
}
}
if(ChildOf.class.isAssignableFrom(currentArg.getType()) && BindingReflections.isAugmentationChild(currentArg.getType())) {
import java.lang.reflect.Field;
import java.util.Map;
-
-import org.opendaylight.yangtools.yang.data.impl.codec.IdentityCodec;
-import org.opendaylight.yangtools.yang.data.impl.codec.InstanceIdentifierCodec;
import org.opendaylight.yangtools.yang.binding.BindingCodec;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.IdentityCodec;
+import org.opendaylight.yangtools.yang.data.impl.codec.InstanceIdentifierCodec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public static final String CLASS_TO_CASE_MAP = "CLASS_TO_CASE";
public static final String COMPOSITE_TO_CASE = "COMPOSITE_TO_CASE";
public static final String AUGMENTATION_CODEC = "AUGMENTATION_CODEC";
+ public static final String DISPATCH_CODEC = "DISPATCH_CODEC";
public static void setIdentifierCodec(Class<?> obj,InstanceIdentifierCodec codec) {
Field instanceIdField;
}
}
+ public static void setDispatchCodec(Class<? extends BindingCodec<?,?>> codec,
+ BindingCodec<?, ?> dispatchCodec) {
+ Field instanceIdField;
+ try {
+ instanceIdField = codec.getField(DISPATCH_CODEC);
+ instanceIdField.set(null, dispatchCodec);
+ } catch (NoSuchFieldException e) {
+ LOG.debug("BUG: dispatch codec is not needed for {}",codec.getName(),e);
+ } catch (SecurityException | IllegalAccessException e) {
+ LOG.error("Dispatch codec could not be set for {}",codec.getName(),e);
+ }
+ }
+
public static void setAugmentationCodec(Class<? extends BindingCodec<?,?>> dataCodec,
BindingCodec<?,?> augmentableCodec) {
Field instanceIdField;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
+import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
-import java.util.Objects;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType;
import org.opendaylight.yangtools.sal.binding.model.api.Type;
import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTOBuilder;
-import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
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.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
-import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
GeneratorListener {
private static final Logger LOG = LoggerFactory.getLogger(LazyGeneratedCodecRegistry.class);
- private static final LateMixinCodec NOT_READY_CODEC = new LateMixinCodec();
// Concrete class to codecs
private static final Map<Class<?>, DataContainerCodec<?>> containerCodecs = Collections
@SuppressWarnings("rawtypes")
private static final Map<Type, WeakReference<Class>> typeToClass = new ConcurrentHashMap<>();
- @SuppressWarnings("rawtypes")
- private static final ConcurrentMap<Type, ChoiceCaseCodecImpl> typeToCaseCodecs = new ConcurrentHashMap<>();
+ private static final ConcurrentMap<Type, ChoiceCaseNode> caseTypeToCaseSchema = new ConcurrentHashMap<>();
private static final Map<SchemaPath, Type> pathToType = new ConcurrentHashMap<>();
private static final Map<List<QName>, Type> pathToInstantiatedType = new ConcurrentHashMap<>();
.<Type, Type> create());
private final InstanceIdentifierCodec instanceIdentifierCodec = new InstanceIdentifierCodecImpl(this);
- private final CaseClassMapFacade classToCaseRawCodec = new CaseClassMapFacade();
private final IdentityCompositeCodec identityRefCodec = new IdentityCompositeCodec();
private final ClassLoadingStrategy classLoadingStrategy;
private final AbstractTransformerGenerator generator;
return potential;
}
ConcreteType typeref = Types.typeForClass(caseClass);
- ChoiceCaseCodecImpl caseCodec = typeToCaseCodecs.get(typeref);
+ ChoiceCaseNode caseSchema = caseTypeToCaseSchema.get(typeref);
- Preconditions.checkState(caseCodec != null, "Case Codec was not created proactivelly for %s",
- caseClass.getName());
- Preconditions.checkState(caseCodec.getSchema() != null, "Case schema is not available for %s",
- caseClass.getName());
- Class<? extends BindingCodec> newCodec = generator.caseCodecFor(caseClass, caseCodec.getSchema());
+ Preconditions.checkState(caseSchema != null, "Case schema is not available for %s", caseClass.getName());
+ Class<? extends BindingCodec> newCodec = generator.caseCodecFor(caseClass, caseSchema);
BindingCodec newInstance = newInstanceOf(newCodec);
- caseCodec.setDelegate(newInstance);
+ @SuppressWarnings("unchecked")
+ ChoiceCaseCodecImpl caseCodec = new ChoiceCaseCodecImpl(caseClass, caseSchema, newInstance);
caseCodecs.put(caseClass, caseCodec);
-
- for (Entry<Class<?>, PublicChoiceCodecImpl<?>> choice : choiceCodecs.entrySet()) {
- if (choice.getKey().isAssignableFrom(caseClass)) {
- choice.getValue().cases.put(caseClass, caseCodec);
- }
- }
return caseCodec;
}
synchronized (choiceToCases) {
choiceToCases.putAll(context.getChoiceToCases());
}
- captureCases(context.getCases(), schemaContext);
- }
-
- private void captureCases(final Map<SchemaPath, GeneratedTypeBuilder> cases, final SchemaContext module) {
- for (Entry<SchemaPath, GeneratedTypeBuilder> caseNode : cases.entrySet()) {
- ReferencedTypeImpl typeref = new ReferencedTypeImpl(caseNode.getValue().getPackageName(), caseNode
- .getValue().getName());
-
- pathToType.put(caseNode.getKey(), caseNode.getValue());
-
- ChoiceCaseNode node = (ChoiceCaseNode) SchemaContextUtil.findDataSchemaNode(module, caseNode.getKey());
-
- if (node == null) {
- LOG.warn("Failed to find YANG SchemaNode for {}, with path {} was not found in context.",
- typeref.getFullyQualifiedName(), caseNode.getKey());
- @SuppressWarnings("rawtypes")
- ChoiceCaseCodecImpl value = new ChoiceCaseCodecImpl();
- typeToCaseCodecs.putIfAbsent(typeref, value);
- continue;
- }
- @SuppressWarnings("rawtypes")
- ChoiceCaseCodecImpl value = new ChoiceCaseCodecImpl(node);
- typeToCaseCodecs.putIfAbsent(typeref, value);
+ synchronized (caseTypeToCaseSchema) {
+ caseTypeToCaseSchema.putAll(context.getCaseTypeToSchemas());
}
}
Preconditions.checkState(oldCodec == null);
BindingCodec<Map<QName, Object>, Object> delegate = newInstanceOf(choiceCodec);
PublicChoiceCodecImpl<?> newCodec = new PublicChoiceCodecImpl(delegate);
+ DispatchChoiceCodecImpl dispatchCodec = new DispatchChoiceCodecImpl(choiceClass);
choiceCodecs.put(choiceClass, newCodec);
- CodecMapping.setClassToCaseMap(choiceCodec, classToCaseRawCodec);
- CodecMapping.setCompositeNodeToCaseMap(choiceCodec, newCodec.getCompositeToCase());
-
- tryToCreateCasesCodecs(schema);
-
- }
-
- @Deprecated
- private void tryToCreateCasesCodecs(final ChoiceNode schema) {
- for (ChoiceCaseNode choiceCase : schema.getCases()) {
- ChoiceCaseNode caseNode = choiceCase;
- if (caseNode.isAddedByUses()) {
- DataSchemaNode origCaseNode = SchemaContextUtil.findOriginal(caseNode, currentSchema);
- if (origCaseNode instanceof ChoiceCaseNode) {
- caseNode = (ChoiceCaseNode) origCaseNode;
- }
- }
- SchemaPath path = caseNode.getPath();
-
- Type type;
- if (path != null && (type = pathToType.get(path)) != null) {
- ReferencedTypeImpl typeref = new ReferencedTypeImpl(type.getPackageName(), type.getName());
- @SuppressWarnings("rawtypes")
- ChoiceCaseCodecImpl partialCodec = typeToCaseCodecs.get(typeref);
- if (partialCodec.getSchema() == null) {
- partialCodec.setSchema(caseNode);
- }
- try {
- Class<?> caseClass = classLoadingStrategy.loadClass(type.getFullyQualifiedName());
- getCaseCodecFor(caseClass);
- } catch (ClassNotFoundException e) {
- LOG.trace("Could not proactivelly create case codec for {}", type, e);
- }
- }
- }
-
+ CodecMapping.setDispatchCodec(choiceCodec, dispatchCodec);
}
@Override
@SuppressWarnings("rawtypes")
private static class ChoiceCaseCodecImpl<T extends DataContainer> implements ChoiceCaseCodec<T>, //
Delegator<BindingCodec>, LocationAwareBindingCodec<Node<?>, ValueWithQName<T>> {
- private boolean augmenting;
- private boolean uses;
- private BindingCodec delegate;
-
- private Set<String> validNames;
- private Set<QName> validQNames;
- private ChoiceCaseNode schema;
- private Set<InstanceIdentifier<?>> applicableLocations;
+ private final BindingCodec delegate;
+ private final ChoiceCaseNode schema;
+ private final Map<InstanceIdentifier<?>, ChoiceCaseNode> instantiatedLocations;
+ private final Class<?> dataType;
@Override
public boolean isApplicable(final InstanceIdentifier location) {
- return applicableLocations.contains(location);
+ return instantiatedLocations.containsKey(location);
}
- public void setSchema(final ChoiceCaseNode caseNode) {
+ public ChoiceCaseCodecImpl(final Class<?> caseClass, final ChoiceCaseNode caseNode,
+ final BindingCodec newInstance) {
+ this.delegate = newInstance;
+ this.dataType = caseClass;
this.schema = caseNode;
- validNames = new HashSet<>();
- validQNames = new HashSet<>();
- for (DataSchemaNode node : caseNode.getChildNodes()) {
- QName qname = node.getQName();
- validQNames.add(qname);
- validNames.add(qname.getLocalName());
- }
- augmenting = caseNode.isAugmenting();
- uses = caseNode.isAddedByUses();
- applicableLocations = new HashSet<>();
- }
-
- public ChoiceCaseCodecImpl() {
- this.delegate = NOT_READY_CODEC;
- }
-
- public ChoiceCaseCodecImpl(final ChoiceCaseNode caseNode) {
- this.delegate = NOT_READY_CODEC;
- setSchema(caseNode);
+ instantiatedLocations = new HashMap<>();
}
@Override
@Override
public ValueWithQName<T> deserialize(final Node<?> input, final InstanceIdentifier<?> bindingIdentifier) {
- throw new UnsupportedOperationException("Direct invocation of this codec is not allowed.");
+ if (input == null) {
+ return null;
+ }
+ QName qname = input.getNodeType();
+ synchronized (instantiatedLocations) {
+ ChoiceCaseNode instantiation = instantiatedLocations.get(bindingIdentifier);
+ if (instantiation != null) {
+ qname = instantiatedLocations.get(bindingIdentifier).getQName();
+ }
+ }
+ @SuppressWarnings("unchecked")
+ T value = (T) getDelegate().deserialize(new SimpleEntry(qname, input), bindingIdentifier);
+ return new ValueWithQName<T>(qname, value);
}
@Override
return delegate;
}
- public void setDelegate(final BindingCodec delegate) {
- this.delegate = delegate;
- }
-
public ChoiceCaseNode getSchema() {
return schema;
}
@Override
+ @Deprecated
public boolean isAcceptable(final Node<?> input) {
- if (input instanceof CompositeNode) {
- if (augmenting && !uses) {
- return checkAugmenting((CompositeNode) input);
- } else {
- return checkLocal((CompositeNode) input);
+ return checkAgainstSchema(schema, input);
+ }
+
+ private static boolean checkAgainstSchema(final ChoiceCaseNode schema, final Node<?> node) {
+ if (node instanceof CompositeNode) {
+ CompositeNode input = (CompositeNode) node;
+ for (Node<?> childNode : input.getValue()) {
+ QName child = childNode.getNodeType();
+ if (schema.getDataChildByName(child) != null) {
+ return true;
+ }
}
}
return false;
}
- @SuppressWarnings("deprecation")
- private boolean checkLocal(final CompositeNode input) {
- QName parent = input.getNodeType();
- for (Node<?> childNode : input.getChildren()) {
- QName child = childNode.getNodeType();
- if (!Objects.equals(parent.getNamespace(), child.getNamespace())
- || !Objects.equals(parent.getRevision(), child.getRevision())) {
- continue;
- }
- if (validNames.contains(child.getLocalName())) {
- return true;
- }
+ @Override
+ public Class<?> getDataType() {
+ return dataType;
+ }
+
+ public void adaptForPath(final InstanceIdentifier<?> augTarget, final ChoiceCaseNode choiceCaseNode) {
+ synchronized (instantiatedLocations) {
+ instantiatedLocations.put(augTarget, choiceCaseNode);
}
- return false;
}
- @SuppressWarnings("deprecation")
- private boolean checkAugmenting(final CompositeNode input) {
- for (Node<?> child : input.getChildren()) {
- if (validQNames.contains(child.getNodeType())) {
- return true;
- }
+ public boolean isAcceptable(final InstanceIdentifier path, final CompositeNode input) {
+ ChoiceCaseNode instantiatedSchema = null;
+ synchronized (instantiatedLocations) {
+ instantiatedSchema = instantiatedLocations.get(path);
}
- return false;
+ if (instantiatedSchema == null) {
+ return false;
+ }
+ return checkAgainstSchema(instantiatedSchema, input);
}
- @Override
- public Class<?> getDataType() {
- // TODO Auto-generated method stub
- throw new UnsupportedOperationException("Not implemented Yet.");
+ protected boolean isAugmenting(final QName choiceName,final QName proposedQName) {
+ if (schema.isAugmenting()) {
+ return true;
+ }
+ // Choice QName
+ QName parentQName = Iterables.get(schema.getPath().getPathTowardsRoot(), 1);
+ if (!parentQName.getNamespace().equals(schema.getQName().getNamespace())) {
+ return true;
+ }
+ if (!parentQName.equals(choiceName)) {
+ // This item is instantiation of choice via uses in other YANG module
+ if(choiceName.getNamespace().equals(schema.getQName())) {
+ // Original definition of grouping is in same namespace
+ // as original definition of case
+ // so for sure case is introduced via instantiation of grouping
+ return false;
+ }
+ // Since we are still here, that means case has same namespace
+ // as its parent, which is instantiation of grouping
+ // but case namespace is different from parent node
+ // so it is augmentation.
+ return true;
+ }
+ return false;
}
}
private final BindingCodec<Map<QName, Object>, Object> delegate;
- @SuppressWarnings("rawtypes")
- private final Map<Class, ChoiceCaseCodecImpl<?>> cases = Collections
- .synchronizedMap(new WeakHashMap<Class, ChoiceCaseCodecImpl<?>>());
-
- private final CaseCompositeNodeMapFacade CompositeToCase;
-
public PublicChoiceCodecImpl(final BindingCodec<Map<QName, Object>, Object> delegate) {
this.delegate = delegate;
- this.CompositeToCase = new CaseCompositeNodeMapFacade(cases);
}
@Override
throw new UnsupportedOperationException("Direct invocation of this codec is not allowed.");
}
- public CaseCompositeNodeMapFacade getCompositeToCase() {
- return CompositeToCase;
- }
-
@Override
public BindingCodec<Map<QName, Object>, Object> getDelegate() {
return delegate;
}
- @SuppressWarnings("unused")
- private class DispatchChoiceCodecImpl extends LocationAwareDispatchCodec<ChoiceCaseCodecImpl<?>> {
-
- @Override
- public Object deserialize(final Object input,
- @SuppressWarnings("rawtypes") final InstanceIdentifier bindingIdentifier) {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Object serialize(final Object input) {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- protected ChoiceCaseCodecImpl<?> tryToLoadImplementation(final Class<? extends DataContainer> inputType) {
- return getCaseCodecFor(inputType);
- }
-
- @Override
- protected void tryToLoadImplementations() {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- protected void adaptForPathImpl(final InstanceIdentifier<?> path, final DataNodeContainer ctx) {
- // TODO Auto-generated method stub
+ class DispatchChoiceCodecImpl extends LocationAwareDispatchCodec<ChoiceCaseCodecImpl<?>> {
+ private final Class<?> choiceType;
+ private final QName choiceName;
+ private DispatchChoiceCodecImpl(final Class<?> type) {
+ choiceType = type;
+ choiceName = BindingReflections.findQName(type);
}
- }
-
- @SuppressWarnings("rawtypes")
- private class CaseClassMapFacade extends MapFacadeBase {
@Override
- public Set<Entry<Class, BindingCodec<Object, Object>>> entrySet() {
- return Collections.emptySet();
- }
-
- @Override
- public BindingCodec get(final Object key) {
- if (key instanceof Class) {
- Class cls = (Class) key;
- // bindingClassEncountered(cls);
- ChoiceCaseCodecImpl caseCodec = getCaseCodecFor(cls);
- return caseCodec.getDelegate();
- }
- return null;
- }
- }
-
- @SuppressWarnings("rawtypes")
- private static class CaseCompositeNodeMapFacade extends MapFacadeBase<CompositeNode> {
-
- final Map<Class, ChoiceCaseCodecImpl<?>> choiceCases;
-
- public CaseCompositeNodeMapFacade(final Map<Class, ChoiceCaseCodecImpl<?>> choiceCases) {
- this.choiceCases = choiceCases;
- }
+ public Object deserialize(final Object input, @SuppressWarnings("rawtypes") final InstanceIdentifier path) {
+ adaptForPath(path);
- @Override
- public BindingCodec get(final Object key) {
- if (!(key instanceof CompositeNode)) {
- return null;
- }
- for (Entry<Class, ChoiceCaseCodecImpl<?>> entry : choiceCases.entrySet()) {
- ChoiceCaseCodecImpl<?> codec = entry.getValue();
- if (codec.isAcceptable((CompositeNode) key)) {
- return codec.getDelegate();
+ if (input instanceof CompositeNode) {
+ List<Entry<Class, ChoiceCaseCodecImpl<?>>> codecs = new ArrayList<>(getImplementations().entrySet());
+ for (Entry<Class, ChoiceCaseCodecImpl<?>> codec : codecs) {
+ ChoiceCaseCodecImpl<?> caseCodec = codec.getValue();
+ if (caseCodec.isAcceptable(path, (CompositeNode) input)) {
+ ValueWithQName<?> value = caseCodec.deserialize((CompositeNode) input, path);
+ if (value != null) {
+ return value.getValue();
+ }
+ return null;
+ }
}
}
return null;
}
- }
-
- /**
- * This map is used as only facade for
- * {@link org.opendaylight.yangtools.yang.binding.BindingCodec} in different
- * classloaders to retrieve codec dynamicly based on provided key.
- *
- * @param <T>
- * Key type
- */
- @SuppressWarnings("rawtypes")
- private abstract static class MapFacadeBase<T> implements Map<T, BindingCodec<?, ?>> {
-
- @Override
- public boolean containsKey(final Object key) {
- return get(key) != null;
- }
-
- @Override
- public void clear() {
- throw notModifiable();
- }
-
- @Override
- public boolean equals(final Object obj) {
- return super.equals(obj);
- }
-
+ @SuppressWarnings("unchecked")
@Override
- public BindingCodec remove(final Object key) {
- return null;
+ public Object serialize(final Object input) {
+ Preconditions.checkArgument(input instanceof Map.Entry<?, ?>, "Input must be QName, Value");
+ @SuppressWarnings("rawtypes")
+ QName derivedQName = (QName) ((Map.Entry) input).getKey();
+ @SuppressWarnings("rawtypes")
+ Object inputValue = ((Map.Entry) input).getValue();
+ Preconditions.checkArgument(inputValue instanceof DataObject);
+ Class<? extends DataContainer> inputType = ((DataObject) inputValue).getImplementedInterface();
+ ChoiceCaseCodecImpl<?> codec = tryToLoadImplementation(inputType);
+ Preconditions.checkState(codec != null, "Unable to get codec for %s", inputType);
+ if (codec.isAugmenting(choiceName,derivedQName)) {
+ // If choice is augmenting we use QName which defined this
+ // augmentation
+ return codec.getDelegate().serialize(new ValueWithQName<>(codec.getSchema().getQName(), inputValue));
+ }
+ return codec.getDelegate().serialize(input);
}
- @Override
- public int size() {
- return 0;
- }
- @Override
- public Collection<BindingCodec<?, ?>> values() {
- return Collections.emptySet();
- }
- private UnsupportedOperationException notModifiable() {
- return new UnsupportedOperationException("Not externally modifiable.");
+ @SuppressWarnings("rawtypes")
+ protected Optional<ChoiceCaseCodecImpl> tryToLoadImplementation(final Type potential) {
+ try {
+ @SuppressWarnings("unchecked")
+ Class<? extends DataContainer> clazz = (Class<? extends DataContainer>) classLoadingStrategy
+ .loadClass(potential);
+ ChoiceCaseCodecImpl codec = tryToLoadImplementation(clazz);
+ addImplementation(codec);
+ return Optional.of(codec);
+ } catch (ClassNotFoundException e) {
+ LOG.warn("Failed to find class for choice {}", potential, e);
+ }
+ return Optional.absent();
}
@Override
- public BindingCodec<Map<QName, Object>, Object> put(final T key, final BindingCodec<?, ?> value) {
- throw notModifiable();
+ protected ChoiceCaseCodecImpl<?> tryToLoadImplementation(final Class<? extends DataContainer> inputType) {
+ ChoiceCaseCodecImpl<?> codec = getCaseCodecFor(inputType);
+ addImplementation(codec);
+ return codec;
}
@Override
- public void putAll(final Map<? extends T, ? extends BindingCodec<?, ?>> m) {
- throw notModifiable();
+ protected void tryToLoadImplementations() {
+ Type type = referencedType(choiceType);
+ Collection<Type> potentialCases;
+ synchronized (choiceToCases) {
+ potentialCases = choiceToCases.get(type);
+ }
+ for (Type potential : potentialCases) {
+ try {
+ tryToLoadImplementation(potential);
+ } catch (CodeGenerationException e) {
+ LOG.warn("Failed to proactively generate choice code for {}", type, e);
+ }
+ }
}
@Override
- public int hashCode() {
- return super.hashCode();
+ protected void adaptForPathImpl(final InstanceIdentifier<?> augTarget, final DataNodeContainer ctxNode) {
+ Optional<ChoiceNode> newChoice = findInstantiatedChoice(ctxNode, choiceName);
+ tryToLoadImplementations();
+ Preconditions.checkState(newChoice.isPresent(), "BUG: Unable to find instantiated choice node in schema.");
+ for (@SuppressWarnings("rawtypes")
+ Entry<Class, ChoiceCaseCodecImpl<?>> codec : getImplementations().entrySet()) {
+ ChoiceCaseCodecImpl<?> caseCodec = codec.getValue();
+ Optional<ChoiceCaseNode> instantiatedSchema = findInstantiatedCase(newChoice.get(),
+ caseCodec.getSchema());
+ if (instantiatedSchema.isPresent()) {
+ caseCodec.adaptForPath(augTarget, instantiatedSchema.get());
+ }
+ }
}
- @Override
- public boolean isEmpty() {
- return true;
- }
+ private Optional<ChoiceNode> findInstantiatedChoice(final DataNodeContainer ctxNode, final QName choiceName) {
+ DataSchemaNode potential = ctxNode.getDataChildByName(choiceName);
+ if (potential == null) {
+ potential = ctxNode.getDataChildByName(choiceName.getLocalName());
+ }
- @Override
- public Set<T> keySet() {
- return Collections.emptySet();
- }
+ if (potential instanceof ChoiceNode) {
+ return Optional.of((ChoiceNode) potential);
+ }
- @Override
- public Set<Entry<T, BindingCodec<?, ?>>> entrySet() {
- return Collections.emptySet();
+ return Optional.absent();
}
- @Override
- public boolean containsValue(final Object value) {
- return false;
+ private Optional<ChoiceCaseNode> findInstantiatedCase(final ChoiceNode newChoice, final ChoiceCaseNode schema) {
+ ChoiceCaseNode potential = newChoice.getCaseNodeByName(schema.getQName());
+ if (potential != null) {
+ return Optional.of(potential);
+ }
+ // FIXME: Probably requires more extensive check
+ // e.g. we have one choice and two augmentations from different
+ // modules using same local name
+ // but different namespace / contents
+ return Optional.fromNullable(newChoice.getCaseNodeByName(schema.getQName().getLocalName()));
}
}
*
* Adaptation consists of:
* <ol>
- * <li> scan of available (valid) augmentations for
- * current location
+ * <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
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);
+ 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);
+ LOG.error("Unable to serialize instance identifiers for {}", augPath, e);
}
}
} else {
- // Omits warning for empty augmentations since they are not represented in data
- if(!aug.getChildNodes().isEmpty()) {
+ // 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());
+ aug.getChildNodes());
}
}
}
}
-
-
private Type getTypeForAugmentation(final AugmentationSchema aug) {
Optional<AugmentationSchema> currentAug = Optional.of(aug);
while (currentAug.isPresent()) {
}
}
- @SuppressWarnings({ "rawtypes", "unchecked" })
- private static class LateMixinCodec implements BindingCodec, Delegator<BindingCodec> {
-
- private BindingCodec delegate;
-
- @Override
- public BindingCodec getDelegate() {
- if (delegate == null) {
- throw new IllegalStateException("Codec not initialized yet.");
- }
- return delegate;
- }
-
- @Override
- public Object deserialize(final Object input) {
- return getDelegate().deserialize(input);
- }
-
- @Override
- public Object deserialize(final Object input, final InstanceIdentifier bindingIdentifier) {
- return getDelegate().deserialize(input, bindingIdentifier);
- }
-
- @Override
- public Object serialize(final Object input) {
- return getDelegate().serialize(input);
- }
-
- }
-
@SuppressWarnings("rawtypes")
private static class AugmentationCodecWrapper<T extends Augmentation<?>> implements AugmentationCodec<T>,
Delegator<BindingCodec>, LocationAwareBindingCodec<Node<?>, ValueWithQName<T>> {
*/
package org.opendaylight.yangtools.sal.binding.generator.impl;
+import com.google.common.collect.BiMap;
+import com.google.common.collect.HashBiMap;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
-
import org.opendaylight.yangtools.sal.binding.model.api.Type;
import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTOBuilder;
import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
-import com.google.common.collect.BiMap;
-import com.google.common.collect.HashBiMap;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
-
public final class ModuleContext {
private GeneratedTypeBuilder moduleNode;
private final List<GeneratedTOBuilder> genTOs = new ArrayList<GeneratedTOBuilder>();
private final BiMap<Type,AugmentationSchema> typeToAugmentation = HashBiMap.create();
private final Multimap<Type, Type> choiceToCases = HashMultimap.create();
+ private final BiMap<Type,ChoiceCaseNode> caseTypeToSchema = HashBiMap.create();
private final Multimap<Type, Type> augmentableToAugmentations = HashMultimap.create();
augmentableToAugmentations.put(target,augmentation);
}
+ public void addChoiceToCaseMapping(Type choiceType, Type caseType, ChoiceCaseNode schema) {
+ choiceToCases.put(choiceType, caseType);
+ caseTypeToSchema.put(caseType, schema);
+ }
+
+ public BiMap<Type, ChoiceCaseNode> getCaseTypeToSchemas() {
+ return caseTypeToSchema;
+ }
+
}
//staticQNameField(inputType);
staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
staticField(it, IDENTITYREF_CODEC, BindingCodec)
- staticField(it, CLASS_TO_CASE_MAP, Map)
- staticField(it, COMPOSITE_TO_CASE, Map)
+ staticField(it, DISPATCH_CODEC, BindingCodec)
//staticField(it,QNAME_TO_CASE_MAP,BindingCodec)
implementsType(BINDING_CODEC)
method(List, "toDomStatic", #[QName, Object]) [
if($2 == null) {
return null;
}
- «DataObject.name» _baValue = («DataObject.name») $2;
- Class _baClass = _baValue.getImplementedInterface();
- «BINDING_CODEC.name» _codec = «CLASS_TO_CASE_MAP».get(_baClass);
- if(_codec == null) {
- return null;
+ if («DISPATCH_CODEC» == null) {
+ throw new «IllegalStateException.name»("Implementation of codec was not initialized.");
}
- java.util.Map.Entry _input = new «SimpleEntry.name»($1,_baValue);
- Object _ret = _codec.serialize(_input);
+ java.util.Map.Entry _input = new «SimpleEntry.name»($1,$2);
+ Object _ret = «DISPATCH_CODEC».serialize(_input);
////System.out.println("«typeSpec.name»#toDomStatic: " + _ret);
return («List.name») _ret;
}
modifiers = PUBLIC + FINAL + STATIC
bodyChecked = '''
{
- «BINDING_CODEC.name» _codec = («BINDING_CODEC.name») «COMPOSITE_TO_CASE».get($2);
- if(_codec != null) {
- return _codec.deserialize(new «SimpleEntry.name»($1,$2),$3);
+ if («DISPATCH_CODEC» == null) {
+ throw new «IllegalStateException.name»("Implementation of codec was not initialized.");
}
- return null;
+ return «DISPATCH_CODEC».deserialize($2,$3);
}
'''
]
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- vi: set et smarttab sw=4 tabstop=4: -->
-<!--
- 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
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
- <modelVersion>4.0.0</modelVersion>
-
- <parent>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yangtools-parent</artifactId>
- <version>0.6.2-SNAPSHOT</version>
- <relativePath>/../../common/parent/pom.xml</relativePath>
- </parent>
-
- <artifactId>features-file</artifactId>
- <packaging>pom</packaging>
-
- <properties>
- <features.file>features.xml</features.file>
- </properties>
-
- <build>
- <resources>
- <resource>
- <directory>src/main/resources</directory>
- <filtering>true</filtering>
- </resource>
- </resources>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-resources-plugin</artifactId>
- <executions>
- <execution>
- <id>filter</id>
- <phase>generate-resources</phase>
- <goals>
- <goal>resources</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>build-helper-maven-plugin</artifactId>
- <executions>
- <execution>
- <id>attach-artifacts</id>
- <phase>package</phase>
- <goals>
- <goal>attach-artifact</goal>
- </goals>
- <configuration>
- <artifacts>
- <artifact>
- <file>${project.build.directory}/classes/${features.file}</file>
- <type>xml</type>
- <classifier>features</classifier>
- </artifact>
- </artifacts>
- </configuration>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
-</project>
-
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yangtools-parent</artifactId>
+ <version>0.6.2-SNAPSHOT</version>
+ <relativePath>../parent/pom.xml</relativePath>
+ </parent>
+ <artifactId>features-yangtools</artifactId>
+ <packaging>pom</packaging>
+ <properties>
+ <features.file>features.xml</features.file>
+ </properties>
+ <build>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.karaf.tooling</groupId>
+ <artifactId>karaf-maven-plugin</artifactId>
+ <version>${karaf.version}</version>
+ <extensions>true</extensions>
+ <executions>
+ <execution>
+ <id>features-create-kar</id>
+ <goals>
+ <goal>features-create-kar</goal>
+ </goals>
+ <configuration>
+ <featuresFile>${project.build.directory}/classes/${features.file}</featuresFile>
+ </configuration>
+ </execution>
+ </executions>
+ <!-- There is no useful configuration for the kar mojo. The features-generate-descriptor mojo configuration may be useful -->
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>filter</id>
+ <phase>generate-resources</phase>
+ <goals>
+ <goal>resources</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-artifacts</id>
+ <phase>package</phase>
+ <goals>
+ <goal>attach-artifact</goal>
+ </goals>
+ <configuration>
+ <artifacts>
+ <artifact>
+ <file>${project.build.directory}/classes/${features.file}</file>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </artifact>
+ </artifacts>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
<feature name='yangtools-all' version='${project.version}'>
<feature version='${project.version}'>yangtools-models</feature>
<feature version='${project.version}'>yangtools-binding</feature>
+ <feature version='${project.version}'>yangtools-common</feature>
<feature version='${project.version}'>yangtools-concepts</feature>
<feature version='${project.version}'>yangtools-binding-generator</feature>
</feature>
<feature name='yangtools-models' version='${project.version}'>
- <bundle>mvn:org.opendaylight.yangtools.model/ietf-inet-types/2010.09.24.4-SNAPSHOT</bundle>
- <bundle>mvn:org.opendaylight.yangtools.model/ietf-yang-types/2010.09.24.4-SNAPSHOT</bundle>
- <bundle>mvn:org.opendaylight.yangtools.model/yang-ext/2013.09.07.4-SNAPSHOT</bundle>
- <bundle>mvn:org.opendaylight.yangtools.model/opendaylight-l2-types/2013.08.27.4-SNAPSHOT</bundle>
- <bundle>mvn:org.opendaylight.yangtools.model/ietf-topology/2013.10.21.2-SNAPSHOT</bundle>
- <bundle>mvn:org.opendaylight.yangtools.model/opendaylight-l2-types/2013.08.27.4-SNAPSHOT</bundle>
- </feature>
+ <bundle>mvn:org.opendaylight.yangtools.model/ietf-inet-types/${ietf.inet.types.version}</bundle>
+ <bundle>mvn:org.opendaylight.yangtools.model/ietf-yang-types/${ietf.yang.types.version}</bundle>
+ <bundle>mvn:org.opendaylight.yangtools.model/yang-ext/${yang.ext.version}</bundle>
+ <bundle>mvn:org.opendaylight.yangtools.model/opendaylight-l2-types/${opendaylight.l2.types.version}</bundle>
+ <bundle>mvn:org.opendaylight.yangtools.model/ietf-topology/${ietf.topology.version}</bundle>
+ </feature>
<feature name='yangtools-binding' version='${project.version}'>
<feature version='${project.version}'>yangtools-concepts</feature>
- <bundle>mvn:org.opendaylight.yangtools.thirdparty/antlr4-runtime-osgi-nohead/4.0</bundle>
- <bundle>mvn:commons-io/commons-io/2.4</bundle>
+ <bundle>mvn:org.opendaylight.yangtools.thirdparty/antlr4-runtime-osgi-nohead/${antlr4.version}</bundle>
+ <bundle>mvn:commons-io/commons-io/${commons.io.version}</bundle>
<bundle>mvn:org.opendaylight.yangtools/yang-binding/${project.version}</bundle>
<bundle>mvn:org.opendaylight.yangtools/yang-data-api/${project.version}</bundle>
<bundle>mvn:org.opendaylight.yangtools/yang-data-impl/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.yangtools/yang-data-json/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.yangtools/yang-data-operations/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.yangtools/yang-data-util/${project.version}</bundle>
<bundle>mvn:org.opendaylight.yangtools/yang-model-api/${project.version}</bundle>
<bundle>mvn:org.opendaylight.yangtools/yang-model-util/${project.version}</bundle>
<bundle>mvn:org.opendaylight.yangtools/yang-parser-impl/${project.version}</bundle>
<bundle>wrap:mvn:org.eclipse.xtend/org.eclipse.xtend.lib/${xtend.version}</bundle>
<bundle>wrap:mvn:org.eclipse.xtext/org.eclipse.xtext.xbase.lib/${xtend.version}</bundle>
</feature>
-
+ <feature name="yangtools-common" version='${project.version}'>
+ <bundle>mvn:org.opendaylight.yangtools/util/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.yangtools/object-cache-api/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.yangtools/object-cache-guava/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.yangtools/object-cache-noop/${project.version}</bundle>
+ </feature>
<feature name='yangtools-binding-generator' version='${project.version}'>
<feature version='${project.version}'>yangtools-binding</feature>
<bundle>mvn:org.javassist/javassist/${javassist.version}</bundle>
- <bundle>mvn:org.apache.commons/commons-lang3/${commons.lang.version}</bundle>
+ <bundle>mvn:org.apache.commons/commons-lang3/${commons.lang3.version}</bundle>
<bundle>mvn:org.opendaylight.yangtools/binding-generator-api/${project.version}</bundle>
<bundle>mvn:org.opendaylight.yangtools/binding-generator-impl/${project.version}</bundle>
<bundle>mvn:org.opendaylight.yangtools/binding-generator-spi/${project.version}</bundle>
</prerequisites>
<properties>
- <junit.version>4.10</junit.version>
+ <antlr4.version>4.0</antlr4.version>
+ <commons.io.version>2.4</commons.io.version>
+ <ctrie.version>0.2.0</ctrie.version>
<exam.version>3.0.0</exam.version>
<groovy.version>2.1.6</groovy.version>
- <nexusproxy>http://nexus.opendaylight.org/content</nexusproxy>
- <ctrie.version>0.2.0</ctrie.version>
<ietf.topology.version>2013.10.21.2-SNAPSHOT</ietf.topology.version>
<ietf.inet.types.version>2010.09.24.4-SNAPSHOT</ietf.inet.types.version>
<ietf.yang.types.version>2010.09.24.4-SNAPSHOT</ietf.yang.types.version>
<ietf.restconf.version>2013.10.19.1-SNAPSHOT</ietf.restconf.version>
+ <junit.version>4.10</junit.version>
+ <karaf.version>3.0.1</karaf.version>
+ <nexusproxy>http://nexus.opendaylight.org/content</nexusproxy>
+ <opendaylight.l2.types.version>2013.08.27.4-SNAPSHOT</opendaylight.l2.types.version>
+ <yang.ext.version>2013.09.07.4-SNAPSHOT</yang.ext.version>
<maven.javadoc.version>2.9.1</maven.javadoc.version>
</properties>
<version>0.6.2-SNAPSHOT</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>bug1196-test-model</artifactId>
+ <version>0.6.2-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<modules>
<module>checkstyle-logging</module>
<module>concepts</module>
- <module>feature</module>
+ <module>features</module>
<module>mockito-configuration</module>
<module>object-cache-api</module>
<module>object-cache-guava</module>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!-- Copyright (c) 2013 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 -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yangtools-parent</artifactId>
+ <version>0.6.2-SNAPSHOT</version>
+ <relativePath>/../../common/parent/pom.xml</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>bug1196-test-model</artifactId>
+ <name>${project.artifactId}</name>
+ <description>${project.artifactId}</description>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-binding</artifactId>
+ <version>0.6.2-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ <version>0.6.2-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>yang-ext</artifactId>
+ <version>2013.09.07.4-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>ietf-inet-types</artifactId>
+ <version>2010.09.24.4-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>org.opendaylight.yangtools.model.${project.artifactId}</Bundle-Name>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>yang-ext</artifactId>
+ <version>2013.09.07.4-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>ietf-inet-types</artifactId>
+ </dependency>
+ </dependencies>
+
+</project>
--- /dev/null
+module network-topology-pcep {
+ // vi: set et smarttab sw=4 tabstop=4:
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:topology:pcep";
+ prefix "pn";
+
+ import network-topology { prefix nt; revision-date 2013-10-21; }
+
+ revision "2013-10-24" {
+ }
+
+
+ grouping pcep-client-attributes {
+ container path-computation-client {
+ config false;
+ list reported-lsp {
+ leaf name {
+ type string;
+ }
+ key name;
+ }
+ }
+ }
+
+ augment "/nt:network-topology/nt:topology/nt:node" {
+ when "../../nt:topology-types/topology-pcep";
+
+ uses pcep-client-attributes;
+ }
+
+}
+
--- /dev/null
+module network-topology-unix {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:network:topology-unix";
+ prefix "unix";
+
+ import network-topology { prefix nt; revision-date 2013-10-21; }
+ import network-topology-pcep { prefix topo; revision-date 2013-10-24; }
+ import odl-pcep-ietf-stateful07 { prefix stateful; revision-date 2013-12-22; }
+
+ revision "2013-12-22" {
+ }
+
+
+ augment "/nt:network-topology/nt:topology/nt:node/topo:path-computation-client/topo:reported-lsp/stateful:lsp/stateful:tlvs/stateful:vs-tlv/stateful:vendor-payload" {
+ case unix {
+ container unix-sub-tlvs {
+ leaf unix-value {
+ type uint8;
+ }
+ }
+ }
+ }
+
+}
+
--- /dev/null
+module network-topology {
+ yang-version 1;
+ namespace "urn:TBD:params:xml:ns:yang:network-topology";
+ prefix "nt";
+
+
+ revision 2013-10-21 {
+ }
+
+
+
+ container network-topology {
+ list topology {
+ key "topology-id";
+ leaf topology-id {
+ type string;
+ }
+ list node {
+ }
+ }
+ }
+}
+
--- /dev/null
+module odl-pcep-ietf-stateful07 {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:pcep:ietf:stateful";
+ prefix "stateful";
+
+ import network-topology { prefix nt; revision-date 2013-10-21; }
+ import network-topology-pcep { prefix topo; revision-date 2013-10-24; }
+ import pcep-types { prefix pcep; revision-date 2013-10-05; }
+ import yang-ext { prefix ext; revision-date 2013-07-09; }
+
+ revision "2013-12-22" {
+ }
+
+
+ grouping lsp-object {
+ container lsp {
+ container "tlvs" {
+ uses pcep:vs-tlv;
+ }
+ }
+ }
+
+ augment "/nt:network-topology/nt:topology/nt:node/topo:path-computation-client/topo:reported-lsp" {
+ uses lsp-object;
+ }
+
+ augment "/nt:network-topology/nt:topology/nt:node/topo:path-computation-client/topo:reported-lsp/stateful:lsp/stateful:tlvs/stateful:vs-tlv/stateful:vendor-payload" {
+ case linux {
+ container linux-sub-tlvs {
+ leaf linux-value {
+ type uint8;
+ }
+ }
+ }
+ }
+
+}
+
--- /dev/null
+module pcep-types {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:pcep:types";
+ prefix "pcep-t";
+
+ revision "2013-10-05" {
+ }
+
+
+ grouping vs-tlv {
+ description "Vendor-specific TLV.";
+ container vs-tlv {
+ choice vendor-payload {
+ }
+ }
+ }
+
+}
+
<modules>
<module>bug527-test-model</module>
+ <module>bug1196-test-model</module>
<module>bundle-test</module>
<module>test-models</module>
<module>regression-test-model</module>
<version>0.6.2-SNAPSHOT</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>bug1196-test-model</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
--- /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.restconf.utils;
+
+import static junit.framework.Assert.assertNotNull;
+import static org.junit.Assert.assertEquals;
+
+import java.io.InputStream;
+import java.util.AbstractMap.SimpleEntry;
+import java.util.Map.Entry;
+
+import javassist.ClassPool;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.topology.unix.rev131222.network.topology.topology.node.path.computation.client.reported.lsp.lsp.tlvs.vs.tlv.vendor.payload.unix.UnixSubTlvs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.ReportedLsp1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.Lsp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.lsp.Tlvs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.network.topology.topology.node.path.computation.client.reported.lsp.lsp.tlvs.vs.tlv.vendor.payload.linux.LinuxSubTlvs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.vs.tlv.VsTlv;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.Node1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.PathComputationClient;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.ReportedLsp;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+public class Bug1196Test {
+
+ private static final InstanceIdentifier<PathComputationClient> PATH_TO_CLIENT = InstanceIdentifier.builder(NetworkTopology.class)
+ .child(Topology.class)
+ .child(Node.class)
+ .augmentation(Node1.class)
+ .child(PathComputationClient.class)
+ .build();
+ private RuntimeGeneratedMappingServiceImpl mappingService;
+
+ @Before
+ public void setup() {
+ this.mappingService = new RuntimeGeneratedMappingServiceImpl(new ClassPool());
+
+ final ModuleInfoBackedContext moduleInfo = ModuleInfoBackedContext.create();
+ moduleInfo.addModuleInfos(BindingReflections.loadModuleInfos());
+ this.mappingService.onGlobalContextUpdated(moduleInfo.tryToCreateSchemaContext().get());
+ }
+
+ @Test
+ public void testXmlDataToDataObjectLinuxCase() {
+ final InstanceIdentifier<Topology> instanceIdentifier = InstanceIdentifier.builder(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(new TopologyId("example-pcep-topology"))).toInstance();
+ final InputStream is = this.getClass().getClassLoader().getResourceAsStream("topology-bug1196-linux.xml");
+ final DataSchemaNode dataSchema = RestconfUtils.toRestconfIdentifier(instanceIdentifier, this.mappingService,
+ this.mappingService.getSchemaContext()).getValue();
+ Topology topology = (Topology) RestconfUtils.dataObjectFromInputStream(instanceIdentifier, is,
+ this.mappingService.getSchemaContext(), this.mappingService, dataSchema);
+ assertNotNull(topology);
+ assertNotNull(topology.getNode());
+ assertEquals(1, topology.getNode().size());
+ Node node = topology.getNode().get(0);
+ Node1 node1 = node.getAugmentation(Node1.class);
+ assertNotNull(node1);
+ final PathComputationClient pcc = node1.getPathComputationClient();
+ final Lsp lsp = pcc.getReportedLsp().get(0).getAugmentation(ReportedLsp1.class).getLsp();
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.lsp.Tlvs tlvs = lsp.getTlvs();
+ assertNotNull(tlvs);
+ VsTlv vsTlv = tlvs.getVsTlv();
+ assertNotNull(vsTlv.getVendorPayload());
+
+ Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> domPcc = mappingService.toDataDom(new SimpleEntry<InstanceIdentifier<?>,DataObject>(PATH_TO_CLIENT,pcc));
+ CompositeNode domPccValue = domPcc.getValue();
+ assertNotNull(domPccValue);
+ CompositeNode domPccTlvs = getFirstReportedLspVsTlvs(domPccValue);
+ assertNotNull(domPccTlvs);
+ assertNotNull(domPccTlvs.getFirstCompositeByName(LinuxSubTlvs.QNAME));
+
+ }
+
+ private CompositeNode getFirstReportedLspVsTlvs(final CompositeNode domPccValue) {
+ return domPccValue.getFirstCompositeByName(ReportedLsp.QNAME).getFirstCompositeByName(Lsp.QNAME).getFirstCompositeByName(Tlvs.QNAME).getFirstCompositeByName(QName.create(Tlvs.QNAME,VsTlv.QNAME.getLocalName()));
+ }
+
+ @Test
+ public void testXmlDataToDataObjectUnixCase() {
+ final InstanceIdentifier<Topology> instanceIdentifier = InstanceIdentifier.builder(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(new TopologyId("example-pcep-topology"))).toInstance();
+ final InputStream is = this.getClass().getClassLoader().getResourceAsStream("topology-bug1196-unix.xml");
+ final DataSchemaNode dataSchema = RestconfUtils.toRestconfIdentifier(instanceIdentifier, this.mappingService,
+ this.mappingService.getSchemaContext()).getValue();
+ Topology topology = (Topology) RestconfUtils.dataObjectFromInputStream(instanceIdentifier, is,
+ this.mappingService.getSchemaContext(), this.mappingService, dataSchema);
+ assertNotNull(topology);
+ assertNotNull(topology.getNode());
+ assertEquals(1, topology.getNode().size());
+ Node node = topology.getNode().get(0);
+ Node1 node1 = node.getAugmentation(Node1.class);
+ assertNotNull(node1);
+ final PathComputationClient pcc = node1.getPathComputationClient();
+ final Lsp lsp = pcc.getReportedLsp().get(0).getAugmentation(ReportedLsp1.class).getLsp();
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.lsp.Tlvs tlvs = lsp.getTlvs();
+ assertNotNull(tlvs);
+ VsTlv vsTlv = tlvs.getVsTlv();
+ assertNotNull(vsTlv.getVendorPayload());
+
+ Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> domPcc = mappingService.toDataDom(new SimpleEntry<InstanceIdentifier<?>,DataObject>(PATH_TO_CLIENT,pcc));
+ CompositeNode domPccValue = domPcc.getValue();
+ assertNotNull(domPccValue);
+ CompositeNode domPccTlvs = getFirstReportedLspVsTlvs(domPccValue);
+ assertNotNull(domPccTlvs);
+ assertNotNull(domPccTlvs.getFirstCompositeByName(UnixSubTlvs.QNAME));
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Copyright (c) 2013 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 -->
+<topology xmlns="urn:TBD:params:xml:ns:yang:network-topology">
+ <server-provided>true</server-provided>
+ <topology-id>example-pcep-topology</topology-id>
+ <topology-types/>
+ <node>
+ <path-computation-client xmlns="urn:opendaylight:params:xml:ns:yang:topology:pcep">
+ <state-sync>synchronized</state-sync>
+ <stateful-tlv>
+ <stateful>
+ <lsp-update-capability>true</lsp-update-capability>
+ <include-db-version>false</include-db-version>
+ <initiation>true</initiation>
+ </stateful>
+ </stateful-tlv>
+ <reported-lsp>
+ <name>update-tunel</name>
+ <path>
+ <bandwidth>
+ <bandwidth>AAAAAA==</bandwidth>
+ <ignore>false</ignore>
+ <processing-rule>false</processing-rule>
+ </bandwidth>
+ <ero>
+ <ignore>false</ignore>
+ <processing-rule>false</processing-rule>
+ <subobject>
+ <loose>false</loose>
+ <ip-prefix>
+ <ip-prefix>195.20.160.40/32</ip-prefix>
+ </ip-prefix>
+ </subobject>
+ <subobject>
+ <loose>false</loose>
+ <ip-prefix>
+ <ip-prefix>201.20.160.43/32</ip-prefix>
+ </ip-prefix>
+ </subobject>
+ </ero>
+ <lspa>
+ <exclude-any>0</exclude-any>
+ <hold-priority>7</hold-priority>
+ <ignore>false</ignore>
+ <include-all>0</include-all>
+ <include-any>0</include-any>
+ <local-protection-desired>false</local-protection-desired>
+ <processing-rule>false</processing-rule>
+ <setup-priority>7</setup-priority>
+ </lspa>
+ </path>
+ <lsp xmlns="urn:opendaylight:params:xml:ns:yang:pcep:ietf:stateful">
+ <tlvs>
+ <symbolic-path-name>
+ <path-name>dXBkYXRlLXR1bmVs</path-name>
+ </symbolic-path-name>
+ <vs-tlv>
+ <enterprise-number>9</enterprise-number>
+ <linux-sub-tlvs>
+ <linux-value>5</linux-value>
+ </linux-sub-tlvs>
+ </vs-tlv>
+ </tlvs>
+ <delegate>true</delegate>
+ <processing-rule>false</processing-rule>
+ <ignore>false</ignore>
+ <operational>true</operational>
+ <sync>false</sync>
+ <plsp-id>40</plsp-id>
+ <remove>false</remove>
+ </lsp>
+ </reported-lsp>
+ <ip-address>39.39.39.39</ip-address>
+ </path-computation-client>
+ <node-id>pcc://39.39.39.39</node-id>
+ </node>
+</topology>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Copyright (c) 2013 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 -->
+<topology xmlns="urn:TBD:params:xml:ns:yang:network-topology">
+ <server-provided>true</server-provided>
+ <topology-id>example-pcep-topology</topology-id>
+ <topology-types/>
+ <node>
+ <path-computation-client xmlns="urn:opendaylight:params:xml:ns:yang:topology:pcep">
+ <state-sync>synchronized</state-sync>
+ <stateful-tlv>
+ <stateful>
+ <lsp-update-capability>true</lsp-update-capability>
+ <include-db-version>false</include-db-version>
+ <initiation>true</initiation>
+ </stateful>
+ </stateful-tlv>
+ <reported-lsp>
+ <name>update-tunel</name>
+ <path>
+ <bandwidth>
+ <bandwidth>AAAAAA==</bandwidth>
+ <ignore>false</ignore>
+ <processing-rule>false</processing-rule>
+ </bandwidth>
+ <ero>
+ <ignore>false</ignore>
+ <processing-rule>false</processing-rule>
+ <subobject>
+ <loose>false</loose>
+ <ip-prefix>
+ <ip-prefix>195.20.160.40/32</ip-prefix>
+ </ip-prefix>
+ </subobject>
+ <subobject>
+ <loose>false</loose>
+ <ip-prefix>
+ <ip-prefix>201.20.160.43/32</ip-prefix>
+ </ip-prefix>
+ </subobject>
+ </ero>
+ <lspa>
+ <exclude-any>0</exclude-any>
+ <hold-priority>7</hold-priority>
+ <ignore>false</ignore>
+ <include-all>0</include-all>
+ <include-any>0</include-any>
+ <local-protection-desired>false</local-protection-desired>
+ <processing-rule>false</processing-rule>
+ <setup-priority>7</setup-priority>
+ </lspa>
+ </path>
+ <lsp xmlns="urn:opendaylight:params:xml:ns:yang:pcep:ietf:stateful">
+ <tlvs>
+ <symbolic-path-name>
+ <path-name>dXBkYXRlLXR1bmVs</path-name>
+ </symbolic-path-name>
+ <vs-tlv>
+ <enterprise-number>9</enterprise-number>
+ <unix-sub-tlvs xmlns="urn:opendaylight:params:xml:ns:yang:network:topology-unix">
+ <unix-value>5</unix-value>
+ </unix-sub-tlvs>
+ </vs-tlv>
+ </tlvs>
+ <delegate>true</delegate>
+ <processing-rule>false</processing-rule>
+ <ignore>false</ignore>
+ <operational>true</operational>
+ <sync>false</sync>
+ <plsp-id>40</plsp-id>
+ <remove>false</remove>
+ </lsp>
+ </reported-lsp>
+ <ip-address>39.39.39.39</ip-address>
+ </path-computation-client>
+ <node-id>pcc://39.39.39.39</node-id>
+ </node>
+</topology>