import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
public ChoiceNodeCodecContext(final DataContainerCodecPrototype<ChoiceSchemaNode> prototype) {
super(prototype);
- Map<YangInstanceIdentifier.PathArgument, DataContainerCodecPrototype<?>> byYangCaseChildBuilder = new HashMap<>();
- Map<Class<?>, DataContainerCodecPrototype<?>> byClassBuilder = new HashMap<>();
- Map<Class<?>, DataContainerCodecPrototype<?>> byCaseChildClassBuilder = new HashMap<>();
- Set<Class<?>> potentialSubstitutions = new HashSet<>();
+ final Map<YangInstanceIdentifier.PathArgument, DataContainerCodecPrototype<?>> byYangCaseChildBuilder = new HashMap<>();
+ final Map<Class<?>, DataContainerCodecPrototype<?>> byClassBuilder = new HashMap<>();
+ final Map<Class<?>, DataContainerCodecPrototype<?>> byCaseChildClassBuilder = new HashMap<>();
+ final Set<Class<?>> potentialSubstitutions = new HashSet<>();
// Walks all cases for supplied choice in current runtime context
- for (Class<?> caze : factory().getRuntimeContext().getCases(getBindingClass())) {
+ for (final Class<?> caze : factory().getRuntimeContext().getCases(getBindingClass())) {
// We try to load case using exact match thus name
// and original schema must equals
- DataContainerCodecPrototype<ChoiceCaseNode> cazeDef = loadCase(caze);
+ final DataContainerCodecPrototype<ChoiceCaseNode> cazeDef = loadCase(caze);
// If we have case definition, this case is instantiated
// at current location and thus is valid in context of parent choice
if (cazeDef != null) {
byClassBuilder.put(cazeDef.getBindingClass(), cazeDef);
// Updates collection of case children
@SuppressWarnings("unchecked")
- Class<? extends DataObject> cazeCls = (Class<? extends DataObject>) caze;
- for (Class<? extends DataObject> cazeChild : BindingReflections.getChildrenClasses(cazeCls)) {
+ final Class<? extends DataObject> cazeCls = (Class<? extends DataObject>) caze;
+ for (final Class<? extends DataObject> cazeChild : BindingReflections.getChildrenClasses(cazeCls)) {
byCaseChildClassBuilder.put(cazeChild, cazeDef);
}
// Updates collection of YANG instance identifier to case
- for (DataSchemaNode cazeChild : cazeDef.getSchema().getChildNodes()) {
+ for (final DataSchemaNode cazeChild : cazeDef.getSchema().getChildNodes()) {
byYangCaseChildBuilder.put(new NodeIdentifier(cazeChild.getQName()), cazeDef);
}
} else {
}
}
- Map<Class<?>, DataContainerCodecPrototype<?>> bySubstitutionBuilder = new HashMap<>();
+ final Map<Class<?>, DataContainerCodecPrototype<?>> bySubstitutionBuilder = new HashMap<>();
/*
* Walks all cases which are not directly instantiated and
* tries to match them to instantiated cases - represent same data as instantiated case,
* binding specification, that if choice is in grouping schema path location is lost,
* and users may use incorrect case class using copy builders.
*/
- for(Class<?> substitution : potentialSubstitutions) {
- search: for(Entry<Class<?>, DataContainerCodecPrototype<?>> real : byClassBuilder.entrySet()) {
+ for(final Class<?> substitution : potentialSubstitutions) {
+ search: for(final Entry<Class<?>, DataContainerCodecPrototype<?>> real : byClassBuilder.entrySet()) {
if(BindingReflections.isSubstitutionFor(substitution, real.getKey())) {
bySubstitutionBuilder.put(substitution, real.getValue());
break search;
@SuppressWarnings("unchecked")
@Override
- public <DV extends DataObject> DataContainerCodecContext<DV, ?> streamChild(Class<DV> childClass) {
- DataContainerCodecPrototype<?> child = byClass.get(childClass);
- Preconditions.checkArgument(child != null,"Supplied class is not valid case",childClass);
- return (DataContainerCodecContext<DV, ?>) child.get();
+ public <DV extends DataObject> DataContainerCodecContext<DV, ?> streamChild(final Class<DV> childClass) {
+ final DataContainerCodecPrototype<?> child = byClass.get(childClass);
+ return (DataContainerCodecContext<DV, ?>) childNonNull(child,childClass,"Supplied class %s is not valid case").get();
}
@SuppressWarnings("unchecked")
@Override
public <DV extends DataObject> Optional<DataContainerCodecContext<DV, ?>> possibleStreamChild(
- Class<DV> childClass) {
- DataContainerCodecPrototype<?> child = byClass.get(childClass);
+ final Class<DV> childClass) {
+ final DataContainerCodecPrototype<?> child = byClass.get(childClass);
if(child != null) {
return Optional.<DataContainerCodecContext<DV,?>>of((DataContainerCodecContext<DV, ?>) child.get());
}
}
protected DataContainerCodecPrototype<ChoiceCaseNode> loadCase(final Class<?> childClass) {
- Optional<ChoiceCaseNode> childSchema = factory().getRuntimeContext().getCaseSchemaDefinition(schema(), childClass);
+ final Optional<ChoiceCaseNode> childSchema = factory().getRuntimeContext().getCaseSchemaDefinition(schema(), childClass);
if (childSchema.isPresent()) {
return DataContainerCodecPrototype.from(childClass, childSchema.get(), factory());
}
@Override
public NodeCodecContext<?> yangPathArgumentChild(final YangInstanceIdentifier.PathArgument arg) {
- DataContainerCodecPrototype<?> cazeProto = byYangCaseChild.get(arg);
- Preconditions.checkArgument(cazeProto != null, "Argument %s is not valid child of %s", arg, schema());
+ final DataContainerCodecPrototype<?> cazeProto = byYangCaseChild.get(arg);
+ childNonNull(cazeProto != null, arg,"Argument %s is not valid child of %s", arg, schema());
return cazeProto.get().yangPathArgumentChild(arg);
}
@SuppressWarnings("unchecked")
@Override
+ @Nullable
public D deserialize(final NormalizedNode<?, ?> data) {
- Preconditions
- .checkArgument(data instanceof org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode);
- NormalizedNodeContainer<?, ?, NormalizedNode<?,?>> casted = (NormalizedNodeContainer<?, ?, NormalizedNode<?,?>>) data;
- NormalizedNode<?, ?> first = Iterables.getFirst(casted.getValue(), null);
+ Preconditions.checkArgument(data instanceof ChoiceNode);
+ final NormalizedNodeContainer<?, ?, NormalizedNode<?,?>> casted = (NormalizedNodeContainer<?, ?, NormalizedNode<?,?>>) data;
+ final NormalizedNode<?, ?> first = Iterables.getFirst(casted.getValue(), null);
if (first == null) {
return null;
}
- DataContainerCodecPrototype<?> caze = byYangCaseChild.get(first.getIdentifier());
+ final DataContainerCodecPrototype<?> caze = byYangCaseChild.get(first.getIdentifier());
return (D) caze.get().deserialize(data);
}
- @Nullable DataContainerCodecContext<?,?> getCazeByChildClass(final @Nonnull Class<? extends DataObject> type) {
- final DataContainerCodecPrototype<?> protoCtx = byCaseChildClass.get(type);
- if(protoCtx != null) {
- return protoCtx.get();
- }
- return null;
+ DataContainerCodecContext<?, ?> getCazeByChildClass(final @Nonnull Class<? extends DataObject> type) {
+ final DataContainerCodecPrototype<?> protoCtx =
+ childNonNull(byCaseChildClass.get(type), type, "Class %s is not child of any cases for %s", type,
+ bindingArg());
+ return protoCtx.get();
}
@Override
- protected Object deserializeObject(NormalizedNode<?, ?> normalizedNode) {
+ protected Object deserializeObject(final NormalizedNode<?, ?> normalizedNode) {
return deserialize(normalizedNode);
}
@Override
- public PathArgument deserializePathArgument(YangInstanceIdentifier.PathArgument arg) {
+ public PathArgument deserializePathArgument(final YangInstanceIdentifier.PathArgument arg) {
Preconditions.checkArgument(getDomPathArgument().equals(arg));
return null;
}
@Override
public YangInstanceIdentifier.PathArgument serializePathArgument(
- PathArgument arg) {
+ final PathArgument arg) {
// FIXME: check for null, since binding container is null.
return getDomPathArgument();
}
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.util.List;
+import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeCachingCodec;
import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
import org.opendaylight.yangtools.yang.binding.DataObjectSerializer;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
return new BindingToNormalizedStreamWriter(this, domWriter);
}
+ @Nonnull
+ protected final <V> V childNonNull(@Nullable final V nullable, final YangInstanceIdentifier.PathArgument child,
+ final String message, final Object... args) {
+ if (nullable != null) {
+ return nullable;
+ }
+ MissingSchemaException.checkModulePresent(factory().getRuntimeContext().getSchemaContext(), child);
+ throw IncorrectNestingException.create(message, args);
+ }
+
+ @Nonnull
+ protected final <V> V childNonNull(@Nullable final V nullable, final QName child, final String message,
+ final Object... args) {
+ if (nullable != null) {
+ return nullable;
+ }
+ MissingSchemaException.checkModulePresent(factory().getRuntimeContext().getSchemaContext(), child);
+ throw IncorrectNestingException.create(message, args);
+ }
+
+ @Nonnull
+ protected final <V> V childNonNull(@Nullable final V nullable, final Class<?> childClass, final String message,
+ final Object... args) {
+ if (nullable != null) {
+ return nullable;
+ }
+ MissingSchemaForClassException.check(factory().getRuntimeContext(), childClass);
+ throw IncorrectNestingException.create(message, args);
+ }
+
DataObjectSerializer eventStreamSerializer() {
if(eventStreamSerializer == null) {
eventStreamSerializer = factory().getEventStreamSerializer(getBindingClass());
*/
package org.opendaylight.yangtools.binding.data.codec.impl;
-import org.opendaylight.yangtools.yang.binding.AugmentationHolder;
-
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
import org.opendaylight.yangtools.sal.binding.model.api.Type;
import org.opendaylight.yangtools.yang.binding.Augmentable;
import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.AugmentationHolder;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
}
}
}
- Preconditions.checkArgument(childProto != null, " Child %s is not valid child.",childClass);
- return (DataContainerCodecContext<DV, ?>) childProto.get();
+ return (DataContainerCodecContext<DV, ?>) childNonNull(childProto, childClass, " Child %s is not valid child.").get();
}
final Class<? extends DataObject> argType = arg.getType();
final DataContainerCodecPrototype<?> ctxProto = byBindingArgClass.get(argType);
- if(ctxProto != null) {
- final DataContainerCodecContext<?,?> context = ctxProto.get();
- if(context instanceof ChoiceNodeCodecContext) {
- final ChoiceNodeCodecContext<?> choice = (ChoiceNodeCodecContext<?>) context;
- final DataContainerCodecContext<?,?> caze = choice.getCazeByChildClass(arg.getType());
- if(caze != null) {
- choice.addYangPathArgument(arg, builder);
- caze.addYangPathArgument(arg, builder);
- return caze.bindingPathArgumentChild(arg, builder);
- }
- return null;
- }
- context.addYangPathArgument(arg, builder);
- return context;
+ final DataContainerCodecContext<?, ?> context =
+ childNonNull(ctxProto, argType, "Class %s is not valid child of %s", argType, getBindingClass()).get();
+ if (context instanceof ChoiceNodeCodecContext) {
+ final ChoiceNodeCodecContext<?> choice = (ChoiceNodeCodecContext<?>) context;
+ final DataContainerCodecContext<?, ?> caze = choice.getCazeByChildClass(arg.getType());
+ choice.addYangPathArgument(arg, builder);
+ caze.addYangPathArgument(arg, builder);
+ return caze.bindingPathArgumentChild(arg, builder);
}
- // Argument is not valid child.
- return null;
+ context.addYangPathArgument(arg, builder);
+ return context;
}
@SuppressWarnings("unchecked")
arg = new NodeIdentifier(arg.getNodeType());
}
final NodeContextSupplier childSupplier = byYang.get(arg);
- Preconditions.checkArgument(childSupplier != null, "Argument %s is not valid child of %s", arg, schema());
+ childNonNull(childSupplier != null, arg, "Argument %s is not valid child of %s", arg, schema());
return (NodeCodecContext<D>) childSupplier.get();
}
protected final LeafNodeCodecContext<?> getLeafChild(final String name) {
final LeafNodeCodecContext<?> value = leafChild.get(name);
- Preconditions.checkArgument(value != null, "Leaf %s is not valid for %s", name, getBindingClass());
- return value;
+ return IncorrectNestingException.checkNonNull(value, "Leaf %s is not valid for %s", name, getBindingClass());
}
private DataContainerCodecPrototype<?> loadChildPrototype(final Class<?> childClass) {
childSchema = null;
}
}
- Preconditions.checkArgument(childSchema != null, "Node %s does not have child named %s", schema(), childClass);
- return DataContainerCodecPrototype.from(childClass, childSchema, factory());
+ final DataSchemaNode nonNullChild =
+ childNonNull(childSchema, childClass, "Node %s does not have child named %s", schema(), childClass);
+ return DataContainerCodecPrototype.from(childClass, nonNullChild, factory());
}
private DataContainerCodecPrototype<?> getAugmentationPrototype(final Type value) {
--- /dev/null
+/*
+ * Copyright (c) 2015 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.binding.data.codec.impl;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/**
+ *
+ * Thrown where incorrect nesting of data structures was detected
+ * and was caused by user.
+ *
+ */
+public class IncorrectNestingException extends IllegalArgumentException {
+
+ private static final long serialVersionUID = 1L;
+
+ protected IncorrectNestingException(final String message) {
+ super(message);
+ }
+
+ public static IncorrectNestingException create(final String message, final Object... args) {
+ return new IncorrectNestingException(String.format(message, args));
+ }
+
+ public static void check(final boolean check, final String message, final Object... args) {
+ if(!check) {
+ throw IncorrectNestingException.create(message, args);
+ }
+ }
+
+ @Nonnull
+ public static <V> V checkNonNull(@Nullable final V nullable, final String message, final Object... args) {
+ if(nullable != null) {
+ return nullable;
+ }
+ throw IncorrectNestingException.create(message, args);
+ }
+}
}
@Override
- public BindingCodecTreeNode<?> bindingPathArgumentChild(PathArgument arg,
- List<YangInstanceIdentifier.PathArgument> builder) {
- return null;
+ public BindingCodecTreeNode<?> bindingPathArgumentChild(final PathArgument arg,
+ final List<YangInstanceIdentifier.PathArgument> builder) {
+ throw new IllegalArgumentException("Leaf does not have children");
}
@Override
public BindingNormalizedNodeCachingCodec<D> createCachingCodec(
- ImmutableCollection<Class<? extends DataObject>> cacheSpecifier) {
- return null;
+ final ImmutableCollection<Class<? extends DataObject>> cacheSpecifier) {
+ throw new UnsupportedOperationException("Leaves does not support caching codec.");
}
@Override
public Class<D> getBindingClass() {
- return null;
+ throw new UnsupportedOperationException("Leaf does not have DataObject representation");
}
@Override
- public NormalizedNode<?, ?> serialize(D data) {
+ public NormalizedNode<?, ?> serialize(final D data) {
throw new UnsupportedOperationException("Separete serialization of leaf node is not supported.");
}
@Override
- public void writeAsNormalizedNode(D data, NormalizedNodeStreamWriter writer) {
+ public void writeAsNormalizedNode(final D data, final NormalizedNodeStreamWriter writer) {
throw new UnsupportedOperationException("Separete serialization of leaf node is not supported.");
}
@Override
- public <E extends DataObject> BindingCodecTreeNode<E> streamChild(Class<E> childClass) {
- return null;
+ public <E extends DataObject> BindingCodecTreeNode<E> streamChild(final Class<E> childClass) {
+ throw new IllegalArgumentException("Leaf does not have children");
}
@Override
public <E extends DataObject> Optional<? extends BindingCodecTreeNode<E>> possibleStreamChild(
- Class<E> childClass) {
- return null;
+ final Class<E> childClass) {
+ throw new IllegalArgumentException("Leaf does not have children");
}
@Override
- public BindingCodecTreeNode<?> yangPathArgumentChild(
- org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument child) {
- return null;
+ public BindingCodecTreeNode<?> yangPathArgumentChild(final YangInstanceIdentifier.PathArgument child) {
+ throw new IllegalArgumentException("Leaf does not have children");
}
@Override
- protected Object deserializeObject(NormalizedNode<?, ?> normalizedNode) {
+ protected Object deserializeObject(final NormalizedNode<?, ?> normalizedNode) {
if (normalizedNode instanceof LeafNode<?>) {
return valueCodec.deserialize(normalizedNode.getValue());
} else if(normalizedNode instanceof LeafSetNode<?>) {
@SuppressWarnings("unchecked")
- Collection<LeafSetEntryNode<Object>> domValues = ((LeafSetNode<Object>) normalizedNode).getValue();
- List<Object> result = new ArrayList<>(domValues.size());
- for (LeafSetEntryNode<Object> valueNode : domValues) {
+ final Collection<LeafSetEntryNode<Object>> domValues = ((LeafSetNode<Object>) normalizedNode).getValue();
+ final List<Object> result = new ArrayList<>(domValues.size());
+ for (final LeafSetEntryNode<Object> valueNode : domValues) {
result.add(valueCodec.deserialize(valueNode.getValue()));
}
return result;
}
@Override
- public InstanceIdentifier.PathArgument deserializePathArgument(YangInstanceIdentifier.PathArgument arg) {
+ public InstanceIdentifier.PathArgument deserializePathArgument(final YangInstanceIdentifier.PathArgument arg) {
Preconditions.checkArgument(getDomPathArgument().equals(arg));
return null;
}
@Override
- public YangInstanceIdentifier.PathArgument serializePathArgument(InstanceIdentifier.PathArgument arg) {
+ public YangInstanceIdentifier.PathArgument serializePathArgument(final InstanceIdentifier.PathArgument arg) {
return getDomPathArgument();
}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.binding.data.codec.impl;
+
+import com.google.common.base.Preconditions;
+import java.util.Set;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Thrown when codec was used with data which are not modeled
+ * and available in schema used by codec.
+ *
+ */
+public class MissingSchemaException extends IllegalArgumentException {
+
+ private static final long serialVersionUID = 1L;
+
+ protected MissingSchemaException(final String msg) {
+ super(msg);
+ }
+
+ private static MissingSchemaException create(final String format, final Object... args) {
+ return new MissingSchemaException(String.format(format, args));
+ }
+
+ static void checkModulePresent(final SchemaContext schemaContext, final QName name) {
+ if(schemaContext.findModuleByNamespaceAndRevision(name.getNamespace(), name.getRevision()) == null) {
+ throw MissingSchemaException.create("Module %s is not present in current schema context.",name.getModule());
+ }
+ }
+
+ static void checkModulePresent(final SchemaContext schemaContext, final YangInstanceIdentifier.PathArgument child) {
+ checkModulePresent(schemaContext, extractName(child));
+ }
+
+ private static QName extractName(final PathArgument child) {
+ if(child instanceof YangInstanceIdentifier.AugmentationIdentifier) {
+ final Set<QName> children = ((YangInstanceIdentifier.AugmentationIdentifier) child).getPossibleChildNames();
+ Preconditions.checkArgument(!children.isEmpty(),"Augmentation without childs must not be used in data");
+ return children.iterator().next();
+ }
+ return child.getNodeType();
+ }
+
+
+
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.binding.data.codec.impl;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+
+/**
+ *
+ * Thrown when Java Binding class was used in data for which codec does not
+ * have schema.
+ *
+ * By serialization / deserialization of this exception {@link #getBindingClass()}
+ * will return null.
+ *
+ */
+public class MissingSchemaForClassException extends MissingSchemaException {
+
+ private static final long serialVersionUID = 1L;
+
+ private final transient Class<?> bindingClass;
+
+ private MissingSchemaForClassException(final Class<?> clz) {
+ super(String.format("Schema is not available for %s", clz));
+ this.bindingClass = Preconditions.checkNotNull(clz);
+ }
+
+ static MissingSchemaForClassException forClass(final Class<?> clz) {
+ return new MissingSchemaForClassException(clz);
+ }
+
+ public Class<?> getBindingClass() {
+ return bindingClass;
+ }
+
+ public static void check(final BindingRuntimeContext runtimeContext, final Class<?> bindingClass) {
+ final Object schema;
+ if (Augmentation.class.isAssignableFrom(bindingClass)) {
+ schema = runtimeContext.getAugmentationDefinition(bindingClass);
+ } else {
+ schema = runtimeContext.getSchemaDefinition(bindingClass);
+ }
+ if(schema == null) {
+ throw MissingSchemaForClassException.forClass(bindingClass);
+ }
+ }
+}
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import com.google.common.base.Throwables;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
+import com.google.common.util.concurrent.UncheckedExecutionException;
import org.opendaylight.yangtools.util.ClassLoaderUtils;
import org.opendaylight.yangtools.yang.binding.BindingMapping;
import org.opendaylight.yangtools.yang.binding.ChildOf;
@Override
public DataContainerCodecContext<?,?> load(final QName qname) {
final DataSchemaNode childSchema = schema().getDataChildByName(qname);
- Preconditions.checkArgument(childSchema != null, "Argument %s is not valid child of %s", qname,
- schema());
-
+ childNonNull(childSchema, qname,"Argument %s is not valid child of %s", qname,schema());
if (childSchema instanceof DataNodeContainer || childSchema instanceof ChoiceSchemaNode) {
@SuppressWarnings("rawtypes")
final Class childCls = factory().getRuntimeContext().getClassForSchema(childSchema);
@SuppressWarnings("unchecked")
@Override
- public <DV extends DataObject> DataContainerCodecContext<DV, ?> streamChild(Class<DV> childClass)
+ public <DV extends DataObject> DataContainerCodecContext<DV, ?> streamChild(final Class<DV> childClass)
throws IllegalArgumentException {
/* FIXME: This is still not solved for RPCs
* TODO: Probably performance wise RPC, Data and Notification loading cache
if (Notification.class.isAssignableFrom(childClass)) {
return (DataContainerCodecContext<DV, ?>) getNotification((Class<? extends Notification>)childClass);
}
- return (DataContainerCodecContext<DV, ?>) childrenByClass.getUnchecked(childClass);
+ return (DataContainerCodecContext<DV, ?>) getOrRethrow(childrenByClass,childClass);
}
@Override
@Override
public DataContainerCodecContext<?,?> yangPathArgumentChild(final PathArgument arg) {
- return childrenByQName.getUnchecked(arg.getNodeType());
+ return getOrRethrow(childrenByQName,arg.getNodeType());
}
@Override
ContainerNodeCodecContext<?> getRpc(final Class<? extends DataContainer> rpcInputOrOutput) {
- return rpcDataByClass.getUnchecked(rpcInputOrOutput);
+ return getOrRethrow(rpcDataByClass, rpcInputOrOutput);
}
NotificationCodecContext<?> getNotification(final Class<? extends Notification> notification) {
- return notificationsByClass.getUnchecked(notification);
+ return getOrRethrow(notificationsByClass, notification);
}
NotificationCodecContext<?> getNotification(final SchemaPath notification) {
- return notificationsByPath.getUnchecked(notification);
+ return getOrRethrow(notificationsByPath, notification);
}
ContainerNodeCodecContext<?> getRpc(final SchemaPath notification) {
- return rpcDataByPath.getUnchecked(notification);
+ return getOrRethrow(rpcDataByPath, notification);
}
private DataContainerCodecContext<?,?> createDataTreeChildContext(final Class<?> key) {
final Class<Object> parent = ClassLoaderUtils.findFirstGenericArgument(key, ChildOf.class);
- Preconditions.checkArgument(DataRoot.class.isAssignableFrom(parent));
+ IncorrectNestingException.check(DataRoot.class.isAssignableFrom(parent), "Class %s is not top level item.", key);
final QName qname = BindingReflections.findQName(key);
- final DataSchemaNode childSchema = schema().getDataChildByName(qname);
+ final DataSchemaNode childSchema = childNonNull(schema().getDataChildByName(qname),key,"%s is not top-level item.",key);
return DataContainerCodecPrototype.from(key, childSchema, factory()).get();
}
}
@Override
- protected Object deserializeObject(NormalizedNode<?, ?> normalizedNode) {
+ protected Object deserializeObject(final NormalizedNode<?, ?> normalizedNode) {
throw new UnsupportedOperationException("Unable to deserialize root");
}
@Override
- public InstanceIdentifier.PathArgument deserializePathArgument(YangInstanceIdentifier.PathArgument arg) {
+ public InstanceIdentifier.PathArgument deserializePathArgument(final YangInstanceIdentifier.PathArgument arg) {
Preconditions.checkArgument(arg == null);
return null;
}
@Override
- public YangInstanceIdentifier.PathArgument serializePathArgument(InstanceIdentifier.PathArgument arg) {
+ public YangInstanceIdentifier.PathArgument serializePathArgument(final InstanceIdentifier.PathArgument arg) {
Preconditions.checkArgument(arg == null);
return null;
}
+ private static <K,V> V getOrRethrow(final LoadingCache<K, V> cache, final K key) {
+ try {
+ return cache.getUnchecked(key);
+ } catch (final UncheckedExecutionException e) {
+ final Throwable cause = e.getCause();
+ if(cause != null) {
+ Throwables.propagateIfPossible(cause);
+ }
+ throw e;
+ }
+ }
+
}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.binding.data.codec.test;
+
+import javassist.ClassPool;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.binding.data.codec.impl.IncorrectNestingException;
+import org.opendaylight.yangtools.binding.data.codec.impl.MissingSchemaException;
+import org.opendaylight.yangtools.binding.data.codec.impl.MissingSchemaForClassException;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+
+public class ExceptionReportingTest {
+
+
+ private static final BindingNormalizedNodeCodecRegistry EMPTY_SCHEMA_CODEC = codec();
+ private static final BindingNormalizedNodeCodecRegistry ONLY_TOP_CODEC = codec(Top.class);
+ private static final BindingNormalizedNodeCodecRegistry FULL_CODEC = codec(TreeComplexUsesAugment.class);
+
+ private static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
+ private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier
+ .builder(Top.class).child(TopLevelList.class, TOP_FOO_KEY).build();
+ private static final InstanceIdentifier<TreeLeafOnlyAugment> BA_TREE_LEAF_ONLY =
+ BA_TOP_LEVEL_LIST.augmentation(TreeLeafOnlyAugment.class);
+
+ private static final QName TOP_QNAME =
+ QName.create("urn:opendaylight:params:xml:ns:yang:yangtools:test:binding", "2014-07-01", "top");
+ private static final YangInstanceIdentifier BI_TOP_PATH = YangInstanceIdentifier.builder().node(TOP_QNAME).build();
+ private static final YangInstanceIdentifier BI_TREE_LEAF_ONLY = FULL_CODEC.toYangInstanceIdentifier(BA_TREE_LEAF_ONLY);
+
+
+ @Test(expected=MissingSchemaException.class)
+ public void testDOMTop() {
+ EMPTY_SCHEMA_CODEC.fromYangInstanceIdentifier(BI_TOP_PATH);
+ }
+
+ @Test(expected=MissingSchemaException.class)
+ public void testDOMAugment() {
+ EMPTY_SCHEMA_CODEC.fromYangInstanceIdentifier(BI_TREE_LEAF_ONLY);
+ }
+
+ @Test(expected=MissingSchemaForClassException.class)
+ public void testBindingTop() {
+ EMPTY_SCHEMA_CODEC.toYangInstanceIdentifier(BA_TOP_LEVEL_LIST);
+ }
+
+ @Test(expected=MissingSchemaForClassException.class)
+ public void testBindingAugment() {
+ ONLY_TOP_CODEC.toYangInstanceIdentifier(BA_TREE_LEAF_ONLY);
+ }
+
+ @Test(expected=IncorrectNestingException.class)
+ public void testBindingSkippedRoot() {
+ FULL_CODEC.toYangInstanceIdentifier(InstanceIdentifier.create(TopLevelList.class));
+ }
+
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ @Test(expected=IncorrectNestingException.class)
+ public void testBindingIncorrectAugment() {
+ FULL_CODEC.toYangInstanceIdentifier(InstanceIdentifier.create(Top.class).augmentation((Class) TreeComplexUsesAugment.class));
+ }
+
+
+ private static BindingNormalizedNodeCodecRegistry codec(final Class<?>... classes ) {
+ final ModuleInfoBackedContext ctx = ModuleInfoBackedContext.create();
+ for(final Class<?> clazz : classes) {
+ YangModuleInfo modInfo;
+ try {
+ modInfo = BindingReflections.getModuleInfo(clazz);
+ ctx.registerModuleInfo(modInfo);
+ } catch (final Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ final SchemaContext schema = ctx.tryToCreateSchemaContext().get();
+ final BindingRuntimeContext runtimeCtx = BindingRuntimeContext.create(ctx, schema);
+ final JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+ final BindingNormalizedNodeCodecRegistry registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+ registry.onBindingRuntimeContextUpdated(runtimeCtx);
+ return registry;
+ }
+
+}
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+import javax.annotation.Nullable;
import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl;
import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy;
import org.opendaylight.yangtools.yang.binding.Augmentation;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.AugmentationSchemaProxy;
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.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaNode;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.util.EffectiveAugmentationSchema;
import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
* schema.
*
* @param augClass Augmentation class
- * @return Schema of augmentation
- * @throws IllegalArgumentException If supplied class is not an augmentation or current context does not contain schema for augmentation.
+ * @return Schema of augmentation or null if augmentaiton is not known in this context
+ * @throws IllegalArgumentException If supplied class is not an augmentation
*/
- public AugmentationSchema getAugmentationDefinition(final Class<?> augClass) throws IllegalArgumentException {
+ public @Nullable AugmentationSchema getAugmentationDefinition(final Class<?> augClass) throws IllegalArgumentException {
Preconditions.checkArgument(Augmentation.class.isAssignableFrom(augClass), "Class %s does not represent augmentation", augClass);
- final AugmentationSchema ret = augmentationToSchema.get(referencedType(augClass));
- Preconditions.checkArgument(ret != null, "Supplied augmentation %s is not valid in current context", augClass);
- return ret;
+ return augmentationToSchema.get(referencedType(augClass));
}
/**
public Entry<AugmentationIdentifier, AugmentationSchema> getResolvedAugmentationSchema(final DataNodeContainer target,
final Class<? extends Augmentation<?>> aug) {
final AugmentationSchema origSchema = getAugmentationDefinition(aug);
+ Preconditions.checkArgument(origSchema != null, "Augmentation %s is not known in current schema context",aug);
/*
* FIXME: Validate augmentation schema lookup
*
}
final AugmentationIdentifier identifier = new AugmentationIdentifier(childNames);
- final AugmentationSchema proxy = new AugmentationSchemaProxy(origSchema, realChilds);
+ final AugmentationSchema proxy = new EffectiveAugmentationSchema(origSchema, realChilds);
return new AbstractMap.SimpleEntry<>(identifier, proxy);
}