+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
package org.opendaylight.yangtools.yang.data.impl.tree;
import java.io.InputStream;
import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
/**
- * @author Lukas Sedlak <lsedlak@cisco.com>
+ * @author Lukas Sedlak <lsedlak@cisco.com>
*/
public class BenchmarkModel {
*
* JMH is used for microbenchmarking.
*
- * @author Lukas Sedlak <lsedlak@cisco.com>
+ * @author Lukas Sedlak <lsedlak@cisco.com>
*
* @see <a href="http://openjdk.java.net/projects/code-tools/jmh/">JMH</a>
*/
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.List;
import java.util.Map;
import java.util.Set;
+import org.opendaylight.yangtools.sal.binding.generator.impl.YangTemplate;
import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
import org.opendaylight.yangtools.binding.generator.util.BindingTypes;
import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl;
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);
}
*/
package org.opendaylight.yangtools.yang.data.impl.schema;
-import com.google.common.base.Preconditions;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
/**
}
void setResult(final NormalizedNode<?, ?> result) {
- Preconditions.checkState(!this.finished, "Result was already set.");
+ if (finished) {
+ throw new ResultAlreadySetException("Normalized Node result was already set.", this.result);
+ }
this.finished = true;
this.result = result;
}
--- /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.yang.data.impl.schema;
+
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public class ResultAlreadySetException extends IllegalStateException {
+ private final NormalizedNode<?, ?> resultData;
+
+ public ResultAlreadySetException(String message, NormalizedNode<?, ?> resultData) {
+ this(message, resultData, null);
+ }
+
+ public ResultAlreadySetException(String message, NormalizedNode<?, ?> resultData, Throwable cause) {
+ super(message, cause);
+ this.resultData = resultData;
+ }
+
+ public NormalizedNode<?, ?> getResultData() {
+ return resultData;
+ }
+}
*/
package org.opendaylight.yangtools.yang.data.impl.schema.transform;
+import javax.annotation.Nullable;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
/**
* @param schema
* @return NormalizedNode as a result of parsing list of E elements with schema S
*/
+ @Nullable
N parse(Iterable<E> xmlDom, S schema);
}
* @param <E> type of elements to be parsed
*/
public abstract class AugmentationNodeBaseParser<E> extends
- BaseDispatcherParser<E,AugmentationNode, AugmentationSchema> {
+ BaseDispatcherParser<E, YangInstanceIdentifier.AugmentationIdentifier, AugmentationNode, AugmentationSchema> {
+
+ public AugmentationNodeBaseParser(final BuildingStrategy<YangInstanceIdentifier.AugmentationIdentifier, AugmentationNode> buildingStrategy) {
+ super(buildingStrategy);
+ }
+
+ public AugmentationNodeBaseParser() {}
@Override
protected final DataContainerNodeBuilder<YangInstanceIdentifier.AugmentationIdentifier, AugmentationNode> getBuilder(final AugmentationSchema schema) {
import java.util.List;
import java.util.Map;
import java.util.Set;
+import javax.annotation.Nullable;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.AttributesBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
import org.opendaylight.yangtools.yang.model.util.EffectiveAugmentationSchema;
/**
* Abstract(base) Parser for DataContainerNodes e.g. ContainerNode, AugmentationNode.
*/
-public abstract class BaseDispatcherParser<E, N extends DataContainerNode<?>, S>
- implements ToNormalizedNodeParser<E, N, S> {
+public abstract class BaseDispatcherParser<E, P extends YangInstanceIdentifier.PathArgument, N extends DataContainerNode<P>, S>
+ implements ExtensibleParser<P, E, N, S> {
+
+ private final BuildingStrategy<P, N> buildingStrategy;
+
+ public BaseDispatcherParser(final BuildingStrategy<P, N> buildingStrategy) {
+ this.buildingStrategy = buildingStrategy;
+ }
+
+ public BaseDispatcherParser() {
+ this.buildingStrategy = new SimpleBuildingStrategy<>();
+ }
/**
*
* @param schema
* @return New(empty) instance of a builder to build node identified by schema.
*/
- protected abstract DataContainerNodeBuilder<?, N> getBuilder(S schema);
+ protected abstract DataContainerNodeBuilder<P, N> getBuilder(S schema);
/**
*
*/
protected abstract NodeParserDispatcher<E> getDispatcher();
+ /**
+ * can return null only if you override ParsingStrategy and explicitely return null
+ * @param elements
+ * @param schema
+ * @return
+ */
+ @Nullable
@Override
public N parse(final Iterable<E> elements, final S schema) {
checkAtLeastOneNode(schema, elements);
- DataContainerNodeBuilder<?, N> containerBuilder = getBuilder(schema);
+ DataContainerNodeBuilder<P, N> containerBuilder = getBuilder(schema);
// Map child nodes to QName
LinkedListMultimap<QName, E> mappedChildElements = mapChildElements(elements);
Map<QName, ChoiceSchemaNode> mappedChoiceChildNodes = mapChildElementsFromChoices(schema);
LinkedListMultimap<ChoiceSchemaNode, E> choicesToElements = LinkedListMultimap.create();
+ Map<QName, String> attributes = getAttributes(elements.iterator().next());
+ if (containerBuilder instanceof AttributesBuilder) {
+ final int size = Iterables.size(elements);
+ Preconditions.checkArgument(size == 1, "Unexpected number of elements: %s, should be 1 for: %s",
+ size, schema);
+ ((AttributesBuilder<?>) containerBuilder).withAttributes(attributes);
+ }
+
+ //parse keys first
+ if (schema instanceof ListSchemaNode) {
+ for (QName qname : ((ListSchemaNode) schema).getKeyDefinition()) {
+ if(mappedChildElements.get(qname.withoutRevision()).isEmpty()) {
+ continue;
+ }
+
+ DataSchemaNode childSchema = getSchemaForChild(schema, qname);
+ List<E> childrenForQName = mappedChildElements.removeAll(qname.withoutRevision());
+
+
+ DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> optionalChildNode = getDispatcher()
+ .dispatchChildElement(childSchema, childrenForQName);
+ if (optionalChildNode != null) {
+ containerBuilder.withChild(optionalChildNode);
+ }
+ }
+ }
+
+ //stage attribues for strategy before going deeper in the recursion
+ buildingStrategy.prepareAttributes(attributes, containerBuilder);
+
// process Child nodes
for (QName childPartialQName : mappedChildElements.keySet()) {
DataSchemaNode childSchema = getSchemaForChild(schema, childPartialQName);
choicesToElements.putAll(choiceSchema, childrenForQName);
// Regular child nodes
} else {
- DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> builtChildNode = getDispatcher()
+ DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> optionalChildNode = getDispatcher()
.dispatchChildElement(childSchema, childrenForQName);
- containerBuilder.withChild(builtChildNode);
+ if (optionalChildNode != null) {
+ containerBuilder.withChild(optionalChildNode);
+ }
}
}
// TODO ordering is not preserved for choice and augment elements
for (ChoiceSchemaNode choiceSchema : choicesToElements.keySet()) {
- containerBuilder.withChild(getDispatcher().dispatchChildElement(choiceSchema,
- choicesToElements.get(choiceSchema)));
+ DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> optionalChild = getDispatcher()
+ .dispatchChildElement(choiceSchema, choicesToElements.get(choiceSchema));
+ if (optionalChild != null) {
+ containerBuilder.withChild(optionalChild);
+ }
}
for (AugmentationSchema augmentSchema : augmentsToElements.keySet()) {
Set<DataSchemaNode> realChildSchemas = getRealSchemasForAugment(schema, augmentSchema);
EffectiveAugmentationSchema augSchemaProxy = new EffectiveAugmentationSchema(augmentSchema, realChildSchemas);
- containerBuilder.withChild(getDispatcher().dispatchChildElement(augSchemaProxy, augmentsToElements.get(augmentSchema)));
+ DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> optionalChild = getDispatcher()
+ .dispatchChildElement(augSchemaProxy, augmentsToElements.get(augmentSchema));
+ if (optionalChild != null) {
+ containerBuilder.withChild(optionalChild);
+ }
}
- if (containerBuilder instanceof AttributesBuilder) {
- final int size = Iterables.size(elements);
- Preconditions.checkArgument(size == 1, "Unexpected number of elements: %s, should be 1 for: %s",
- size, schema);
- ((AttributesBuilder<?>) containerBuilder).withAttributes(getAttributes(elements.iterator().next()));
- }
+ return buildingStrategy.build(containerBuilder);
+ }
- return containerBuilder.build();
+ @Override
+ public BuildingStrategy<P, N> getBuildingStrategy() {
+ return buildingStrategy;
}
protected Map<QName, String> getAttributes(final E e) {
Preconditions.checkArgument(!Iterables.isEmpty(childNodes),
"Node detected 0 times, should be at least 1, identified by: %s, found: %s", schema, childNodes);
}
+
+ public static class SimpleBuildingStrategy<P extends YangInstanceIdentifier.PathArgument, N extends DataContainerNode<P>> implements BuildingStrategy<P, N> {
+ @Override
+ public N build(final NormalizedNodeBuilder<P, ?, N> builder) {
+ return builder.build();
+ }
+
+ @Override
+ public void prepareAttributes(final Map<QName, String> attributes, final NormalizedNodeBuilder<P, ?, N> containerBuilder) {
+ // NOOP
+ }
+ }
}
*
* @param <E> type of elements to be parsed
*/
-public abstract class ChoiceNodeBaseParser<E> extends BaseDispatcherParser<E, ChoiceNode, ChoiceSchemaNode> {
+public abstract class ChoiceNodeBaseParser<E> extends BaseDispatcherParser<E, YangInstanceIdentifier.NodeIdentifier, ChoiceNode, ChoiceSchemaNode> {
+
+ protected ChoiceNodeBaseParser() {}
+
+ protected ChoiceNodeBaseParser(final BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, ChoiceNode> buildingStrategy) {
+ super(buildingStrategy);
+ }
@Override
protected final DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifier, ChoiceNode> getBuilder(
* @param <E> type of elements to be parsed
*/
public abstract class ContainerNodeBaseParser<E> extends
- BaseDispatcherParser<E, ContainerNode, ContainerSchemaNode> {
+ BaseDispatcherParser<E, YangInstanceIdentifier.NodeIdentifier, ContainerNode, ContainerSchemaNode> {
+
+ public ContainerNodeBaseParser() {}
+
+ public ContainerNodeBaseParser(final BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, ContainerNode> buildingStrategy) {
+ super(buildingStrategy);
+ }
@Override
protected final DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifier, ContainerNode> getBuilder(
@Override
protected abstract Map<QName, String> getAttributes(E e);
+
}
--- /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.yang.data.impl.schema.transform.base.parser;
+
+import java.util.Map;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+
+/**
+ * Extensible parser allows its subclasses to customize the building process of normalized nodes
+ *
+ * @param <P>
+ * @param <E>
+ * @param <N>
+ * @param <S>
+ */
+public interface ExtensibleParser<P extends YangInstanceIdentifier.PathArgument, E, N extends NormalizedNode<P, ?>, S>
+ extends ToNormalizedNodeParser<E, N, S> {
+
+ /**
+ * Provide building strategy
+ */
+ BuildingStrategy<P, N> getBuildingStrategy();
+
+ /**
+ * Building strategy serves as a set of hooks into the parsing process.
+ *
+ * @param <P>
+ * @param <N>
+ */
+ interface BuildingStrategy<P extends YangInstanceIdentifier.PathArgument, N extends NormalizedNode<P, ?>> {
+
+ /**
+ * Build normalized node from its builder
+ *
+ * @param builder filled builder for node
+ * @return built normalized node or null if the node should not be built
+ */
+ @Nullable N build(NormalizedNodeBuilder<P, ?, N> builder);
+
+ /**
+ * Hook for subclasses to handle attributes associated with current node. This is called before the build method
+ * and allows subclasses to react to node's attributes e.g. modification operation
+ *
+ * @param attributes attributes for node
+ * @param containerBuilder builder created for node. Can be modified according to attributes e.g. remove attribute
+ */
+ void prepareAttributes(Map<QName, String> attributes, NormalizedNodeBuilder<P, ?, N> containerBuilder);
+ }
+}
*/
package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
import java.util.Map;
-
import org.opendaylight.yangtools.yang.common.QName;
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.LeafNode;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeAttrBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Iterables;
-
/**
* Abstract(base) parser for LeafNodes, parses elements of type E.
*
* @param <E> type of elements to be parsed
*/
-public abstract class LeafNodeBaseParser<E> implements
- ToNormalizedNodeParser<E, LeafNode<?>, LeafSchemaNode> {
+public abstract class LeafNodeBaseParser<E> implements ExtensibleParser<NodeIdentifier, E, LeafNode<?>, LeafSchemaNode> {
+
+ private final BuildingStrategy<NodeIdentifier, LeafNode<?>> buildingStrategy;
+
+ public LeafNodeBaseParser() {
+ buildingStrategy = new SimpleLeafBuildingStrategy();
+ }
+ public LeafNodeBaseParser(final BuildingStrategy<NodeIdentifier, LeafNode<?>> buildingStrategy) {
+ this.buildingStrategy = buildingStrategy;
+ }
+
+ @SuppressWarnings("unchecked")
@Override
public final LeafNode<?> parse(Iterable<E> elements, LeafSchemaNode schema) {
final int size = Iterables.size(elements);
final E e = elements.iterator().next();
Object value = parseLeaf(e, schema);
- NormalizedNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifier,Object,LeafNode<Object>> leafBuilder = Builders.leafBuilder(schema);
+ NormalizedNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifier, Object, LeafNode<Object>> leafBuilder =
+ Builders.leafBuilder(schema);
leafBuilder.withAttributes(getAttributes(e));
- return leafBuilder.withValue(value).build();
+ final BuildingStrategy rawBuildingStrat = buildingStrategy;
+ return (LeafNode<?>) rawBuildingStrat.build(leafBuilder.withValue(value));
}
/**
* @return attributes mapped to QNames
*/
protected abstract Map<QName, String> getAttributes(E e);
+
+ @Override
+ public BuildingStrategy<NodeIdentifier, LeafNode<?>> getBuildingStrategy() {
+ return buildingStrategy;
+ }
+
+ public static class SimpleLeafBuildingStrategy implements BuildingStrategy<NodeIdentifier, LeafNode<?>> {
+ @Override
+ public LeafNode<?> build(final NormalizedNodeBuilder<NodeIdentifier, ?, LeafNode<?>> builder) {
+ return builder.build();
+ }
+
+ @Override
+ public void prepareAttributes(final Map<QName, String> attributes, final NormalizedNodeBuilder<NodeIdentifier, ?, LeafNode<?>> containerBuilder) {
+ // NOOP
+ }
+ }
}
*/
package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
import java.util.Map;
-
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeAttrBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Iterables;
-
/**
* Abstract(base) parser for LeafSetEntryNodes, parses elements of type E.
*
* @param <E> type of elements to be parsed
*/
-public abstract class LeafSetEntryNodeBaseParser<E> implements
- ToNormalizedNodeParser<E, LeafSetEntryNode<?>, LeafListSchemaNode> {
+public abstract class LeafSetEntryNodeBaseParser<E> implements ExtensibleParser<YangInstanceIdentifier.NodeWithValue, E, LeafSetEntryNode<?>, LeafListSchemaNode> {
+
+ private final BuildingStrategy<YangInstanceIdentifier.NodeWithValue, LeafSetEntryNode<?>> buildingStrategy;
+
+ public LeafSetEntryNodeBaseParser() {
+ buildingStrategy = new SimpleLeafSetEntryBuildingStrategy();
+ }
+ public LeafSetEntryNodeBaseParser(final BuildingStrategy<YangInstanceIdentifier.NodeWithValue, LeafSetEntryNode<?>> buildingStrategy) {
+ this.buildingStrategy = buildingStrategy;
+ }
+
+ @SuppressWarnings("unchecked")
@Override
- public final LeafSetEntryNode<Object> parse(Iterable<E> elements, LeafListSchemaNode schema) {
+ public final LeafSetEntryNode<?> parse(Iterable<E> elements, LeafListSchemaNode schema) {
final int size = Iterables.size(elements);
Preconditions.checkArgument(size == 1, "Xml elements mapped to leaf node illegal count: %s", size);
NormalizedNodeAttrBuilder<YangInstanceIdentifier.NodeWithValue, Object, LeafSetEntryNode<Object>> leafEntryBuilder = Builders
.leafSetEntryBuilder(schema);
leafEntryBuilder.withAttributes(getAttributes(e));
+ leafEntryBuilder.withValue(value);
+
+ final BuildingStrategy rawBuildingStrat = buildingStrategy;
+ return (LeafSetEntryNode<?>) rawBuildingStrat.build(leafEntryBuilder);
+ }
- return leafEntryBuilder.withValue(value).build();
+ @Override
+ public BuildingStrategy<NodeWithValue, LeafSetEntryNode<?>> getBuildingStrategy() {
+ return buildingStrategy;
}
/**
*/
protected abstract Map<QName, String> getAttributes(E e);
+ public static class SimpleLeafSetEntryBuildingStrategy implements BuildingStrategy<YangInstanceIdentifier.NodeWithValue, LeafSetEntryNode<?>> {
+
+ @Override
+ public LeafSetEntryNode<?> build(final NormalizedNodeBuilder<NodeWithValue, ?, LeafSetEntryNode<?>> builder) {
+ return builder.build();
+ }
+
+ @Override
+ public void prepareAttributes(final Map<QName, String> attributes, final NormalizedNodeBuilder<NodeWithValue, ?, LeafSetEntryNode<?>> containerBuilder) {
+ }
+ }
}
package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser;
import java.util.Collections;
-
import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
import java.util.Map;
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.schema.DataContainerNode;
import org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils;
import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
* @param <E>
* type of elements to be parsed
*/
-public abstract class ListEntryNodeBaseParser<E, N extends DataContainerNode<?>> extends
- BaseDispatcherParser<E, N, ListSchemaNode> {
+public abstract class ListEntryNodeBaseParser<P extends YangInstanceIdentifier.PathArgument, E, N extends DataContainerNode<P>> extends
+ BaseDispatcherParser<E, P, N, ListSchemaNode> {
+
+ public ListEntryNodeBaseParser(final BuildingStrategy<P, N> buildingStrategy) {
+ super(buildingStrategy);
+ }
+
+ public ListEntryNodeBaseParser() {
+ }
@Override
protected final Set<DataSchemaNode> getRealSchemasForAugment(final ListSchemaNode schema, final AugmentationSchema augmentSchema) {
package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser;
import java.util.Collections;
+import java.util.Map;
+import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
* type of elements to be parsed
*/
public abstract class ListNodeBaseParser<E, N extends NormalizedNode<?, ?>, O extends NormalizedNode<YangInstanceIdentifier.NodeIdentifier, ?>, S extends ListSchemaNode>
- implements ToNormalizedNodeParser<E, O, S> {
+ implements ExtensibleParser<YangInstanceIdentifier.NodeIdentifier, E, O, S> {
+
+ private final BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, O> buildingStrategy;
+
+ public ListNodeBaseParser() {
+ buildingStrategy = new SimpleListNodeBuildingStrategy<>();
+ }
+
+ public ListNodeBaseParser(final BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, O> buildingStrategy) {
+ this.buildingStrategy = buildingStrategy;
+ }
@Override
- public final O parse(Iterable<E> childNodes, S schema) {
+ public O parse(Iterable<E> childNodes, S schema) {
CollectionNodeBuilder<N, O> listBuilder = provideBuilder(schema);
+
+ buildingStrategy.prepareAttributes(Collections.<QName, String>emptyMap(), listBuilder);
+
for (E childNode : childNodes) {
N listChild = getListEntryNodeParser().parse(Collections.singletonList(childNode), schema);
- listBuilder.withChild(listChild);
+ if (listChild != null) {
+ listBuilder.withChild(listChild);
+ }
}
- return listBuilder.build();
+ return buildingStrategy.build(listBuilder);
}
/**
* @return prepares builder which will contain entries of list according to concrete list type
*/
protected abstract CollectionNodeBuilder<N, O> provideBuilder(S schema);
+
+ @Override
+ public BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, O> getBuildingStrategy() {
+ return buildingStrategy;
+ }
+
+ public static class SimpleListNodeBuildingStrategy<O extends NormalizedNode<YangInstanceIdentifier.NodeIdentifier, ?>> implements BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, O> {
+ @Override
+ public O build(final NormalizedNodeBuilder<YangInstanceIdentifier.NodeIdentifier, ?, O> builder) {
+ return builder.build();
+ }
+
+ @Override
+ public void prepareAttributes(final Map<QName, String> attributes, final NormalizedNodeBuilder<YangInstanceIdentifier.NodeIdentifier, ?, O> containerBuilder) {
+ // NOOP
+ }
+ }
}
*/
package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
*/
public abstract class MapNodeBaseParser<E> extends ListNodeBaseParser<E, MapEntryNode, MapNode, ListSchemaNode> {
+ public MapNodeBaseParser() {
+ }
+
+ public MapNodeBaseParser(final BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, MapNode> buildingStrategy) {
+ super(buildingStrategy);
+ }
+
protected CollectionNodeBuilder<MapEntryNode, MapNode> provideBuilder(ListSchemaNode schema) {
return Builders.mapBuilder(schema);
}
*/
package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
*/
public abstract class OrderedListNodeBaseParser<E> extends
ListNodeBaseParser<E, MapEntryNode, OrderedMapNode, ListSchemaNode> {
+
+ public OrderedListNodeBaseParser() {
+ }
+
+ public OrderedListNodeBaseParser(final BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, OrderedMapNode> buildingStrategy) {
+ super(buildingStrategy);
+ }
+
@Override
protected CollectionNodeBuilder<MapEntryNode, OrderedMapNode> provideBuilder(ListSchemaNode schema) {
return Builders.orderedMapBuilder(schema);
}
+
}
*/
public abstract class UnkeyedListNodeBaseParser<E> extends
ListNodeBaseParser<E, UnkeyedListEntryNode, UnkeyedListNode, ListSchemaNode> {
+
+ public UnkeyedListNodeBaseParser(final BuildingStrategy<NodeIdentifier, UnkeyedListNode> buildingStrategy) {
+ super(buildingStrategy);
+ }
+
+ public UnkeyedListNodeBaseParser() {
+ }
+
@Override
protected CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> provideBuilder(ListSchemaNode schema) {
CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> listBuilder = Builders.unkeyedListBuilder();
*/
package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.LinkedListMultimap;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.AugmentationNodeBaseParser;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.NodeParserDispatcher;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
import org.w3c.dom.Element;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.LinkedListMultimap;
-
final class AugmentationNodeDomParser extends AugmentationNodeBaseParser<Element> {
private final NodeParserDispatcher<Element> dispatcher;
this.strictParsing = strictParsing;
}
+ public AugmentationNodeDomParser(final BuildingStrategy<YangInstanceIdentifier.AugmentationIdentifier, AugmentationNode> buildingStrategy,
+ final NodeParserDispatcher<Element> dispatcher, final boolean strictParsing) {
+ super(buildingStrategy);
+ this.dispatcher = Preconditions.checkNotNull(dispatcher);
+ this.strictParsing = strictParsing;
+ }
+
@Override
protected LinkedListMultimap<QName, Element> mapChildElements(Iterable<Element> elements) {
return DomUtils.mapChildElements(elements);
*/
package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.LinkedListMultimap;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.ChoiceNodeBaseParser;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.NodeParserDispatcher;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
import org.w3c.dom.Element;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.LinkedListMultimap;
-
final class ChoiceNodeDomParser extends ChoiceNodeBaseParser<Element> {
private final NodeParserDispatcher<Element> dispatcher;
- ChoiceNodeDomParser(NodeParserDispatcher<Element> dispatcher) {
+ ChoiceNodeDomParser(final NodeParserDispatcher<Element> dispatcher) {
+ this.dispatcher = Preconditions.checkNotNull(dispatcher);
+ }
+
+ ChoiceNodeDomParser(final NodeParserDispatcher<Element> dispatcher, final BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, ChoiceNode> buildingStrategy) {
+ super(buildingStrategy);
this.dispatcher = Preconditions.checkNotNull(dispatcher);
}
@Override
- protected LinkedListMultimap<QName, Element> mapChildElements(Iterable<Element> xml) {
+ protected LinkedListMultimap<QName, Element> mapChildElements(final Iterable<Element> xml) {
return DomUtils.mapChildElements(xml);
}
protected NodeParserDispatcher<Element> getDispatcher() {
return dispatcher;
}
+
}
*/
package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.LinkedListMultimap;
import java.util.Map;
-
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.ContainerNodeBaseParser;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.NodeParserDispatcher;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
import org.w3c.dom.Element;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.LinkedListMultimap;
-
final class ContainerNodeDomParser extends ContainerNodeBaseParser<Element> {
private final NodeParserDispatcher<Element> dispatcher;
ContainerNodeDomParser(final NodeParserDispatcher<Element> dispatcher) {
this.dispatcher = Preconditions.checkNotNull(dispatcher);
- this.strictParsing = super.strictParsing();
+ strictParsing = super.strictParsing();
+ }
+
+ public ContainerNodeDomParser(final NodeParserDispatcher<Element> dispatcher, final boolean strictParsing) {
+ this.dispatcher = dispatcher;
+ this.strictParsing = strictParsing;
}
- ContainerNodeDomParser(final NodeParserDispatcher<Element> dispatcher, final boolean strictParsing) {
+ ContainerNodeDomParser(final NodeParserDispatcher<Element> dispatcher, final BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, ContainerNode> parsingStrategy, final boolean strictParsing) {
+ super(parsingStrategy);
this.dispatcher = Preconditions.checkNotNull(dispatcher);
this.strictParsing = strictParsing;
}
*/
package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParserFactory;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.BaseDispatcherParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.ExtensibleParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.LeafNodeBaseParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.LeafSetEntryNodeBaseParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.ListNodeBaseParser;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.NodeParserDispatcher;
import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
import org.w3c.dom.Element;
public final class DomToNormalizedNodeParserFactory implements ToNormalizedNodeParserFactory<Element> {
+
private final AugmentationNodeDomParser augmentationNodeParser;
private final ChoiceNodeDomParser choiceNodeParser;
private final ContainerNodeDomParser containerNodeParser;
augmentationNodeParser = new AugmentationNodeDomParser(dispatcher, strictParsing);
}
+ private DomToNormalizedNodeParserFactory(final XmlCodecProvider codecProvider, final SchemaContext schema,
+ final BuildingStrategyProvider buildingStratProvider, final boolean strictParsing) {
+ leafNodeParser = new LeafNodeDomParser(codecProvider, schema, buildingStratProvider.forLeaf());
+ leafSetEntryNodeParser = new LeafSetEntryNodeDomParser(codecProvider, schema, buildingStratProvider.forLeafSetEntry());
+
+ // no buildingStrategy for Augment (no use case for now)
+ leafSetNodeParser = new LeafSetNodeDomParser(leafSetEntryNodeParser);
+ // no buildingStrategy for anyXml (probably not necessary)
+ anyXmlNodeParser = new AnyXmlDomParser();
+
+ final NodeParserDispatcher<Element> dispatcher = new NodeParserDispatcher.BaseNodeParserDispatcher<Element>(this) {
+
+ };
+
+ containerNodeParser = new ContainerNodeDomParser(dispatcher, buildingStratProvider.forContainer(), strictParsing);
+ mapEntryNodeParser = new MapEntryNodeDomParser(dispatcher, buildingStratProvider.forMapEntry(), strictParsing);
+ mapNodeParser = new MapNodeDomParser(mapEntryNodeParser, buildingStratProvider.forMap());
+ orderedListNodeParser = new OrderedListNodeDomParser(mapEntryNodeParser, buildingStratProvider.forOrderedList());
+ unkeyedListEntryNodeParser = new UnkeyedListEntryNodeDomParser(buildingStratProvider.forUnkeyedListEntry(), dispatcher);
+ unkeyedListNodeParser = new UnkeyedListNodeDomParser(buildingStratProvider.forUnkeyedList(), unkeyedListEntryNodeParser);
+ choiceNodeParser = new ChoiceNodeDomParser(dispatcher, buildingStratProvider.forChoice());
+ // no buildingStrategy for Augment (no use case for now)
+ augmentationNodeParser = new AugmentationNodeDomParser(buildingStratProvider.forAugmentation(), dispatcher, strictParsing);
+ }
+
@Deprecated
private DomToNormalizedNodeParserFactory(final XmlCodecProvider codecProvider) {
leafNodeParser = new LeafNodeDomParser(codecProvider);
return new DomToNormalizedNodeParserFactory(codecProvider, schema, true);
}
+ public static DomToNormalizedNodeParserFactory getInstance(final XmlCodecProvider codecProvider, final SchemaContext schema,
+ final BuildingStrategyProvider buildingStratProvider) {
+ return new DomToNormalizedNodeParserFactory(codecProvider, schema, buildingStratProvider, true);
+ }
+
+ public static DomToNormalizedNodeParserFactory getInstance(final XmlCodecProvider codecProvider, final SchemaContext schema,
+ final BuildingStrategyProvider buildingStratProvider,
+ final boolean strictParsing) {
+ return new DomToNormalizedNodeParserFactory(codecProvider, schema, buildingStratProvider, strictParsing);
+ }
+
@Deprecated
public static DomToNormalizedNodeParserFactory getInstance(final XmlCodecProvider codecProvider) {
return new DomToNormalizedNodeParserFactory(codecProvider);
public ToNormalizedNodeParser<Element, AnyXmlNode, AnyXmlSchemaNode> getAnyXmlNodeParser() {
return anyXmlNodeParser;
}
+
+ /**
+ * Base provider of building strategies used for customizing parsing process
+ */
+ public static abstract class BuildingStrategyProvider {
+
+ protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifier,LeafNode<?>> forLeaf() {
+ return new LeafNodeBaseParser.SimpleLeafBuildingStrategy();
+ }
+
+ protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeWithValue,LeafSetEntryNode<?>> forLeafSetEntry() {
+ return new LeafSetEntryNodeBaseParser.SimpleLeafSetEntryBuildingStrategy();
+ }
+
+ protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifier,ContainerNode> forContainer() {
+ return new BaseDispatcherParser.SimpleBuildingStrategy<>();
+ }
+
+ protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifierWithPredicates,MapEntryNode> forMapEntry() {
+ return new BaseDispatcherParser.SimpleBuildingStrategy<>();
+ }
+
+ protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifier,MapNode> forMap() {
+ return new ListNodeBaseParser.SimpleListNodeBuildingStrategy<>();
+ }
+
+ protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifier,OrderedMapNode> forOrderedList() {
+ return new ListNodeBaseParser.SimpleListNodeBuildingStrategy<>();
+ }
+
+ protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifier,UnkeyedListEntryNode> forUnkeyedListEntry() {
+ return new BaseDispatcherParser.SimpleBuildingStrategy<>();
+ }
+
+ protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifier,UnkeyedListNode> forUnkeyedList() {
+ return new ListNodeBaseParser.SimpleListNodeBuildingStrategy<>();
+ }
+
+ protected ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.NodeIdentifier,ChoiceNode> forChoice() {
+ return new BaseDispatcherParser.SimpleBuildingStrategy<>();
+ }
+
+ public ExtensibleParser.BuildingStrategy<YangInstanceIdentifier.AugmentationIdentifier, AugmentationNode> forAugmentation() {
+ return new BaseDispatcherParser.SimpleBuildingStrategy<>();
+ }
+ }
}
*/
package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
+import com.google.common.base.Preconditions;
import java.util.Map;
-
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.LeafNodeBaseParser;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.w3c.dom.Element;
-import com.google.common.base.Preconditions;
-
final class LeafNodeDomParser extends LeafNodeBaseParser<Element> {
private final XmlCodecProvider codecProvider;
this.codecProvider = Preconditions.checkNotNull(codecProvider);
}
+ LeafNodeDomParser(XmlCodecProvider codecProvider, final SchemaContext schema, final BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, LeafNode<?>> strategy) {
+ super(strategy);
+ this.ctx = schema;
+ this.codecProvider = Preconditions.checkNotNull(codecProvider);
+ }
+
@Deprecated
LeafNodeDomParser(XmlCodecProvider codecProvider) {
this(codecProvider, null);
protected Map<QName, String> getAttributes(Element element) {
return DomUtils.toAttributes(element.getAttributes());
}
+
}
*/
package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
+import com.google.common.base.Preconditions;
import java.util.Map;
-
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.LeafSetEntryNodeBaseParser;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.w3c.dom.Element;
-import com.google.common.base.Preconditions;
-
final class LeafSetEntryNodeDomParser extends LeafSetEntryNodeBaseParser<Element> {
private final XmlCodecProvider codecProvider;
private final SchemaContext ctx;
- LeafSetEntryNodeDomParser(XmlCodecProvider codecProvider, final SchemaContext schema) {
- ctx = schema;
+ LeafSetEntryNodeDomParser(final XmlCodecProvider codecProvider, final SchemaContext schema) {
+ this.ctx = schema;
+ this.codecProvider = Preconditions.checkNotNull(codecProvider);
+ }
+
+ LeafSetEntryNodeDomParser(final XmlCodecProvider codecProvider, final SchemaContext schema, final BuildingStrategy<YangInstanceIdentifier.NodeWithValue, LeafSetEntryNode<?>> strategy) {
+ super(strategy);
+ this.ctx = schema;
this.codecProvider = Preconditions.checkNotNull(codecProvider);
}
protected Map<QName, String> getAttributes(Element element) {
return DomUtils.toAttributes(element.getAttributes());
}
+
}
import com.google.common.collect.LinkedListMultimap;
import java.util.Map;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.ListEntryNodeBaseParser;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.NodeParserDispatcher;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
import org.w3c.dom.Element;
-abstract class ListEntryNodeDomParser<N extends DataContainerNode<?>> extends ListEntryNodeBaseParser<Element, N> {
+abstract class ListEntryNodeDomParser<P extends YangInstanceIdentifier.PathArgument, N extends DataContainerNode<P>> extends ListEntryNodeBaseParser<P, Element, N> {
private final NodeParserDispatcher<Element> dispatcher;
this.dispatcher = Preconditions.checkNotNull(dispatcher);
}
+ ListEntryNodeDomParser(final BuildingStrategy<P, N> buildingStrategy, final NodeParserDispatcher<Element> dispatcher) {
+ super(buildingStrategy);
+ this.dispatcher = dispatcher;
+ }
+
@Override
protected LinkedListMultimap<QName, Element> mapChildElements(Iterable<Element> elements) {
return DomUtils.mapChildElementsForSingletonNode(elements.iterator().next());
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
import org.w3c.dom.Element;
-final class MapEntryNodeDomParser extends ListEntryNodeDomParser<MapEntryNode> {
+final class MapEntryNodeDomParser extends ListEntryNodeDomParser<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> {
private final boolean strictParsing;
MapEntryNodeDomParser(final NodeParserDispatcher<Element> dispatcher) {
super(dispatcher);
+ // TODO strict parsing attribute should be injected into superclass via a constructor
+ // WIth current approach (getter) we have to call super.strictParsing in constructor and cannot reuse constructors
this.strictParsing = super.strictParsing();
}
this.strictParsing = strictParsing;
}
+ MapEntryNodeDomParser(final NodeParserDispatcher<Element> dispatcher, final BuildingStrategy<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> strategy,
+ final boolean strictParsing) {
+ super(strategy, dispatcher);
+ this.strictParsing = strictParsing;
+ }
+
@Override
protected final DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> getBuilder(
ListSchemaNode schema) {
*/
package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.MapNodeBaseParser;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
private final MapEntryNodeDomParser mapEntryParser;
- MapNodeDomParser(MapEntryNodeDomParser mapEntryParser) {
+ MapNodeDomParser(final MapEntryNodeDomParser mapEntryParser) {
+ this.mapEntryParser = mapEntryParser;
+ }
+
+ MapNodeDomParser(MapEntryNodeDomParser mapEntryParser, final BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, MapNode> strategy) {
+ super(strategy);
this.mapEntryParser = mapEntryParser;
}
protected ToNormalizedNodeParser<Element, MapEntryNode, ListSchemaNode> getListEntryNodeParser() {
return mapEntryParser;
}
+
}
*/
package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.OrderedListNodeBaseParser;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
private final MapEntryNodeDomParser mapEntryNodeParser;
- OrderedListNodeDomParser(MapEntryNodeDomParser mapEntryNodeParser) {
+ OrderedListNodeDomParser(final MapEntryNodeDomParser mapEntryNodeParser) {
+ this.mapEntryNodeParser = mapEntryNodeParser;
+ }
+
+ OrderedListNodeDomParser(MapEntryNodeDomParser mapEntryNodeParser, final BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, OrderedMapNode> strategy) {
+ super(strategy);
this.mapEntryNodeParser = mapEntryNodeParser;
}
protected ToNormalizedNodeParser<Element, MapEntryNode, ListSchemaNode> getListEntryNodeParser() {
return mapEntryNodeParser;
}
+
}
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
import org.w3c.dom.Element;
-final class UnkeyedListEntryNodeDomParser extends ListEntryNodeDomParser<UnkeyedListEntryNode> {
+final class UnkeyedListEntryNodeDomParser extends ListEntryNodeDomParser<YangInstanceIdentifier.NodeIdentifier, UnkeyedListEntryNode> {
UnkeyedListEntryNodeDomParser(final NodeParserDispatcher<Element> dispatcher) {
super(dispatcher);
}
+ UnkeyedListEntryNodeDomParser(final BuildingStrategy<NodeIdentifier, UnkeyedListEntryNode> buildingStrategy, final NodeParserDispatcher<Element> dispatcher) {
+ super(buildingStrategy, dispatcher);
+ }
+
@Override
protected final DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifier, UnkeyedListEntryNode> getBuilder(
ListSchemaNode schema) {
*/
package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.UnkeyedListNodeBaseParser;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
this.unkeyedListEntryNodeParser = unkeyedListEntryNodeParser;
}
+ UnkeyedListNodeDomParser(final BuildingStrategy<YangInstanceIdentifier.NodeIdentifier, UnkeyedListNode> buildingStrategy, final UnkeyedListEntryNodeDomParser unkeyedListEntryNodeParser) {
+ super(buildingStrategy);
+ this.unkeyedListEntryNodeParser = unkeyedListEntryNodeParser;
+ }
+
@Override
protected ToNormalizedNodeParser<Element, UnkeyedListEntryNode, ListSchemaNode> getListEntryNodeParser() {
return unkeyedListEntryNodeParser;
}
+
}
Document currentConfigElement = readXmlToDocument(resourceAsStream);
Preconditions.checkNotNull(currentConfigElement);
- return Optional.of(DomToNormalizedNodeParserFactory.getInstance(DomUtils.defaultValueCodecProvider(), schema).getContainerNodeParser().parse(
+ return Optional.fromNullable(DomToNormalizedNodeParserFactory.getInstance(DomUtils.defaultValueCodecProvider(), schema).getContainerNodeParser().parse(
Collections.singletonList(currentConfigElement.getDocumentElement()), containerNode));
}