*/
package org.opendaylight.yangtools.binding.data.codec.api;
-import java.util.Map;
import java.util.Map.Entry;
-
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-
+import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.Notification;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
/**
- * Serialization service, which provides two-way serialization between
- * Java Binding Data representation and NormalizedNode representation.
+ * Serialization service, which provides two-way serialization between Java
+ * Binding Data representation and NormalizedNode representation.
*/
public interface BindingNormalizedNodeSerializer {
- /**
- * Translates supplied Binding Instance Identifier into NormalizedNode instance identifier.
- *
- * @param binding Binding Instance Identifier
- * @return DOM Instance Identifier
- */
- YangInstanceIdentifier toYangInstanceIdentifier(@Nonnull InstanceIdentifier<?> binding);
+ /**
+ * Translates supplied Binding Instance Identifier into NormalizedNode
+ * instance identifier.
+ *
+ * @param binding
+ * Binding Instance Identifier
+ * @return DOM Instance Identifier
+ */
+ YangInstanceIdentifier toYangInstanceIdentifier(@Nonnull InstanceIdentifier<?> binding);
+
+ /**
+ * Translates supplied YANG Instance Identifier into Binding instance
+ * identifier.
+ *
+ * @param dom
+ * YANG Instance Identifier
+ * @return Binding Instance Identifier, or null if the instance identifier
+ * is not representable.
+ */
+ @Nullable
+ InstanceIdentifier<?> fromYangInstanceIdentifier(@Nonnull YangInstanceIdentifier dom);
+
+ /**
+ * Translates supplied Binding Instance Identifier and data into
+ * NormalizedNode representation.
+ *
+ * @param path
+ * Binding Instance Identifier pointing to data
+ * @param data
+ * Data object representing data
+ * @return NormalizedNode representation
+ */
+ <T extends DataObject> Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> toNormalizedNode(
+ InstanceIdentifier<T> path, T data);
- /**
- * Translates supplied YANG Instance Identifier into Binding instance identifier.
- *
- * @param dom YANG Instance Identifier
- * @return Binding Instance Identifier, or null if the instance identifier is not
- * representable.
- */
- @Nullable InstanceIdentifier<?> fromYangInstanceIdentifier(@Nonnull YangInstanceIdentifier dom);
+ /**
+ * Translates supplied YANG Instance Identifier and NormalizedNode into
+ * Binding data.
+ *
+ * @param path Binding Instance Identifier
+ * @param data NormalizedNode representing data
+ * @return DOM Instance Identifier
+ */
+ @Nullable
+ Entry<InstanceIdentifier<?>, DataObject> fromNormalizedNode(@Nonnull YangInstanceIdentifier path,
+ NormalizedNode<?, ?> data);
- /**
- * Translates supplied Binding Instance Identifier and data into NormalizedNode representation.
- *
- * @param path Binding Instance Identifier pointing to data
- * @param data Data object representing data
- * @return NormalizedNode representation
- */
- <T extends DataObject> Entry<YangInstanceIdentifier, NormalizedNode<?,?>> toNormalizedNode(InstanceIdentifier<T> path, T data);
+ /**
+ * Translates supplied NormalizedNode Notification into Binding data.
+ *
+ * @param path Schema Path of Notification, schema path is absolute, and consists of Notification QName.
+ * @param data NormalizedNode representing data
+ * @return Binding representation of Notification
+ */
+ @Nullable Notification fromNormalizedNodeNotification(@Nonnull SchemaPath path,@Nonnull ContainerNode data);
- /**
- * Translates supplied YANG Instance Identifier and NormalizedNode into Binding data.
- *
- * @param path Binding Instance Identifier
- * @param data NormalizedNode representing data
- * @return DOM Instance Identifier
- */
- @Nullable Entry<InstanceIdentifier<?>,DataObject> fromNormalizedNode(@Nonnull YangInstanceIdentifier path, NormalizedNode<?, ?> data);
+ /**
+ * Translates supplied NormalizedNode RPC input or output into Binding data.
+ *
+ * @param path Schema path of RPC data, Schema path consists of rpc QName and input / output QName.
+ * @param data NormalizedNode representing data
+ * @return Binding representation of RPC data
+ */
+ @Nullable DataObject fromNormalizedNodeRpcData(@Nonnull SchemaPath path,@Nonnull ContainerNode data);
- /**
- * Returns map view which contains translated set of entries to normalized nodes.
- * Returned set will not contain representation of leaf nodes.
- *
- * @param dom Map of YANG Instance Identifier to Data
- * @return Map of Binding Instance Identifier to data.
- */
- Map<InstanceIdentifier<?>,DataObject> fromNormalizedNodes(Map<YangInstanceIdentifier,NormalizedNode<?,?>> dom);
+ /**
+ * Translates supplied Binding Notification or output into NormalizedNode notification.
+ *
+ * @param data NormalizedNode representing notification data
+ * @return NormalizedNode representation of notification
+ */
+ @Nonnull ContainerNode toNormalizedNodeNotification(@Nonnull Notification data);
+ /**
+ * Translates supplied Binding RPC input or output into NormalizedNode data.
+ *
+ * @param data NormalizedNode representing rpc data
+ * @return NormalizedNode representation of rpc data
+ */
+ @Nonnull ContainerNode toNormalizedNodeRpcData(@Nonnull DataContainer data);
}
package org.opendaylight.yangtools.binding.data.codec.api;
import java.util.Map.Entry;
-
+import javax.annotation.Nonnull;
import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.Notification;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
* @return Instance Identifier and {@link BindingStreamEventWriter}
* which will write to supplied {@link NormalizedNodeStreamWriter}.
*/
- Entry<YangInstanceIdentifier, BindingStreamEventWriter> newWriterAndIdentifier(InstanceIdentifier<?> path,
- NormalizedNodeStreamWriter domWriter);
+ @Nonnull Entry<YangInstanceIdentifier, BindingStreamEventWriter> newWriterAndIdentifier(@Nonnull InstanceIdentifier<?> path,
+ @Nonnull NormalizedNodeStreamWriter domWriter);
/**
*
* @return {@link BindingStreamEventWriter}
* which will write to supplied {@link NormalizedNodeStreamWriter}.
*/
- BindingStreamEventWriter newWriter(InstanceIdentifier<?> path, NormalizedNodeStreamWriter domWriter);
+ @Nonnull
+ BindingStreamEventWriter newWriter(@Nonnull InstanceIdentifier<?> path,
+ @Nonnull NormalizedNodeStreamWriter domWriter);
+
+ /**
+ *
+ * Creates a {@link BindingStreamEventWriter} for rpc data which will
+ * translate to NormalizedNode model and invoke proper events on supplied
+ * {@link NormalizedNodeStreamWriter}.
+ *
+ * @param rpcInputOrOutput Binding class representing RPC input or output,
+ * for which writer should be instantiated
+ * @param domWriter
+ * Stream writer on which events will be invoked.
+ * @return {@link BindingStreamEventWriter} which will write to supplied
+ * {@link NormalizedNodeStreamWriter}.
+ */
+ @Nonnull
+ BindingStreamEventWriter newRpcWriter(@Nonnull Class<? extends DataContainer> rpcInputOrOutput,
+ @Nonnull NormalizedNodeStreamWriter domWriter);
+
+ /**
+ *
+ * Creates a {@link BindingStreamEventWriter} for notification which will
+ * translate to NormalizedNode model and invoke proper events on supplied
+ * {@link NormalizedNodeStreamWriter}.
+ *
+ * @param notification Binding class representing notification,
+ * for which writer should be instantiated
+ * @param domWriter
+ * Stream writer on which events will be invoked.
+ * @return {@link BindingStreamEventWriter} which will write to supplied
+ * {@link NormalizedNodeStreamWriter}.
+ */
+ @Nonnull
+ BindingStreamEventWriter newNotificationWriter(@Nonnull Class<? extends Notification> notification,
+ @Nonnull NormalizedNodeStreamWriter domWriter);
}
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
-
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Map.Entry;
-
import javassist.CannotCompileException;
import javassist.CtClass;
import javassist.CtField;
import javassist.CtMethod;
import javassist.Modifier;
import javassist.NotFoundException;
-
import org.opendaylight.yangtools.binding.data.codec.gen.spi.StaticConstantDefinition;
import org.opendaylight.yangtools.binding.data.codec.util.AugmentableDispatchSerializer;
import org.opendaylight.yangtools.binding.generator.util.Types;
import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
try {
cls = (Class<? extends DataObjectSerializerImplementation>) ClassLoaderUtils
.loadClass(type.getClassLoader(), serializerName);
- } catch (ClassNotFoundException e) {
+ } catch (final ClassNotFoundException e) {
cls = generateSerializer(type, serializerName);
}
* classes. This should be almost as good as that, as we are resetting the
* fields to final before ever leaking the class.
*/
- for (StaticConstantDefinition constant : source.getStaticConstants()) {
+ for (final StaticConstantDefinition constant : source.getStaticConstants()) {
final Field field = cls.getDeclaredField(constant.getName());
field.setAccessible(true);
field.set(null, constant.getValue());
private DataObjectSerializerSource generateEmitterSource(final Class<?> type, final String serializerName) {
Types.typeForClass(type);
javassist.appendClassLoaderIfMissing(type.getClassLoader());
- Entry<GeneratedType, Object> typeWithSchema = context.getTypeWithSchema(type);
- GeneratedType generatedType = typeWithSchema.getKey();
- Object schema = typeWithSchema.getValue();
+ final Entry<GeneratedType, Object> typeWithSchema = context.getTypeWithSchema(type);
+ final GeneratedType generatedType = typeWithSchema.getKey();
+ final Object schema = typeWithSchema.getValue();
final DataObjectSerializerSource source;
if (schema instanceof ContainerSchemaNode) {
source = generateContainerSerializer(generatedType, (ContainerSchemaNode) schema);
} else if (schema instanceof ListSchemaNode){
- ListSchemaNode casted = (ListSchemaNode) schema;
+ final ListSchemaNode casted = (ListSchemaNode) schema;
if (casted.getKeyDefinition().isEmpty()) {
source = generateUnkeyedListEntrySerializer(generatedType, casted);
} else {
source = generateSerializer(generatedType,(AugmentationSchema) schema);
} else if(schema instanceof ChoiceCaseNode) {
source = generateCaseSerializer(generatedType,(ChoiceCaseNode) schema);
+ } else if(schema instanceof NotificationDefinition) {
+ source = generateNotificationSerializer(generatedType,(NotificationDefinition) schema);
} else {
throw new UnsupportedOperationException("Schema type " + schema.getClass() + " is not supported");
}
);
// Generate any static fields
- for (StaticConstantDefinition def : source.getStaticConstants()) {
- CtField field = new CtField(javassist.asCtClass(def.getType()), def.getName(), cls);
+ for (final StaticConstantDefinition def : source.getStaticConstants()) {
+ final CtField field = new CtField(javassist.asCtClass(def.getType()), def.getName(), cls);
field.setModifiers(Modifier.PRIVATE + Modifier.STATIC);
cls.addField(field);
}
cls.setModifiers(Modifier.setPublic(cls.getModifiers()));
}
});
- } catch (NotFoundException e) {
+ } catch (final NotFoundException e) {
LOG.error("Failed to instatiate serializer {}", source, e);
throw new LinkageError("Unexpected instantation problem: serializer prototype not found", e);
}
* for all reachable binding objects.
*
* @param type Binding type of augmentation
- * @param node Schema of augmentation
+ * @param schema Schema of augmentation
* @return Source for augmentation node writer
*/
protected abstract DataObjectSerializerSource generateSerializer(GeneratedType type, AugmentationSchema schema);
+ /**
+ * Generates serializer source for notification node,
+ * which will read supplied binding type and invoke proper methods
+ * on supplied {@link BindingStreamEventWriter}.
+ * <p>
+ * Implementation is required to recursively invoke events
+ * for all reachable binding objects.
+ *
+ * @param type Binding type of notification
+ * @param node Schema of notification
+ * @return Source for notification node writer
+ */
+ protected abstract DataObjectSerializerSource generateNotificationSerializer(GeneratedType type, NotificationDefinition node);
+
}
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
/**
* Concrete implementation of {@link AbstractStreamWriterGenerator}
};
}
+ @Override
+ protected DataObjectSerializerSource generateNotificationSerializer(final GeneratedType type, final NotificationDefinition node) {
+
+ return new AugmentableDataNodeContainerEmmiterSource(this, type, node) {
+ @Override
+ public CharSequence emitStartEvent() {
+ return startContainerNode(classReference(type), getChildSizeFromSchema(node));
+ }
+ };
+ }
+
@Override
protected DataObjectSerializerSource generateCaseSerializer(final GeneratedType type, final ChoiceCaseNode node) {
return new AugmentableDataNodeContainerEmmiterSource(this, type, node) {
* <li>name - property name</li>
* <li>type - Java type for property</li>
* <li>value - value to which property should be initialized</li>
- *
+ * </ul>
*/
public class StaticConstantDefinition {
import org.opendaylight.yangtools.yang.binding.BaseIdentity;
import org.opendaylight.yangtools.yang.binding.BindingMapping;
import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.opendaylight.yangtools.yang.binding.Identifiable;
import org.opendaylight.yangtools.yang.binding.Identifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
+import org.opendaylight.yangtools.yang.binding.Notification;
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.LeafListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
return new BindingToNormalizedStreamWriter(getCodecContextNode(path, null), domWriter);
}
+ BindingStreamEventWriter newRpcWriter(final Class<? extends DataContainer> rpcInputOrOutput,
+ final NormalizedNodeStreamWriter domWriter) {
+ final NodeCodecContext schema = root.getRpc(rpcInputOrOutput);
+ return new BindingToNormalizedStreamWriter(schema, domWriter);
+ }
+
+ BindingStreamEventWriter newNotificationWriter(final Class<? extends Notification> notification,
+ final NormalizedNodeStreamWriter domWriter) {
+ final NodeCodecContext schema = root.getNotification(notification);
+ return new BindingToNormalizedStreamWriter(schema, domWriter);
+ }
+
public DataContainerCodecContext<?> getCodecContextNode(final InstanceIdentifier<?> binding,
final List<YangInstanceIdentifier.PathArgument> builder) {
DataContainerCodecContext<?> currentNode = root;
return currentNode;
}
+ NotificationCodecContext getNotificationContext(final SchemaPath notification) {
+ return root.getNotification(notification);
+ }
+
+ ContainerNodeCodecContext getRpcDataContext(final SchemaPath path) {
+ return root.getRpc(path);
+ }
+
@Override
public ImmutableMap<String, LeafNodeCodecContext> getLeafNodes(final Class<?> parentClass,
final DataNodeContainer childSchema) {
return new IdentifiableItemCodec(schema, identifier, listClz, valueCtx);
}
+
+
+
+
}
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
-
import java.io.IOException;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
import java.util.Map.Entry;
-
import org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeSerializer;
import org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeWriterFactory;
import org.opendaylight.yangtools.binding.data.codec.gen.impl.DataObjectSerializerGenerator;
import org.opendaylight.yangtools.concepts.Delegator;
import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.DataObjectSerializer;
import org.opendaylight.yangtools.yang.binding.DataObjectSerializerImplementation;
import org.opendaylight.yangtools.yang.binding.DataObjectSerializerRegistry;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.binding.Notification;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Override
public <T extends DataObject> Entry<YangInstanceIdentifier,NormalizedNode<?,?>> toNormalizedNode(final InstanceIdentifier<T> path, final T data) {
- NormalizedNodeResult result = new NormalizedNodeResult();
+ final NormalizedNodeResult result = new NormalizedNodeResult();
// We create DOM stream writer which produces normalized nodes
- NormalizedNodeStreamWriter domWriter = ImmutableNormalizedNodeStreamWriter.from(result);
+ final NormalizedNodeStreamWriter domWriter = ImmutableNormalizedNodeStreamWriter.from(result);
// We create Binding Stream Writer which translates from Binding to Normalized Nodes
- Entry<YangInstanceIdentifier, BindingStreamEventWriter> writeCtx = codecContext.newWriter(path, domWriter);
+ final Entry<YangInstanceIdentifier, BindingStreamEventWriter> writeCtx = codecContext.newWriter(path, domWriter);
// We get serializer which reads binding data and uses Binding To Normalized Node writer to write result
try {
getSerializer(path.getTargetType()).serialize(data, writeCtx.getValue());
- } catch (IOException e) {
+ } catch (final IOException e) {
LOG.error("Unexpected failure while serializing path {} data {}", path, data, e);
throw new IllegalStateException("Failed to create normalized node", e);
}
return new SimpleEntry<YangInstanceIdentifier,NormalizedNode<?,?>>(writeCtx.getKey(),result.getResult());
}
+ @Override
+ public ContainerNode toNormalizedNodeNotification(final Notification data) {
+ final NormalizedNodeResult result = new NormalizedNodeResult();
+ // We create DOM stream writer which produces normalized nodes
+ final NormalizedNodeStreamWriter domWriter = ImmutableNormalizedNodeStreamWriter.from(result);
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ final Class<? extends DataObject> type = (Class) data.getImplementedInterface();
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ final BindingStreamEventWriter writer = newNotificationWriter((Class) type, domWriter);
+ try {
+ // FIXME: Should be cast to DataObject necessary?
+ getSerializer(type).serialize((DataObject) data, writer);
+ } catch (final IOException e) {
+ LOG.error("Unexpected failure while serializing data {}", data, e);
+ throw new IllegalStateException("Failed to create normalized node", e);
+ }
+ return (ContainerNode) result.getResult();
+
+ }
+
+ @Override
+ public ContainerNode toNormalizedNodeRpcData(final DataContainer data) {
+ final NormalizedNodeResult result = new NormalizedNodeResult();
+ // We create DOM stream writer which produces normalized nodes
+ final NormalizedNodeStreamWriter domWriter = ImmutableNormalizedNodeStreamWriter.from(result);
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ final Class<? extends DataObject> type = (Class) data.getImplementedInterface();
+ final BindingStreamEventWriter writer = newRpcWriter(type, domWriter);
+ try {
+ // FIXME: Should be cast to DataObject necessary?
+ getSerializer(type).serialize((DataObject) data, writer);
+ } catch (final IOException e) {
+ LOG.error("Unexpected failure while serializing data {}", data, e);
+ throw new IllegalStateException("Failed to create normalized node", e);
+ }
+ return (ContainerNode) result.getResult();
+ }
+
private static boolean isBindingRepresentable(final NormalizedNode<?, ?> data) {
if (data instanceof ChoiceNode) {
return false;
}
@Override
- public Map<InstanceIdentifier<?>, DataObject> fromNormalizedNodes(final Map<YangInstanceIdentifier, NormalizedNode<?, ?>> dom) {
- throw new UnsupportedOperationException("Not implemented yet");
+ public Notification fromNormalizedNodeNotification(final SchemaPath path, final ContainerNode data) {
+ final NotificationCodecContext codec = codecContext.getNotificationContext(path);
+ return (Notification) codec.dataFromNormalizedNode(data);
}
@Override
+ public DataObject fromNormalizedNodeRpcData(final SchemaPath path, final ContainerNode data) {
+ final ContainerNodeCodecContext codec = codecContext.getRpcDataContext(path);
+ return (DataObject) codec.dataFromNormalizedNode(data);
+ }
+
+ @Override
public Entry<YangInstanceIdentifier, BindingStreamEventWriter> newWriterAndIdentifier(final InstanceIdentifier<?> path, final NormalizedNodeStreamWriter domWriter) {
return codecContext.newWriter(path, domWriter);
}
return codecContext.newWriterWithoutIdentifier(path, domWriter);
}
+ @Override
+ public BindingStreamEventWriter newNotificationWriter(final Class<? extends Notification> notification,
+ final NormalizedNodeStreamWriter streamWriter) {
+ return codecContext.newNotificationWriter(notification, streamWriter);
+ }
+
+
+ @Override
+ public BindingStreamEventWriter newRpcWriter(final Class<? extends DataContainer> rpcInputOrOutput,
+ final NormalizedNodeStreamWriter streamWriter) {
+ return codecContext.newRpcWriter(rpcInputOrOutput,streamWriter);
+ }
+
public <T extends DataObject> Function<Optional<NormalizedNode<?, ?>>, Optional<T>> deserializeFunction(final InstanceIdentifier<T> path) {
- DataObjectCodecContext<?> ctx = (DataObjectCodecContext<?>) codecContext.getCodecContextNode(path, null);
+ final DataObjectCodecContext<?> ctx = (DataObjectCodecContext<?>) codecContext.getCodecContextNode(path, null);
return new DeserializeFunction<T>(ctx);
}
}
}
- private class GeneratorLoader extends CacheLoader<Class<? extends DataObject>, DataObjectSerializer> {
+ private class GeneratorLoader extends CacheLoader<Class<? extends DataContainer>, DataObjectSerializer> {
@Override
- public DataObjectSerializer load(final Class<? extends DataObject> key) throws Exception {
- DataObjectSerializerImplementation prototype = generator.getSerializer(key);
+ public DataObjectSerializer load(final Class<? extends DataContainer> key) throws Exception {
+ final DataObjectSerializerImplementation prototype = generator.getSerializer(key);
return new DataObjectSerializerProxy(prototype);
}
}
Map<Class<?>, DataContainerCodecPrototype<?>> byCaseChildClassBuilder = new HashMap<>();
Set<Class<?>> potentialSubstitutions = new HashSet<>();
// Walks all cases for supplied choice in current runtime context
- for (Class caze : factory().getRuntimeContext().getCases(bindingClass())) {
+ for (Class<?> caze : factory().getRuntimeContext().getCases(bindingClass())) {
// We try to load case using exact match thus name
// and original schema must equals
DataContainerCodecPrototype<ChoiceCaseNode> cazeDef = loadCase(caze);
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
class DataContainerCodecPrototype<T> implements NodeContextSupplier {
@SuppressWarnings({ "unchecked", "rawtypes" })
static <T extends DataSchemaNode> DataContainerCodecPrototype<T> from(final Class<?> cls, final T schema,
final CodecContextFactory factory) {
- NodeIdentifier arg = new NodeIdentifier(schema.getQName());
+ final NodeIdentifier arg = new NodeIdentifier(schema.getQName());
return new DataContainerCodecPrototype(cls, arg, schema, factory);
}
static DataContainerCodecPrototype<SchemaContext> rootPrototype(final CodecContextFactory factory) {
- SchemaContext schema = factory.getRuntimeContext().getSchemaContext();
- NodeIdentifier arg = new NodeIdentifier(schema.getQName());
+ final SchemaContext schema = factory.getRuntimeContext().getSchemaContext();
+ final NodeIdentifier arg = new NodeIdentifier(schema.getQName());
return new DataContainerCodecPrototype<SchemaContext>(DataRoot.class, arg, schema, factory);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
- public static DataContainerCodecPrototype<?> from(final Class<?> augClass, final AugmentationIdentifier arg,
+ static DataContainerCodecPrototype<?> from(final Class<?> augClass, final AugmentationIdentifier arg,
final AugmentationSchema schema, final CodecContextFactory factory) {
return new DataContainerCodecPrototype(augClass, arg, schema, factory);
}
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ static DataContainerCodecPrototype<NotificationDefinition> from(final Class<?> augClass, final NotificationDefinition schema, final CodecContextFactory factory) {
+ final PathArgument arg = new NodeIdentifier(schema.getQName());
+ return new DataContainerCodecPrototype<NotificationDefinition>(augClass,arg, schema, factory);
+ }
+
protected final T getSchema() {
return schema;
}
@Override
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
if (method.getParameterTypes().length == 0) {
- String name = method.getName();
+ final String name = method.getName();
if (GET_IMPLEMENTED_INTERFACE.equals(name)) {
return context.bindingClass();
} else if (TO_STRING.equals(name)) {
return false;
}
try {
- for (Method m : context.getHashCodeAndEqualsMethods()) {
- Object thisValue = getBindingData(m);
- Object otherValue = m.invoke(other);
+ for (final Method m : context.getHashCodeAndEqualsMethods()) {
+ final Object thisValue = getBindingData(m);
+ final Object otherValue = m.invoke(other);
if(!Objects.equals(thisValue, otherValue)) {
return false;
}
}
private Integer bindingHashCode() {
- Integer ret = cachedHashcode;
+ final Integer ret = cachedHashcode;
if (ret != null) {
return ret;
}
final int prime = 31;
int result = 1;
- for (Method m : context.getHashCodeAndEqualsMethods()) {
- Object value = getBindingData(m);
+ for (final Method m : context.getHashCodeAndEqualsMethods()) {
+ final Object value = getBindingData(m);
result += prime * result + ((value == null) ? 0 : value.hashCode());
}
if (Augmentation.class.isAssignableFrom(context.bindingClass())) {
private Object getBindingData(final Method method) {
Object cached = cachedData.get(method);
if (cached == null) {
- Object readedValue = context.getBindingChildValue(method, data);
+ final Object readedValue = context.getBindingChildValue(method, data);
if (readedValue == null) {
cached = NULL_VALUE;
} else {
}
public String bindingToString() {
- ToStringHelper helper = com.google.common.base.Objects.toStringHelper(context.bindingClass()).omitNullValues();
+ final ToStringHelper helper = com.google.common.base.Objects.toStringHelper(context.bindingClass()).omitNullValues();
- for (Method m :context.getHashCodeAndEqualsMethods()) {
+ for (final Method m :context.getHashCodeAndEqualsMethods()) {
helper.add(m.getName(), getBindingData(m));
}
if (Augmentable.class.isAssignableFrom(context.bindingClass())) {
if (getClass() != obj.getClass()) {
return false;
}
- LazyDataObject other = (LazyDataObject) obj;
+ final LazyDataObject other = (LazyDataObject) obj;
if (context == null) {
if (other.context != null) {
return false;
--- /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.yang.data.api.schema.ContainerNode;
+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.NotificationDefinition;
+
+final class NotificationCodecContext extends DataObjectCodecContext<NotificationDefinition> {
+
+ public NotificationCodecContext(final Class<?> key, final NotificationDefinition schema, final CodecContextFactory factory) {
+ super(DataContainerCodecPrototype.from(key, schema, factory));
+ }
+
+ @Override
+ protected Object dataFromNormalizedNode(final NormalizedNode<?, ?> data) {
+ Preconditions.checkState(data instanceof ContainerNode);
+ return createBindingProxy((NormalizedNodeContainer<?, ?, ?>) data);
+ }
+
+}
\ No newline at end of file
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.opendaylight.yangtools.util.ClassLoaderUtils;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.opendaylight.yangtools.yang.binding.DataRoot;
+import org.opendaylight.yangtools.yang.binding.Notification;
import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
+import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils;
-class SchemaRootCodecContext extends DataContainerCodecContext<SchemaContext> {
+final class SchemaRootCodecContext extends DataContainerCodecContext<SchemaContext> {
- private final LoadingCache<Class<?>, DataContainerCodecContext<?>> childrenByClass = CacheBuilder.newBuilder().build(
- new CacheLoader<Class<?>, DataContainerCodecContext<?>>() {
+ private final LoadingCache<Class<?>, DataContainerCodecContext<?>> childrenByClass = CacheBuilder.newBuilder()
+ .build(new CacheLoader<Class<?>, DataContainerCodecContext<?>>() {
@Override
public DataContainerCodecContext<?> load(final Class<?> key) {
- Class<Object> parent = ClassLoaderUtils.findFirstGenericArgument(key, ChildOf.class);
- Preconditions.checkArgument(DataRoot.class.isAssignableFrom(parent));
- QName qname = BindingReflections.findQName(key);
- DataSchemaNode childSchema = schema().getDataChildByName(qname);
- return DataContainerCodecPrototype.from(key, childSchema, factory()).get();
+ return createDataTreeChildContext(key);
+ }
+
+ });
+
+ private final LoadingCache<Class<?>, ContainerNodeCodecContext> rpcDataByClass = CacheBuilder.newBuilder().build(
+ new CacheLoader<Class<?>, ContainerNodeCodecContext>() {
+ @Override
+ public ContainerNodeCodecContext load(final Class<?> key) {
+ return createRpcDataContext(key);
+ }
+ });
+
+ private final LoadingCache<Class<?>, NotificationCodecContext> notificationsByClass = CacheBuilder.newBuilder()
+ .build(new CacheLoader<Class<?>, NotificationCodecContext>() {
+ @Override
+ public NotificationCodecContext load(final Class<?> key) {
+ return createNotificationDataContext(key);
}
});
private final LoadingCache<QName, DataContainerCodecContext<?>> childrenByQName = CacheBuilder.newBuilder().build(
- new CacheLoader<QName, DataContainerCodecContext<?>>() {
- @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());
-
- if (childSchema instanceof DataNodeContainer || childSchema instanceof ChoiceNode) {
- final Class<?> childCls = factory().getRuntimeContext().getClassForSchema(childSchema);
- return getStreamChild(childCls);
- } else {
- throw new UnsupportedOperationException("Unsupported child type " + childSchema.getClass());
+ new CacheLoader<QName, DataContainerCodecContext<?>>() {
+ @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());
+
+ if (childSchema instanceof DataNodeContainer || childSchema instanceof ChoiceNode) {
+ final Class<?> childCls = factory().getRuntimeContext().getClassForSchema(childSchema);
+ return getStreamChild(childCls);
+ } else {
+ throw new UnsupportedOperationException("Unsupported child type " + childSchema.getClass());
+ }
}
- }
- });
+ });
+
+ private final LoadingCache<SchemaPath, ContainerNodeCodecContext> rpcDataByPath = CacheBuilder.newBuilder().build(
+ new CacheLoader<SchemaPath, ContainerNodeCodecContext>() {
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ @Override
+ public ContainerNodeCodecContext load(final SchemaPath key) {
+ final ContainerSchemaNode schema = SchemaContextUtil.getRpcDataSchema(schema(), key);
+ final Class cls = factory().getRuntimeContext().getClassForSchema(schema);
+ return getRpc(cls);
+ }
+ });
+
+ private final LoadingCache<SchemaPath, NotificationCodecContext> notificationsByPath = CacheBuilder.newBuilder()
+ .build(new CacheLoader<SchemaPath, NotificationCodecContext>() {
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ @Override
+ public NotificationCodecContext load(final SchemaPath key) throws Exception {
+ final NotificationDefinition schema = SchemaContextUtil.getNotificationSchema(schema(), key);
+ final Class clz = factory().getRuntimeContext().getClassForSchema(schema);
+ return getNotification(clz);
+ }
+ });
private SchemaRootCodecContext(final DataContainerCodecPrototype<SchemaContext> dataPrototype) {
super(dataPrototype);
* @return
*/
static SchemaRootCodecContext create(final CodecContextFactory factory) {
- DataContainerCodecPrototype<SchemaContext> prototype = DataContainerCodecPrototype.rootPrototype(factory);
+ final DataContainerCodecPrototype<SchemaContext> prototype = DataContainerCodecPrototype.rootPrototype(factory);
return new SchemaRootCodecContext(prototype);
}
throw new UnsupportedOperationException("Not supported");
}
- @Override
- protected PathArgument getDomPathArgument() {
- throw new UnsupportedOperationException();
- }
-
@Override
protected NodeCodecContext getYangIdentifierChild(final PathArgument arg) {
return childrenByQName.getUnchecked(arg.getNodeType());
protected Object dataFromNormalizedNode(final NormalizedNode<?, ?> normalizedNode) {
throw new UnsupportedOperationException("Could not create Binding data representation for root");
}
+
+ ContainerNodeCodecContext getRpc(final Class<? extends DataContainer> rpcInputOrOutput) {
+ return rpcDataByClass.getUnchecked(rpcInputOrOutput);
+ }
+
+ NotificationCodecContext getNotification(final Class<? extends Notification> notification) {
+ return notificationsByClass.getUnchecked(notification);
+ }
+
+ NotificationCodecContext getNotification(final SchemaPath notification) {
+ return notificationsByPath.getUnchecked(notification);
+ }
+
+ ContainerNodeCodecContext getRpc(final SchemaPath notification) {
+ return rpcDataByPath.getUnchecked(notification);
+ }
+
+ private DataContainerCodecContext<?> createDataTreeChildContext(final Class<?> key) {
+ final Class<Object> parent = ClassLoaderUtils.findFirstGenericArgument(key, ChildOf.class);
+ Preconditions.checkArgument(DataRoot.class.isAssignableFrom(parent));
+ final QName qname = BindingReflections.findQName(key);
+ final DataSchemaNode childSchema = schema().getDataChildByName(qname);
+ return DataContainerCodecPrototype.from(key, childSchema, factory()).get();
+ }
+
+ private ContainerNodeCodecContext createRpcDataContext(final Class<?> key) {
+ Preconditions.checkArgument(DataContainer.class.isAssignableFrom(key));
+ final QName qname = BindingReflections.findQName(key);
+ final QNameModule module = qname.getModule();
+ RpcDefinition rpc = null;
+ for (final RpcDefinition potential : schema().getOperations()) {
+ final QName potentialQName = potential.getQName();
+ /*
+ *
+ * Check if rpc and class represents data from same module and then
+ * checks if rpc local name produces same class name as class name
+ * appended with Input/Output based on QName associated with bidning
+ * class.
+ *
+ * FIXME: Rework this to have more precise logic regarding Binding
+ * Specification.
+ */
+ if (module.equals(potentialQName.getModule())
+ && key.getSimpleName().equals(
+ BindingMapping.getClassName(potentialQName) + BindingMapping.getClassName(qname))) {
+ rpc = potential;
+ break;
+ }
+ }
+ Preconditions.checkArgument(rpc != null, "Supplied class %s is not valid RPC class.", key);
+ final ContainerSchemaNode schema = SchemaNodeUtils.getRpcDataSchema(rpc, qname);
+ Preconditions.checkArgument(schema != null, "Schema for %s does not define input / output.", rpc.getQName());
+ return (ContainerNodeCodecContext) DataContainerCodecPrototype.from(key, schema, factory()).get();
+ }
+
+ private NotificationCodecContext createNotificationDataContext(final Class<?> notificationType) {
+ Preconditions.checkArgument(Notification.class.isAssignableFrom(notificationType));
+ Preconditions.checkArgument(notificationType.isInterface(), "Supplied class must be interface.");
+ final QName qname = BindingReflections.findQName(notificationType);
+ /**
+ * FIXME: After Lithium cleanup of yang-model-api, use direct call on schema context
+ * to retrieve notification via index.
+ */
+ final NotificationDefinition schema = SchemaContextUtil.getNotificationSchema(schema(),
+ SchemaPath.create(true, qname));
+ Preconditions.checkArgument(schema != null, "Supplied %s is not valid notification", notificationType);
+
+ return new NotificationCodecContext(notificationType, schema, factory());
+ }
+
}
\ No newline at end of file
package org.opendaylight.yangtools.binding.data.codec.util;
import com.google.common.base.Preconditions;
-
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
-
import org.opendaylight.yangtools.yang.binding.Augmentable;
import org.opendaylight.yangtools.yang.binding.Augmentation;
import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
} else {
augmentations = BindingReflections.getAugmentations((Augmentable<?>) obj);
}
- for (Entry<Class<? extends Augmentation<?>>, Augmentation<?>> aug : augmentations.entrySet()) {
+ for (final Entry<Class<? extends Augmentation<?>>, Augmentation<?>> aug : augmentations.entrySet()) {
emitAugmentation(aug.getKey(), aug.getValue(), stream, reg);
}
}
}
private Map<Class<? extends Augmentation<?>>, Augmentation<?>> getFromProxy(final DataObject obj) {
- InvocationHandler proxy = Proxy.getInvocationHandler(obj);
+ final InvocationHandler proxy = Proxy.getInvocationHandler(obj);
if (proxy instanceof AugmentationReader) {
return ((AugmentationReader) proxy).getAugmentations(obj);
}
@SuppressWarnings("rawtypes")
private void emitAugmentation(final Class type, final Augmentation<?> value, final BindingStreamEventWriter stream,
final DataObjectSerializerRegistry registry) throws IOException {
+ /*
+ * Binding Specification allowed to insert augmentation with null for
+ * value, which effectively could be used to remove augmentation
+ * from builder / DTO.
+ */
+ if(value == null) {
+ return;
+ }
Preconditions.checkArgument(value instanceof DataObject);
@SuppressWarnings("unchecked")
- DataObjectSerializer serializer = registry.getSerializer(type);
+ final DataObjectSerializer serializer = registry.getSerializer(type);
if (serializer != null) {
serializer.serialize((DataObject) value, stream);
} else {
--- /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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.collect.ImmutableList;
+import javassist.ClassPool;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.TwoLevelListChanged;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.TwoLevelListChangedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListBuilder;
+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.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.Notification;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+public class NotificationProcessingTest extends AbstractBindingRuntimeTest {
+
+ private BindingNormalizedNodeCodecRegistry registry;
+
+ @Override
+ @Before
+ public void setup() {
+ super.setup();
+ final JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+ registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+ registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+ }
+
+ private TwoLevelListChanged createTestData() {
+ final TwoLevelListChangedBuilder tb = new TwoLevelListChangedBuilder();
+ tb.setTopLevelList(ImmutableList.of(new TopLevelListBuilder().setKey(new TopLevelListKey("test")).build()));
+ return tb.build();
+ }
+
+ @Test
+ public void testNotificationToNormalized() {
+ final TwoLevelListChanged bindingOriginal = createTestData();
+ final ContainerNode dom = registry.toNormalizedNodeNotification(bindingOriginal);
+ assertNotNull("Serialization must not return null obejct.",dom);
+ assertEquals(TwoLevelListChanged.QNAME,dom.getIdentifier().getNodeType());
+
+ final Notification bindingDeserialized = registry.fromNormalizedNodeNotification(SchemaPath.create(true, TwoLevelListChanged.QNAME),dom);
+ assertNotNull(bindingDeserialized);
+ assertTrue(bindingDeserialized instanceof TwoLevelListChanged);
+ assertEquals(bindingOriginal,bindingDeserialized);
+ }
+
+}
--- /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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import com.google.common.collect.ImmutableList;
+import javassist.ClassPool;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.GetTopOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.GetTopOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.PutTopInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.PutTopInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListBuilder;
+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.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+public class RpcDataSerializationTest extends AbstractBindingRuntimeTest {
+
+ private BindingNormalizedNodeCodecRegistry registry;
+ private static final QName PUT_TOP = QName.create(PutTopInput.QNAME, "put-top");
+ private static final QName GET_TOP = QName.create(GetTopOutput.QNAME, "get-top");
+
+ private static final SchemaPath PUT_TOP_INPUT = SchemaPath.create(true, PUT_TOP, PutTopInput.QNAME);
+ private static final SchemaPath GET_TOP_OUTPUT = SchemaPath.create(true, GET_TOP, GetTopOutput.QNAME);
+
+ @Override
+ @Before
+ public void setup() {
+ super.setup();
+ final JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+ registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+ registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+ }
+
+ @Test
+ public void testRpcInputToNormalized() {
+ final PutTopInputBuilder tb = new PutTopInputBuilder();
+ tb.setTopLevelList(ImmutableList.of(new TopLevelListBuilder().setKey(new TopLevelListKey("test")).build()));
+ final PutTopInput bindingOriginal = tb.build();
+ final ContainerNode dom = registry.toNormalizedNodeRpcData(bindingOriginal);
+ assertNotNull(dom);
+ assertEquals(PutTopInput.QNAME, dom.getIdentifier().getNodeType());
+
+ final DataObject bindingDeserialized = registry.fromNormalizedNodeRpcData(PUT_TOP_INPUT, dom);
+ assertEquals(bindingOriginal, bindingDeserialized);
+ }
+
+ @Test
+ public void testRpcOutputToNormalized() {
+ final GetTopOutputBuilder tb = new GetTopOutputBuilder();
+ tb.setTopLevelList(ImmutableList.of(new TopLevelListBuilder().setKey(new TopLevelListKey("test")).build()));
+ final GetTopOutput bindingOriginal = tb.build();
+ final ContainerNode dom = registry.toNormalizedNodeRpcData(bindingOriginal);
+ assertNotNull(dom);
+ assertEquals(GetTopOutput.QNAME, dom.getIdentifier().getNodeType());
+
+ final DataObject bindingDeserialized = registry.fromNormalizedNodeRpcData(GET_TOP_OUTPUT, dom);
+ assertEquals(bindingOriginal, bindingDeserialized);
+
+ }
+
+}
import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNode;
import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findNodeInSchemaContext;
import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule;
-
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
-
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
-
import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
import org.opendaylight.yangtools.binding.generator.util.BindingTypes;
import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl;
* <ul>
* <li>are generated from <code>context</code> schema nodes and</li>
* <li>are also part of some of the module in <code>modules</code>
- * set</li>.
+ * set.</li>
* </ul>
* @throws IllegalArgumentException
* <ul>
* <code>schemaNode</code>.
*
* The new builder always implements
- * {@link org.opendaylight.yangtools.yang.binding.DataObject DataObject}.<br />
+ * {@link org.opendaylight.yangtools.yang.binding.DataObject DataObject}.<br>
* If <code>schemaNode</code> is instance of GroupingDefinition it also
* implements {@link org.opendaylight.yangtools.yang.binding.Augmentable
- * Augmentable}.<br />
+ * Augmentable}.<br>
* If <code>schemaNode</code> is instance of
* {@link org.opendaylight.yangtools.yang.model.api.DataNodeContainer
* DataNodeContainer} it can also implement nodes which are specified in
}
}
sb.append(NEW_LINE);
- sb.append("<br />(Source path: <i>");
+ sb.append("<br>(Source path: <i>");
sb.append(moduleSourcePath);
sb.append("</i>):");
sb.append(NEW_LINE);
if (verboseClassComments) {
final Module module = findParentModule(schemaContext, schemaNode);
final StringBuilder linkToBuilderClass = new StringBuilder();
- final StringBuilder linkToKeyClass = new StringBuilder();
final String[] namespace = Iterables.toArray(BSDOT_SPLITTER.split(fullyQualifiedName), String.class);
String className = namespace[namespace.length - 1];
if (hasBuilderClass(schemaNode)) {
linkToBuilderClass.append(className);
linkToBuilderClass.append("Builder");
-
- if (schemaNode instanceof ListSchemaNode) {
- linkToKeyClass.append(className);
- linkToKeyClass.append("Key");
- }
}
sb.append("<p>");
sb.append(module.getName());
sb.append("</b>");
sb.append(NEW_LINE);
- sb.append("<br />(Source path: <i>");
+ sb.append("<br>(Source path: <i>");
sb.append(module.getModuleSourcePath());
sb.append("</i>):");
sb.append(NEW_LINE);
sb.append(NEW_LINE);
sb.append("@see ");
sb.append(linkToBuilderClass);
+ sb.append(NEW_LINE);
if (schemaNode instanceof ListSchemaNode) {
- sb.append("@see ");
- sb.append(linkToKeyClass);
+ final List<QName> keyDef = ((ListSchemaNode)schemaNode).getKeyDefinition();
+ if (keyDef != null && !keyDef.isEmpty()) {
+ sb.append("@see ");
+ sb.append(className);
+ sb.append("Key");
+ }
+ sb.append(NEW_LINE);
}
- sb.append(NEW_LINE);
}
}
sb.append(module.getName());
sb.append("</b>");
sb.append(NEW_LINE);
- sb.append("<br />Source path: <i>");
+ sb.append("<br>Source path: <i>");
sb.append(module.getModuleSourcePath());
sb.append("</i>):");
sb.append(NEW_LINE);
Preconditions.checkArgument(identityType != null, "Supplied QName %s is not a valid identity", key);
try {
return strategy.loadClass(identityType);
- } catch (ClassNotFoundException e) {
+ } catch (final ClassNotFoundException e) {
throw new IllegalArgumentException("Required class " + identityType + "was not found.", e);
}
}
this.strategy = strategy;
this.schemaContext = schema;
- BindingGeneratorImpl generator = new BindingGeneratorImpl(false);
+ final BindingGeneratorImpl generator = new BindingGeneratorImpl(false);
generator.generateTypes(schema);
- Map<Module, ModuleContext> modules = generator.getModuleContexts();
+ final Map<Module, ModuleContext> modules = generator.getModuleContexts();
- for (ModuleContext ctx : modules.values()) {
+ for (final ModuleContext ctx : modules.values()) {
augmentationToSchema.putAll(ctx.getTypeToAugmentation());
typeToDefiningSchema.putAll(ctx.getTypeToSchema());
public Entry<AugmentationIdentifier, AugmentationSchema> getResolvedAugmentationSchema(final DataNodeContainer target,
final Class<? extends Augmentation<?>> aug) {
- AugmentationSchema origSchema = getAugmentationDefinition(aug);
+ final AugmentationSchema origSchema = getAugmentationDefinition(aug);
/*
* FIXME: Validate augmentation schema lookup
*
* with data and it is up to underlying user to validate data.
*
*/
- Set<QName> childNames = new HashSet<>();
- Set<DataSchemaNode> realChilds = new HashSet<>();
- for (DataSchemaNode child : origSchema.getChildNodes()) {
+ final Set<QName> childNames = new HashSet<>();
+ final Set<DataSchemaNode> realChilds = new HashSet<>();
+ for (final DataSchemaNode child : origSchema.getChildNodes()) {
realChilds.add(target.getDataChildByName(child.getQName()));
childNames.add(child.getQName());
}
- AugmentationIdentifier identifier = new AugmentationIdentifier(childNames);
- AugmentationSchema proxy = new AugmentationSchemaProxy(origSchema, realChilds);
+ final AugmentationIdentifier identifier = new AugmentationIdentifier(childNames);
+ final AugmentationSchema proxy = new AugmentationSchemaProxy(origSchema, realChilds);
return new AbstractMap.SimpleEntry<>(identifier, proxy);
}
* @throws IllegalArgumentException If supplied class does not represent case.
*/
public Optional<ChoiceCaseNode> getCaseSchemaDefinition(final ChoiceNode schema, final Class<?> childClass) throws IllegalArgumentException {
- DataSchemaNode origSchema = getSchemaDefinition(childClass);
+ final DataSchemaNode origSchema = getSchemaDefinition(childClass);
Preconditions.checkArgument(origSchema instanceof ChoiceCaseNode, "Supplied schema %s is not case.", origSchema);
/* FIXME: Make sure that if there are multiple augmentations of same
* which was used to generate supplied class.
*/
public Entry<GeneratedType, Object> getTypeWithSchema(final Class<?> type) {
- Object schema = typeToDefiningSchema.get(referencedType(type));
- Type definedType = typeToDefiningSchema.inverse().get(schema);
+ final Object schema = typeToDefiningSchema.get(referencedType(type));
+ final Type definedType = typeToDefiningSchema.inverse().get(schema);
Preconditions.checkNotNull(schema);
Preconditions.checkNotNull(definedType);
if(definedType instanceof GeneratedTypeBuilder) {
}
public ImmutableMap<Type, Entry<Type, Type>> getChoiceCaseChildren(final DataNodeContainer schema) {
- Map<Type,Entry<Type,Type>> childToCase = new HashMap<>();;
- for (ChoiceNode choice : FluentIterable.from(schema.getChildNodes()).filter(ChoiceNode.class)) {
- ChoiceNode originalChoice = getOriginalSchema(choice);
- Type choiceType = referencedType(typeToDefiningSchema.inverse().get(originalChoice));
- Collection<Type> cases = choiceToCases.get(choiceType);
+ final Map<Type,Entry<Type,Type>> childToCase = new HashMap<>();;
+ for (final ChoiceNode choice : FluentIterable.from(schema.getChildNodes()).filter(ChoiceNode.class)) {
+ final ChoiceNode originalChoice = getOriginalSchema(choice);
+ final Type choiceType = referencedType(typeToDefiningSchema.inverse().get(originalChoice));
+ final Collection<Type> cases = choiceToCases.get(choiceType);
for (Type caze : cases) {
- Entry<Type,Type> caseIdentifier = new SimpleEntry<>(choiceType,caze);
- HashSet<Type> caseChildren = new HashSet<>();
+ final Entry<Type,Type> caseIdentifier = new SimpleEntry<>(choiceType,caze);
+ final HashSet<Type> caseChildren = new HashSet<>();
if (caze instanceof GeneratedTypeBuilder) {
caze = ((GeneratedTypeBuilder) caze).toInstance();
}
collectAllContainerTypes((GeneratedType) caze, caseChildren);
- for (Type caseChild : caseChildren) {
+ for (final Type caseChild : caseChildren) {
childToCase.put(caseChild, caseIdentifier);
}
}
}
public Set<Class<?>> getCases(final Class<?> choice) {
- Collection<Type> cazes = choiceToCases.get(referencedType(choice));
- Set<Class<?>> ret = new HashSet<>(cazes.size());
- for(Type caze : cazes) {
+ final Collection<Type> cazes = choiceToCases.get(referencedType(choice));
+ final Set<Class<?>> ret = new HashSet<>(cazes.size());
+ for(final Type caze : cazes) {
try {
final Class<?> c = strategy.loadClass(caze);
ret.add(c);
- } catch (ClassNotFoundException e) {
+ } catch (final ClassNotFoundException e) {
LOG.warn("Failed to load class for case {}, ignoring it", caze, e);
}
}
return ret;
}
- public Class<?> getClassForSchema(final DataSchemaNode childSchema) {
- DataSchemaNode origSchema = getOriginalSchema(childSchema);
- Type clazzType = typeToDefiningSchema.inverse().get(origSchema);
+ public Class<?> getClassForSchema(final SchemaNode childSchema) {
+ final SchemaNode origSchema = getOriginalSchema(childSchema);
+ final Type clazzType = typeToDefiningSchema.inverse().get(origSchema);
try {
return strategy.loadClass(clazzType);
- } catch (ClassNotFoundException e) {
+ } catch (final ClassNotFoundException e) {
throw new IllegalStateException(e);
}
}
public ImmutableMap<AugmentationIdentifier,Type> getAvailableAugmentationTypes(final DataNodeContainer container) {
final Map<AugmentationIdentifier,Type> identifierToType = new HashMap<>();
if (container instanceof AugmentationTarget) {
- Set<AugmentationSchema> augments = ((AugmentationTarget) container).getAvailableAugmentations();
- for (AugmentationSchema augment : augments) {
+ final Set<AugmentationSchema> augments = ((AugmentationTarget) container).getAvailableAugmentations();
+ for (final AugmentationSchema augment : augments) {
// Augmentation must have child nodes if is to be used with Binding classes
AugmentationSchema augOrig = augment;
while (augOrig.getOriginalDefinition().isPresent()) {
}
if (!augment.getChildNodes().isEmpty()) {
- Type augType = typeToDefiningSchema.inverse().get(augOrig);
+ final Type augType = typeToDefiningSchema.inverse().get(augOrig);
if (augType != null) {
identifierToType.put(getAugmentationIdentifier(augment),augType);
}
}
private AugmentationIdentifier getAugmentationIdentifier(final AugmentationSchema augment) {
- Set<QName> childNames = new HashSet<>();
- for (DataSchemaNode child : augment.getChildNodes()) {
+ final Set<QName> childNames = new HashSet<>();
+ for (final DataSchemaNode child : augment.getChildNodes()) {
childNames.add(child.getQName());
}
return new AugmentationIdentifier(childNames);
}
private static Set<Type> collectAllContainerTypes(final GeneratedType type, final Set<Type> collection) {
- for (MethodSignature definition : type.getMethodDefinitions()) {
+ for (final MethodSignature definition : type.getMethodDefinitions()) {
Type childType = definition.getReturnType();
if(childType instanceof ParameterizedType) {
childType = ((ParameterizedType) childType).getActualTypeArguments()[0];
collection.add(referencedType(childType));
}
}
- for (Type parent : type.getImplements()) {
+ for (final Type parent : type.getImplements()) {
if (parent instanceof GeneratedType) {
collectAllContainerTypes((GeneratedType) parent, collection);
}
private static final <T extends SchemaNode> T getOriginalSchema(final T choice) {
@SuppressWarnings("unchecked")
- T original = (T) SchemaNodeUtils.getRootOriginalIfPossible(choice);
+ final T original = (T) SchemaNodeUtils.getRootOriginalIfPossible(choice);
if (original != null) {
return original;
}
*/
package org.opendaylight.yangtools.sal.binding.generator.util;
-import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
+import com.google.common.base.Preconditions;
import java.net.URI;
import java.util.Date;
-import java.util.List;
-
+import java.util.Iterator;
+import javax.annotation.Nullable;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
import org.opendaylight.yangtools.yang.model.api.NamespaceRevisionAware;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
public static QName getAugmentationQName(final AugmentationSchema augmentation) {
checkNotNull(augmentation, "Augmentation must not be null.");
- QName identifier = getAugmentationIdentifier(augmentation);
+ final QName identifier = getAugmentationIdentifier(augmentation);
if(identifier != null) {
return identifier;
}
revision = ((NamespaceRevisionAware) augmentation).getRevision();
}
if(namespace == null || revision == null) {
- for(DataSchemaNode child : augmentation.getChildNodes()) {
+ for(final DataSchemaNode child : augmentation.getChildNodes()) {
// Derive QName from child nodes
if(!child.isAugmenting()) {
namespace = child.getQName().getNamespace();
}
public static QName getAugmentationIdentifier(final AugmentationSchema augmentation) {
- for(UnknownSchemaNode extension : augmentation.getUnknownSchemaNodes()) {
+ for(final UnknownSchemaNode extension : augmentation.getUnknownSchemaNodes()) {
if(AUGMENT_IDENTIFIER.equals(extension.getNodeType().getLocalName())) {
return extension.getQName();
}
return null;
}
+ @Nullable
public static TypeDefinition<?> findTypeDefinition(final SchemaContext context, final SchemaPath path) {
- List<QName> arguments = path.getPath();
- QName first = arguments.get(0);
- QName typeQName = arguments.get(arguments.size() -1);
- DataNodeContainer previous = context.findModuleByNamespaceAndRevision(first.getNamespace(), first.getRevision());
- if(previous == null) {
+ final Iterator<QName> arguments = path.getPathFromRoot().iterator();
+ Preconditions.checkArgument(arguments.hasNext(), "Type Definition path must contain at least one element.");
+
+ QName currentArg = arguments.next();
+ DataNodeContainer currentNode = context.findModuleByNamespaceAndRevision(currentArg.getNamespace(), currentArg.getRevision());
+ if(currentNode == null) {
return null;
}
- checkArgument(arguments.size() == 1);
- for(TypeDefinition<?> typedef : previous.getTypeDefinitions()) {
- if(typedef.getQName().equals(typeQName)) {
+ // Last argument is type definition, so we need to cycle until we hit last argument.
+ while(arguments.hasNext()) {
+ // Nested private type - we need to find container/grouping to which type belongs.
+ final DataSchemaNode child = currentNode.getDataChildByName(currentArg);
+ if(child instanceof DataNodeContainer) {
+ currentNode = (DataNodeContainer) child;
+ } else if (child instanceof ChoiceNode) {
+ final QName caseQName = arguments.next();
+ Preconditions.checkArgument(arguments.hasNext(), "Path must not refer case only.");
+ currentNode = ((ChoiceNode) child).getCaseNodeByName(caseQName);
+ } else {
+ // Search in grouping
+ for( final GroupingDefinition grouping : currentNode.getGroupings()) {
+ if(currentArg.equals(grouping.getQName())) {
+ currentNode = grouping;
+ break;
+ }
+ }
+ }
+ currentArg = arguments.next();
+ }
+
+ for(final TypeDefinition<?> typedef : currentNode.getTypeDefinitions()) {
+ if(typedef.getQName().equals(currentArg)) {
return typedef;
}
}
/**
* Returns an instance of {@link ParameterizedType} describing the typed
- * {@link Map}<K,V>
+ * {@link Map}<K,V>
*
* @param keyType
* Key Type
/**
* Returns an instance of {@link ParameterizedType} describing the typed
- * {@link Set}<V> with concrete type of value.
+ * {@link Set}<V> with concrete type of value.
*
* @param valueType
* Value Type
/**
* Returns an instance of {@link ParameterizedType} describing the typed
- * {@link List}<V> with concrete type of value.
+ * {@link List}<V> with concrete type of value.
*
* @param valueType
* Value Type
*/
package org.opendaylight.yangtools.sal.java.api.generator
+import com.google.common.base.CharMatcher
+import com.google.common.base.Splitter
import com.google.common.collect.ImmutableList
import com.google.common.collect.Range
import java.math.BigDecimal
import java.util.List
import java.util.Map
import java.util.StringTokenizer
+import java.util.regex.Pattern
import org.opendaylight.yangtools.binding.generator.util.Types
import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType
import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty
protected val GeneratedType type;
protected val Map<String, String> importMap;
- private static final String NEW_LINE = '\n'
+ private static final char NEW_LINE = '\n'
+ private static final CharMatcher NL_MATCHER = CharMatcher.is(NEW_LINE)
+ private static final CharMatcher TAB_MATCHER = CharMatcher.is('\t')
+ private static final Pattern SPACES_PATTERN = Pattern.compile(" +")
+ private static final Splitter NL_SPLITTER = Splitter.on(NL_MATCHER)
new(GeneratedType _type) {
if (_type == null) {
}
def String wrapToDocumentation(String text) {
- val StringTokenizer tokenizer = new StringTokenizer(text, "\n", false)
- val StringBuilder sb = new StringBuilder()
-
- if(text.empty)
+ if (text.empty)
return ""
- sb.append("/**")
+ val StringBuilder sb = new StringBuilder("/**")
sb.append(NEW_LINE)
- while(tokenizer.hasMoreTokens) {
+ for (String t : NL_SPLITTER.split(text)) {
sb.append(" * ")
- sb.append(tokenizer.nextToken)
+ sb.append(t)
sb.append(NEW_LINE)
}
sb.append(" */")
'''.toString
}
+ private static final CharMatcher AMP_MATCHER = CharMatcher.is('&');
+ private static final CharMatcher GT_MATCHER = CharMatcher.is('>');
+ private static final CharMatcher LT_MATCHER = CharMatcher.is('<');
+
def encodeJavadocSymbols(String description) {
- if (!description.nullOrEmpty) {
- return description.replace("*/", "*/")
+ if (description.nullOrEmpty) {
+ return description;
}
- return description;
+
+ var ret = description.replace("*/", "*/")
+
+ // FIXME: Use Guava's HtmlEscapers once we have it available
+ ret = AMP_MATCHER.replaceFrom(ret, "&");
+ ret = GT_MATCHER.replaceFrom(ret, ">");
+ ret = LT_MATCHER.replaceFrom(ret, "<");
+ return ret;
}
def protected String formatDataForJavaDoc(GeneratedType type, String additionalComment) {
var char lastChar = ' '
var boolean badEnding = false
- if(text.endsWith(".") || text.endsWith(":") || text.endsWith(",")) {
+ if (text.endsWith('.') || text.endsWith(':') || text.endsWith(',')) {
tempText = text.substring(0, text.length - 1)
lastChar = text.charAt(text.length - 1)
badEnding = true
var boolean isFirstElementOnNewLineEmptyChar = false;
formattedText = formattedText.encodeJavadocSymbols
- formattedText = formattedText.replace(NEW_LINE, "")
- formattedText = formattedText.replace("\t", "")
- formattedText = formattedText.replaceAll(" +", " ");
+ formattedText = NL_MATCHER.removeFrom(formattedText)
+ formattedText = TAB_MATCHER.removeFrom(formattedText)
+ formattedText = SPACES_PATTERN.matcher(formattedText).replaceAll(" ")
val StringTokenizer tokenizer = new StringTokenizer(formattedText, " ", true);
import org.opendaylight.yangtools.yang.binding.Augmentable
import org.opendaylight.yangtools.yang.binding.DataObject
import org.opendaylight.yangtools.yang.binding.Identifiable
+import org.opendaylight.yangtools.concepts.Builder
/**
* Template for generating JAVA builder classes.
*/
val static BUILDER = 'Builder'
+ /**
+ * Constant with the name of the BuilderFor interface
+ */
+ val static BUILDERFOR = Builder.simpleName;
+
/**
* Constant with suffix for the classes which are generated from the builder classes.
*/
new(GeneratedType genType) {
super(genType)
this.properties = propertiesFromMethods(createMethods)
+ importMap.put(Builder.simpleName, Builder.package.name)
}
/**
*/
override body() '''
«wrapToDocumentation(formatDataForJavaDoc(type))»
- public class «type.name»«BUILDER» {
+ public class «type.name»«BUILDER» implements «BUILDERFOR» <«type.importedName»> {
«generateFields(false)»
«IF augmentField != null»
public «type.name»«BUILDER» add«augmentField.name.toFirstUpper»(«Class.importedName»<? extends «augmentField.returnType.importedName»> augmentationType, «augmentField.returnType.importedName» augmentation) {
+ if (augmentation == null) {
+ return remove«augmentField.name.toFirstUpper»(augmentationType);
+ }
this.«augmentField.name».put(augmentationType, augmentation);
return this;
}
+
+ public «type.name»«BUILDER» remove«augmentField.name.toFirstUpper»(«Class.importedName»<? extends «augmentField.returnType.importedName»> augmentationType) {
+ this.«augmentField.name».remove(augmentationType);
+ return this;
+ }
«ENDIF»
'''
* @param type
* Input type to be processed
* @return generated JAVA code
- * @throws IOException
*/
String generate(Type type);
package org.opendaylight.yangtools.sal.binding.model.api;
/**
- * Represents an instance of simple parametrized type such as List<String>.
+ * Represents an instance of simple parametrized type such as List<String>.
*
* The parametrized Type is designed to be used to store information of Java
* Generic Type. The array of {@link #getActualTypeArguments()} holds
* Returns array of Types that are defined for Parameterized Type.
* <br>
* (for example if ParameterizedType encapsulates java generic Map that
- * specifies two parameters Map<K,V> and the K is java.lang.Integer and V
+ * specifies two parameters Map<K,V> and the K is java.lang.Integer and V
* is defined as GeneratedType the array will contain two Types to store
* the information of generic parameters.)
*
uses two-level-list;
}
}
+
+ notification two-level-list-changed {
+ uses two-level-list;
+ }
+
+ rpc get-top {
+ output {
+ uses two-level-list;
+ }
+ }
}
/**
* Sorts set <code>groupingDefinitions</code> according to the mutual
- * dependencies.<br />
+ * dependencies.<br>
*
* Elements of <code>groupingDefinitions</code> are firstly transformed to
* {@link org.opendaylight.yangtools.yang.parser.util.TopologicalSort.Node
* Node} interfaces and then are sorted by
* {@link org.opendaylight.yangtools.yang.parser.util.TopologicalSort#sort(Set)
- * sort()} method of <code>TopologicalSort</code>.<br />
- * <br />
+ * sort()} method of <code>TopologicalSort</code>.<br>
+ * <br>
*
*
- * <i>Definition of dependency relation:<br />
+ * <i>Definition of dependency relation:<br>
* The first <code>GroupingDefinition</code> object (in this context)
* depends on second <code>GroupingDefinition</code> object if the first one
* contains in its set of <code>UsesNode</code> (obtained through
<version>0.7.0-SNAPSHOT</version>
<packaging>pom</packaging>
- <prerequisites>
- <maven>3.0.4</maven>
- </prerequisites>
-
<properties>
<!-- Model versions -->
<ietf.topology.version>2013.10.21.7-SNAPSHOT</ietf.topology.version>
* This interface is mutually exclusive with {@link Mutable} and other
* {@link MutationBehaviour}s.
*
- * @author Robert Varga <rovarga@cisco.com>
- * @author Tony Tkacik <ttkacik@cisco.com>
+ * @author Robert Varga
+ * @author Tony Tkacik
*
*/
public interface Immutable extends MutationBehaviour<Immutable> {
* This interface is mutually exclusive with {@link Immutable} and other
* {@link MutationBehaviour}s.
*
- * @author Tony Tkacik <ttkacik@cisco.com>
+ * @author Tony Tkacik
*
*/
public interface Mutable extends MutationBehaviour<Mutable>{
* This interface is used to prevent same class extends multiple types of MutationBehaviour
* such as {@link Immutable} and {@link Mutable} which are mutually exclusive.
*
- * @author Tony Tkacik <ttkacik@cisco.com>
+ * @author Tony Tkacik
*
* @param <T> Mutation Type
*/
<relativePath>/../../common/parent/pom.xml</relativePath>
</parent>
-
<modelVersion>4.0.0</modelVersion>
<artifactId>mockito-configuration</artifactId>
<description>Default mockito configuration</description>
<packaging>jar</packaging><!-- not needed in OSGi -->
<name>${project.artifactId}</name>
- <prerequisites>
- <maven>3.0.4</maven>
- </prerequisites>
<dependencies>
<!-- all those dependencies will be in test scope as mockito-configuration should be referenced as test scope dependency -->
<groupId>org.opendaylight.yangtools</groupId>
<version>0.7.0-SNAPSHOT</version>
<packaging>pom</packaging>
- <prerequisites>
- <maven>3.0.4</maven>
- </prerequisites>
<properties>
<yangtools.version>0.7.0-SNAPSHOT</yangtools.version>
<sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin>
<sonar.jacoco.reportPath>target/code-coverage/jacoco.exec</sonar.jacoco.reportPath>
<sonar.jacoco.itReportPath>target/code-coverage/jacoco-it.exec</sonar.jacoco.itReportPath>
- <sonar.profile>Sonar way with Findbugs</sonar.profile>
</properties>
- <profiles>
- <profile>
- <id>jdk1.8</id>
- <activation>
- <jdk>1.8</jdk>
- </activation>
- <build>
- <pluginManagement>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-javadoc-plugin</artifactId>
- <version>${maven.javadoc.version}</version>
- <configuration>
- <stylesheetfile>stylesheet.css</stylesheetfile>
- <additionalparam>-Xdoclint:none</additionalparam>
- </configuration>
- <executions>
- <execution>
- <id>attach-javadocs</id>
- <goals>
- <goal>jar</goal>
- </goals>
- </execution>
- <execution>
- <goals>
- <goal>aggregate</goal>
- </goals>
- <phase>site</phase>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </pluginManagement>
- </build>
- </profile>
- </profiles>
-
<dependencyManagement>
<dependencies>
<!-- Testing Dependencies -->
<!-- Note: we can not use variables for these URLs because we need to
- be able to download the parent pom from the repository the first
+ be able to download the parent pom from the repository the first
time we go to use it (since it is in a different project).
To override the settings, use the "mirror" section of the
settings.xml. See http://maven.apache.org/settings.html -->
/**
* Create a new instance, with internal hash initialized to 1,
- * equivalent of {@link #HashCodeBuilder(1)}.
+ * equivalent of <code>HashCodeBuilder(1)</code>.
*/
public HashCodeBuilder() {
this(1);
import com.google.common.util.concurrent.ListenableFuture;
/**
- * An {@link ListeningExecutorService} implementation that also allows for an {@link Executor} to be
+ * An {@link com.google.common.util.concurrent.ListeningExecutorService} implementation that also allows for an {@link Executor} to be
* specified on construction that is used to execute {@link ListenableFuture} callback Runnables,
- * registered via {@link Futures#addCallback} or {@link ListenableFuture#addListener} directly,
+ * registered via {@link com.google.common.util.concurrent.Futures#addCallback} or {@link ListenableFuture#addListener} directly,
* asynchronously when a task that is run on this executor completes. This is useful when you want
* to guarantee listener callback executions are off-loaded onto another thread to avoid blocking
* the thread that completed the task, as a common use case is to pass an executor that runs tasks
* in the same thread as the caller (ie <code>MoreExecutors#sameThreadExecutor</code>}) to
* {@link ListenableFuture#addListener}.
* <p>
- * Most commonly, this class would be used in lieu of <code>MoreExecutors#listeningDecorator<code>
+ * Most commonly, this class would be used in lieu of <code>MoreExecutors#listeningDecorator</code>
* when the underlying delegate Executor is single-threaded, in which case, you may not want
* ListenableFuture callbacks to block the single thread.
* <p>
/**
* An implementation of ListeningExecutorService that attempts to detect deadlock scenarios that
- * could occur if clients invoke the returned Future's <ode>get</code> methods synchronously.
+ * could occur if clients invoke the returned Future's <code>get</code> methods synchronously.
* <p>
* Deadlock scenarios are most apt to occur with a backing single-threaded executor where setting of
* the Future's result is executed on the single thread. Here's a scenario:
* A ThreadPoolExecutor with a specified bounded queue capacity that favors creating new threads
* over queuing, as the former is faster.
* <p>
- * See {@link SpecialExecutors#newFastBlockingThreadPool} for more details.
+ * See {@link SpecialExecutors#newBoundedFastThreadPool} for more details.
*
* @author Thomas Pantelis
*/
/**
* Holds largestQueueSize, this long field should be only accessed
- * using {@value #LARGEST_QUEUE_SIZE_UPDATER}
+ * using {@link #LARGEST_QUEUE_SIZE_UPDATER}
*/
private volatile int largestQueueSize = 0;
* Reads data from data store and return's result in future.
*
* This call is equivalent to invocation of {@link #readData(InstanceIdentifier, RetrievalStrategy)}
- * with {@link DefaultRetrievalStrategy.Default}.
+ * with {@link DefaultRetrievalStrategy#getInstance()}.
*
* @param path InstanceIdentifier representing path in YANG schema to be retrieved.
* @return Future promising the data requested. If the requested data are not present returns value of {@link Optional#absent()}.
}
/**
- * Writes a String message via {@link ChannelOutboundInvoker} through the
- * {@link ChannelPipeline} and request to actual {@link #flush()} to flush
+ * Writes a String message through the
+ * {@link ChannelPipeline} and request to actual {@link Channel#flush()} to flush
* all pending data to the actual transport.
*
* @param message
}
/**
- * Writes a Object message via {@link ChannelOutboundInvoker} through the
- * {@link ChannelPipeline} and request to actual {@link #flush()} to flush
+ * Writes a Object message through the
+ * {@link ChannelPipeline} and request to actual {@link Channel#flush()} to flush
* all pending data to the actual transport.
*
* @param message
}
/**
- * Writes {@link PingWebSocketFrame} via {@link ChannelOutboundInvoker}
+ * Writes {@link PingWebSocketFrame}
* through the {@link ChannelPipeline} and request to actual
- * {@link #flush()} to flush all pending data to the actual transport.
+ * {@link Channel#flush()} to flush all pending data to the actual transport.
*/
public void ping() {
clientChannel.writeAndFlush(new PingWebSocketFrame(Unpooled
* also adds marker interface for augmentations (extensions) -
* {@link Augmentable}
*
- * @author Tony Tkacik <ttkacik@cisco.com>
+ * @author Tony Tkacik
* @param <T>
* Base class which should implements this interface and is target
* for augmentation.
*
* <li><code>list</code> - YANG list statement has two representation in event
* stream - unkeyed list and map. Unkeyed list is YANG list which did not
- * specify key.</li>
+ * specify key.
*
* <ul>
* <li><code>Map</code> - Map start event is emitted using
* <li><code>UnkeyedList</code> - Unkeyed list represent list without keys,
* unkeyed list start is emitted using {@link #startUnkeyedList(Class, int)} list
* end is emitted using {@link #endNode()}. Each list item is emitted using
- * {@link #startUnkeyedListItem()} and ended using {@link #endNode()}.</li>
- * </ul>
+ * {@link #startUnkeyedListItem(int)} and ended using {@link #endNode()}.</li>
+ * </ul></li>
*
* <li><code>leaf</code> - Leaf node event is emitted using
* {@link #leafNode(String, Object)}. {@link #endNode()} MUST be not emitted for
* <li><code>leaf-list</code> - Leaf list start is emitted using
* {@link #startLeafSet(String, int)}. Leaf list end is emitted using
* {@link #endNode()}. Leaf list entries are emitted using
- * {@link #leafSetEntryNode(Object).
+ * {@link #leafSetEntryNode(Object)}.
*
* <li><code>anyxml - Anyxml node event is emitted using
* {@link #leafNode(String, Object)}. {@link #endNode()} MUST be not emitted
*
* <p>
* End of unkeyed list event is emitted by invoking {@link #endNode()}.
- * Valid subevents is only {@link #startUnkeyedListItem()}. All other
+ * Valid subevents is only {@link #startUnkeyedListItem(int)}. All other
* methods will throw {@link IllegalArgumentException}.
*
* @param localName
*
* <p>
* Valid sub-events are:
- * <<p>
- * Valid sub-events are:
* <ul>
* <li>{@link #leafNode(String, Object)}</li>
* <li>{@link #startContainerNode(Class, int)}</li>
* Emits start of choice node.
*
* <p>
- * Valid sub-event in {@link #startCase(QName, int)}, which selects case
+ * Valid sub-event in {@link #startCase(Class, int)}, which selects case
* which should be written.
- * <ul>
*
- * @param localName
- * name of node as defined in schema, namespace and revision are
- * derived from parent node.
+ * @param choice
+ * Choice class.
* @param childSizeHint
* Non-negative count of expected direct child nodes or
* {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
* events than count.
* @throws IllegalArgumentException
* @throws IllegalStateException
- * If node was emitted inside <code>map</code>, <code>choice
- * </code> <code>unkeyed list</code> node.
+ * If node was emitted inside <code>map</code>, <code>choice</code>,
+ * <code>unkeyed list</code> node.
* @throws IOException if an underlying IO error occurs
*/
void startChoiceNode(Class<? extends DataContainer> choice, int childSizeHint) throws IOException, IllegalArgumentException;
* <li>{@link #startAugmentationNode(Class)}</li>
* </ul>
*
- * @param name
+ * @param caze Case class
* @throws IllegalArgumentException
* @throws IOException if an underlying IO error occurs
*/
* <p>
* Valid sub-events are:
*
- * <p>
- * Valid sub-events are:
* <ul>
* <li>{@link #leafNode(String, Object)}</li>
* <li>{@link #startContainerNode(Class, int)}</li>
* Note this is only method, which does not require childSizeHint, since
* maximum value is always size of <code>possibleChildren</code>.
*
- * @param module
- * QName module of YANG module in which augmentation was defined
- * @param possibleChildren
- * Local names of all valid children defined by augmentation.
+ * @param augmentationType augmentation class
* @throws IllegalArgumentException
* If augmentation is invalid in current context.
* @throws IOException if an underlying IO error occurs
/**
* Data container is an interface which has structured contents.
*
- *
- * @author Tony Tkacik <ttkacik@cisco.com>
+ * @author Tony Tkacik
*
*/
public interface DataObject extends DataContainer {
* Check whether an instance identifier contains any wildcards. A wildcard
* is an path argument which has a null key.
*
- * @return @true if any of the path arguments has a null key.
+ * @return true if any of the path arguments has a null key.
*/
public final boolean isWildcarded() {
return wildcarded;
* quick checks on their specific fields.
*
* @param other The other identifier, guaranteed to be the same class
- * @return @true if the other identifier cannot be equal to this one.
+ * @return true if the other identifier cannot be equal to this one.
*/
protected boolean fastNonEqual(final InstanceIdentifier<?> other) {
return false;
* non-wildcarded PathArgument counterpart.
*
* @param other Identifier which should be checked for inclusion.
- * @return @true if this identifier contains the other object
+ * @return true if this identifier contains the other object
*/
public final boolean containsWildcarded(final InstanceIdentifier<?> other) {
Preconditions.checkNotNull(other, "other should not be null");
/**
* Create a new InstanceIdentifierBuilder given a base InstanceIdentifier
*
- * @param basePath
+ * @param base
* @param <T>
* @return
*
*
* Example
* <pre>
- * List<PathArgument> path = Arrays.asList(new Item(Nodes.class))
+ * List<PathArgument> path = Arrays.asList(new Item(Nodes.class))
* new InstanceIdentifier(path);
* </pre>
*
* This method uses first generic argument of
* implemented {@link ChildOf} interface.
*
- * @param augmentation
- * {@link Augmentation} subclass for which we want to determine
- * augmentation target.
- * @return Augmentation target - class which augmentation provides
- * additional extensions.
+ * @param childClass
+ * child class for which we want to find the parent class.
+ * @return Parent class, e.g. class of which the childClass is ChildOf.
*/
public static Class<?> findHierarchicalParent(final Class<? extends ChildOf<?>> childClass) {
return ClassLoaderUtils.findFirstGenericArgument(childClass, ChildOf.class);
* This method is shorthand which gets DataObject class by invoking
* {@link DataObject#getImplementedInterface()} and uses {@link #findHierarchicalParent(Class)}.
*
- * @param childClass
- * {@link Augmentation} subclass for which we want to determine
- * augmentation target.
- * @return Augmentation target - class which augmentation provides
- * additional extensions.
+ * @param child
+ * Child object for which the parent needs to be located.
+ * @return Parent class, or null if a parent is not found.
*/
public static Class<?> findHierarchicalParent(final DataObject child) {
if (child instanceof ChildOf) {
/**
* Returns root package name for supplied package name.
*
- * @param pkg Package for which find model root package.
+ * @param name Package for which find model root package.
* @return Package of model root.
*/
public static String getModelRootPackageName(final String name) {
/**
* Look up specified QName in the global cache and return a shared reference.
*
- * @param module QName instance
+ * @param qname QName instance
* @return Cached instance, according to {@link ObjectCache} policy.
*/
public static QName cachedReference(final QName qname) {
* {@link QName} and its {@link #getLocalName()}, {@link #getNamespace()} and
* {@link #getRevision()} are equals to same properties of this instance.
*
- * @param o the object to be compared for equality with this QName
+ * @param obj the object to be compared for equality with this QName
* @return <tt>true</tt> if the specified object is equal to this QName
*
*/
/**
* Returns the namespace of the module which is specified as argument of
- * YANG {@link Module <b><font color="#00FF00">namespace</font></b>}
- * keyword.
+ * YANG Module <b><font color="#00FF00">namespace</font></b> keyword.
*
* @return URI format of the namespace of the module
*/
* Returns the revision date for the module.
*
* @return date of the module revision which is specified as argument of
- * YANG {@link Module <b><font color="#339900">revison</font></b>}
- * keyword
+ * YANG Module <b><font color="#339900">revison</font></b> keyword
*/
public Date getRevision() {
return revision;
package org.opendaylight.yangtools.yang.common;
+import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
import java.util.Collection;
import java.util.Collections;
-
+import org.opendaylight.yangtools.concepts.Builder;
import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
-import com.google.common.collect.ImmutableList;
-
/**
* A builder for creating RpcResult instances.
*
*
* @param <T> the result value type
*/
-public final class RpcResultBuilder<T> {
+public final class RpcResultBuilder<T> implements Builder<RpcResult<T>> {
private static class RpcResultImpl<T> implements RpcResult<T> {
private final T result;
private final boolean successful;
- RpcResultImpl( boolean successful, T result,
- Collection<RpcError> errors ) {
+ RpcResultImpl( final boolean successful, final T result,
+ final Collection<RpcError> errors ) {
this.successful = successful;
this.result = result;
this.errors = errors;
private final ErrorType errorType;
private final Throwable cause;
- RpcErrorImpl( ErrorSeverity severity, ErrorType errorType,
- String tag, String message, String applicationTag, String info,
- Throwable cause ) {
+ RpcErrorImpl( final ErrorSeverity severity, final ErrorType errorType,
+ final String tag, final String message, final String applicationTag, final String info,
+ final Throwable cause ) {
this.severity = severity;
this.errorType = errorType;
this.tag = tag;
private T result;
private final boolean successful;
- private RpcResultBuilder( boolean successful, T result ) {
+ private RpcResultBuilder( final boolean successful, final T result ) {
this.successful = successful;
this.result = result;
}
*
* @param result the result value
*/
- public static <T> RpcResultBuilder<T> success( T result ) {
+ public static <T> RpcResultBuilder<T> success( final T result ) {
return new RpcResultBuilder<T>( true, result );
}
+ /**
+ * Returns a builder for a successful result.
+ *
+ * @param builder builder for the result value
+ */
+ public static <T> RpcResultBuilder<T> success( final Builder<T> builder ) {
+ return success(builder.build());
+ }
+
/**
* Returns a builder for a failed result.
*/
*
* @param success true if successful, false otherwise.
*/
- public static <T> RpcResultBuilder<T> status( boolean success ) {
+ public static <T> RpcResultBuilder<T> status( final boolean success ) {
return new RpcResultBuilder<T>( success, null );
}
*
* @param other the other RpcResult.
*/
- public static <T> RpcResultBuilder<T> from( RpcResult<T> other ) {
+ public static <T> RpcResultBuilder<T> from( final RpcResult<T> other ) {
return new RpcResultBuilder<T>( other.isSuccessful(), other.getResult() )
.withRpcErrors( other.getErrors() );
}
*
* @return an RpcError
*/
- public static RpcError newError( ErrorType errorType, String tag, String message ) {
+ public static RpcError newError( final ErrorType errorType, final String tag, final String message ) {
return new RpcErrorImpl( ErrorSeverity.ERROR, errorType,
tag != null ? tag : "operation-failed", message, null, null, null );
}
*
* @return an RpcError
*/
- public static RpcError newError( ErrorType errorType, String tag, String message,
- String applicationTag, String info, Throwable cause ) {
+ public static RpcError newError( final ErrorType errorType, final String tag, final String message,
+ final String applicationTag, final String info, final Throwable cause ) {
return new RpcErrorImpl( ErrorSeverity.ERROR, errorType,
tag != null ? tag : "operation-failed", message, applicationTag, info, cause );
}
*
* @return an RpcError
*/
- public static RpcError newWarning( ErrorType errorType, String tag, String message ) {
+ public static RpcError newWarning( final ErrorType errorType, final String tag, final String message ) {
return new RpcErrorImpl( ErrorSeverity.WARNING, errorType, tag, message, null, null, null );
}
*
* @return an RpcError
*/
- public static RpcError newWarning( ErrorType errorType, String tag, String message,
- String applicationTag, String info, Throwable cause ) {
+ public static RpcError newWarning( final ErrorType errorType, final String tag, final String message,
+ final String applicationTag, final String info, final Throwable cause ) {
return new RpcErrorImpl( ErrorSeverity.WARNING, errorType, tag, message,
applicationTag, info, cause );
}
*
* @param result the result value
*/
- public RpcResultBuilder<T> withResult( T result ) {
+ public RpcResultBuilder<T> withResult( final T result ) {
this.result = result;
return this;
}
- private void addError( ErrorSeverity severity, ErrorType errorType,
- String tag, String message, String applicationTag, String info,
- Throwable cause ) {
+ /**
+ * Sets the value of the result.
+ *
+ * @param builder builder for the result value
+ */
+ public RpcResultBuilder<T> withResult( final Builder<T> builder ) {
+ return withResult(builder.build());
+ }
+
+ private void addError( final ErrorSeverity severity, final ErrorType errorType,
+ final String tag, final String message, final String applicationTag, final String info,
+ final Throwable cause ) {
addError( new RpcErrorImpl( severity, errorType,
tag != null ? tag : "operation-failed", message,
applicationTag, info, cause ) );
}
- private void addError( RpcError error ) {
+ private void addError( final RpcError error ) {
if( errors == null ) {
errors = new ImmutableList.Builder<RpcError>();
* {@link RpcError#getTag} for a list of suggested values.
* @param message a string suitable for human display that describes the warning condition.
*/
- public RpcResultBuilder<T> withWarning( ErrorType errorType, String tag, String message ) {
+ public RpcResultBuilder<T> withWarning( final ErrorType errorType, final String tag, final String message ) {
addError( ErrorSeverity.WARNING, errorType, tag, message, null, null, null );
return this;
}
* and/or implementation-specific debugging information.
* @param cause the exception that triggered the warning.
*/
- public RpcResultBuilder<T> withWarning( ErrorType errorType, String tag, String message,
- String applicationTag, String info, Throwable cause ) {
+ public RpcResultBuilder<T> withWarning( final ErrorType errorType, final String tag, final String message,
+ final String applicationTag, final String info, final Throwable cause ) {
addError( ErrorSeverity.WARNING, errorType, tag, message, applicationTag, info, cause );
return this;
}
* @param errorType the conceptual layer at which the error occurred.
* @param message a string suitable for human display that describes the error condition.
*/
- public RpcResultBuilder<T> withError( ErrorType errorType, String message ) {
+ public RpcResultBuilder<T> withError( final ErrorType errorType, final String message ) {
addError( ErrorSeverity.ERROR, errorType, null, message, null, null, null );
return this;
}
* {@link RpcError#getTag} for a list of suggested values.
* @param message a string suitable for human display that describes the error condition.
*/
- public RpcResultBuilder<T> withError( ErrorType errorType, String tag, String message ) {
+ public RpcResultBuilder<T> withError( final ErrorType errorType, final String tag, final String message ) {
addError( ErrorSeverity.ERROR, errorType, tag, message, null, null, null );
return this;
}
* @param message a string suitable for human display that describes the error condition.
* @param cause the exception that triggered the error.
*/
- public RpcResultBuilder<T> withError( ErrorType errorType, String message,
- Throwable cause ) {
+ public RpcResultBuilder<T> withError( final ErrorType errorType, final String message,
+ final Throwable cause ) {
addError( ErrorSeverity.ERROR, errorType, null, message, null, null, cause );
return this;
}
* and/or implementation-specific debugging information.
* @param cause the exception that triggered the error.
*/
- public RpcResultBuilder<T> withError( ErrorType errorType, String tag, String message,
- String applicationTag, String info, Throwable cause ) {
+ public RpcResultBuilder<T> withError( final ErrorType errorType, final String tag, final String message,
+ final String applicationTag, final String info, final Throwable cause ) {
addError( ErrorSeverity.ERROR, errorType, tag, message, applicationTag, info, cause );
return this;
}
*
* @param error the RpcError
*/
- public RpcResultBuilder<T> withRpcError( RpcError error ) {
+ public RpcResultBuilder<T> withRpcError( final RpcError error ) {
addError( error );
return this;
}
*
* @param errors the list of RpcErrors
*/
- public RpcResultBuilder<T> withRpcErrors( Collection<RpcError> errors ) {
+ public RpcResultBuilder<T> withRpcErrors( final Collection<RpcError> errors ) {
if( errors != null ) {
for( RpcError error: errors ) {
addError( error );
return this;
}
+ @Override
public RpcResult<T> build() {
return new RpcResultImpl<T>( successful, result,
errors != null ? errors.build() : Collections.<RpcError>emptyList() );
}
+
+ /**
+ * Builds RpcResult and wraps it in a Future
+ *
+ * This is a convenience method to assist those writing rpcs
+ * that produce immediate results. It allows you to replace
+ *
+ * Futures.immediateFuture(rpcResult.build())
+ *
+ * with
+ *
+ * rpcResult.buildFuture();
+ *
+ * @return Future for RpcResult built by RpcResultBuilder
+ *
+ */
+ public ListenableFuture<RpcResult<T>> buildFuture() {
+ return Futures.immediateFuture(build());
+ }
}
/**
* @author michal.rehak
*
- * @deprecated Use {@link NormalizedNodeUtils} instead.
+ * @deprecated Use {@link org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes} instead.
*/
@Deprecated
public interface NodeModificationBuilder {
}
/**
- *
* Fluent Builder of Instance Identifier instances
- *
- * @
- *
*/
public interface InstanceIdentifierBuilder extends Builder<YangInstanceIdentifier> {
/**
import org.opendaylight.yangtools.concepts.Codec;
/**
- *
- *
* FIXME: In Helium release this codec should be changed to
- * {@link UnsignedShort}
+ * an UnsignedShort (which needs to be defined somewhere).
*
* @author ttkacik
*
* <pre>
* {@code <foo>justSomeString</foo>}
* </pre>
- * </li>
- *
* this AnyXmlNode returns SimpleNode with QName{namespace=someNamespace, revision=someRevision, localName=foo} and value="justSomeString"
+ * </li>
*
* <li>
* but with xml value:
* <pre>
* {@code <foo><bar>stringInXml</bar></foo>}
* </pre>
- * </li>
- *
* this AnyXmlNode returns CompositeNode with QName{}namespace=someNamespace, revision=someRevision, localName=foo}
* and values [SimpleNode with QName{}namespace=someNamespace, revision=someRevision, localName=bar} and value="stringInXml"]
+ * </li>
+ *
* </ul>
- * </p>
*/
public interface AnyXmlNode extends AttributesContainer, DataContainerChild<NodeIdentifier, Node<?>> {
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
/**
- *
* Node representing set of simple leaf nodes.
*
* Node containing instances of {@link LeafSetEntryNode}
*
- * Schema and semantics of this node are described by instance of {@link org.opendaylight.yangtools.yang.model.api.LeafListSchema}.
- *
+ * Schema and semantics of this node are described by instance of {@link org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode}.
*
* @param <T> Type of leaf node values.
*/
* Returns identifier of this node in parent map node
*
* Contents of identifier is defined by <code>key</code> (
- * {@link org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.ListSchemaNode#getKeyDefinition()}
+ * {@link org.opendaylight.yangtools.yang.model.api.ListSchemaNode#getKeyDefinition()}
* ) statement in YANG schema for associated list item and child {@link LeafNode}s
* values with {@link org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier}
* as defined in the schema.
* <li><code>container</code> - Container node representation, start event is
* emitted using {@link #startContainerNode(NodeIdentifier, int)} and node end event is
* emitted using {@link #endNode()}. Container node is implementing
- * {@link DataObject} interface.
+ * the org.opendaylight.yangtools.yang.binding.DataObject interface.
*
* <li><code>list</code> - YANG list statement has two representation in event
* stream - unkeyed list and map. Unkeyed list is YANG list which did not
- * specify key.</li>
+ * specify key.
*
* <ul>
* <li><code>Map</code> - Map start event is emitted using
* unkeyed list start is emitted using {@link #startUnkeyedList(NodeIdentifier, int)} list
* end is emitted using {@link #endNode()}. Each list item is emitted using
* {@link #startUnkeyedListItem(NodeIdentifier, int)} and ended using {@link #endNode()}.</li>
- * </ul>
+ * </ul></li>
*
* <li><code>leaf</code> - Leaf node event is emitted using
* {@link #leafNode(NodeIdentifier, Object)}. {@link #endNode()} MUST NOT BE emitted for
* <li><code>leaf-list</code> - Leaf list start is emitted using
* {@link #startLeafSet(NodeIdentifier, int)}. Leaf list end is emitted using
* {@link #endNode()}. Leaf list entries are emmited using
- * {@link #leafSetEntryNode(Object).
+ * {@link #leafSetEntryNode(Object)}.
*
* <li><code>anyxml - Anyxml node event is emitted using
* {@link #leafNode(NodeIdentifier, Object)}. {@link #endNode()} MUST NOT BE emitted
*/
package org.opendaylight.yangtools.yang.data.api.schema.tree;
+import com.google.common.base.Optional;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import com.google.common.base.Optional;
-
/**
* A single node within a {@link DataTreeCandidate}. The nodes are organized
* in tree hierarchy, reflecting the modification from which this candidate
* tree restricted to the modified nodes.
*/
public interface DataTreeCandidateNode {
+
/**
* Get the node identifier.
*
* @return The node identifier.
*/
- PathArgument getIdentifier();
+ @Nonnull PathArgument getIdentifier();
/**
* Get an unmodifiable iterable of modified child nodes.
*
* @return Unmodifiable iterable of modified child nodes.
*/
- Iterable<DataTreeCandidateNode> getChildNodes();
+ @Nonnull Iterable<DataTreeCandidateNode> getChildNodes();
+
+ /**
+ * Returns modified child or null if child was not modified
+ * / does not exists.
+ *
+ * @param identifier Identifier of child node
+ * @return Modified child or null if child was not modified.
+ */
+ @Nullable DataTreeCandidateNode getModifiedChild(PathArgument identifier);
/**
* Return the type of modification this node is undergoing.
*
* @return Node modification type.
*/
- ModificationType getModificationType();
+ @Nonnull ModificationType getModificationType();
/**
* Return the before-image of data corresponding to the node.
* Create a new data tree modification based on this snapshot, using the
* specified data application strategy.
*
- * @param strategy data modification strategy
* @return A new data tree modification
*/
DataTreeModification newModification();
* Create a new stream writer, which writes to the specified output stream. The codec factory
* can be reused between multiple writers.
*
- * @param codecFactor JSON codec factory
+ * @param codecFactory JSON codec factory
* @param writer Output writer
* @param indentSize indentation size
* @return A stream writer instance
/**
* @param qname
- * @param parent
- * use null to create top composite node (without parent)
* @param value
* @param modifyAction
*/
/**
* Create a new writer with the specified context as its root.
*
- * @param writer Output {@link XMLStreamWriter}
* @param context Associated {@link SchemaContext}.
* @return A new {@link NormalizedNodeStreamWriter}
*/
/**
* Create a new writer with the specified context and rooted in the specified schema path
*
- * @param writer Output {@link XMLStreamWriter}
- * @param context Associated {@link SchemaContext}.
+ * @param context Associated {@link SchemaContext}
+ * @param path schema path
*
* @return A new {@link NormalizedNodeStreamWriter}
*/
*
* @param data Data DOM root element
* @param schemaContext Entire schema context for correct leafref resolution
- * @param schema Data Node Container Schema
+ * @param schemaNode Data Node Container Schema
* @param codecProvider XML Codec Provider
* @return serialized w3c DOM document
* @throws UnsupportedDataTypeException
* @param data Data DOM root element
* @param codecProvider XML Codec Provider
* @return new instance of XML Document
- * @throws UnsupportedDataTypeException
*/
public static Document toDocument(final CompositeNode data, final XmlCodecProvider codecProvider) {
final DOMResult result = new DOMResult(getDocument());
* Retrieves real schemas for augmented child node.
*
* Schema of the same child node from augment, and directly from target is not the same.
- * Schema of child node from augment is incomplete, therefore its useless for xml <-> normalizedNode translation.
+ * Schema of child node from augment is incomplete, therefore its useless for XML/NormalizedNode translation.
*
*/
public static Set<DataSchemaNode> getRealSchemasForAugment(final AugmentationTarget targetSchema, final AugmentationSchema augmentSchema) {
}
/**
- *
* Serialize the inner value of a AnyXmlNode into element of type E.
*
* @param node to be serialized
- * @param schema schema for leaf
* @return serialized inner value as an Element
*/
protected abstract E serializeAnyXml(AnyXmlNode node);
+/*
+ * 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.schema.tree;
+/*
+ * 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.schema.tree;
-
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
}
}
+ private DataTreeCandidateNode childNode(final ModifiedNode input) {
+ final PathArgument id = input.getIdentifier();
+ return new ChildNode(input, childMeta(oldMeta, id), childMeta(newMeta, id));
+ }
+
@Override
public Iterable<DataTreeCandidateNode> getChildNodes() {
return Iterables.transform(mod.getChildren(), new Function<ModifiedNode, DataTreeCandidateNode>() {
@Override
public DataTreeCandidateNode apply(final ModifiedNode input) {
- final PathArgument id = input.getIdentifier();
- return new ChildNode(input, childMeta(oldMeta, id), childMeta(newMeta, id));
+ return childNode(input);
}
});
}
public Optional<NormalizedNode<?, ?>> getDataBefore() {
return optionalData(oldMeta);
}
+
+ @Override
+ public DataTreeCandidateNode getModifiedChild(final PathArgument identifier) {
+ final Optional<ModifiedNode> childMod = mod.getChild(identifier);
+ if(childMod.isPresent()) {
+ return childNode(mod);
+ }
+ return null;
+ }
}
private static final class ChildNode extends AbstractNode {
+/*
+ * 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.schema.tree;
-
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeFactory;
+/*
+ * 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.schema.tree;
-
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.NotThreadSafe;
-import org.opendaylight.yangtools.concepts.Identifiable;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
currentMetadata = Optional.absent();
}
- ModifiedNode newlyCreated = new ModifiedNode(child, currentMetadata, isOrdered);
+ final ModifiedNode newlyCreated = new ModifiedNode(child, currentMetadata, isOrdered);
children.put(child, newlyCreated);
return newlyCreated;
}
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import java.util.Collections;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
-import java.util.Collections;
-
/**
* Internal utility class for an empty candidate. We instantiate this class
* for empty modifications, saving memory and processing speed. Instances
public Optional<NormalizedNode<?, ?>> getDataBefore() {
return Optional.absent();
}
+
+ @Override
+ public DataTreeCandidateNode getModifiedChild(final PathArgument identifier) {
+ return null;
+ }
};
protected NoopDataTreeCandidate(final YangInstanceIdentifier rootPath, final ModifiedNode modificationRoot) {
* <ol>
* <li>List yang files from {@link #yangFilesRootDir}</li>
* <li>Process yang files using {@link YangParserImpl}</li>
- * <li>For each {@link CodeGenerator} from {@link #codeGenerators}:</li>
+ * <li>For each {@link CodeGenerator} from {@link #codeGenerators}:
* <ol>
* <li>Instantiate using default constructor</li>
* <li>Call {@link CodeGenerator#generateSources(SchemaContext, File, Set)}</li>
- * </ol>
+ * </ol></li>
* </ol>
*/
@Mojo(name = "generate-sources", defaultPhase = LifecyclePhase.GENERATE_SOURCES, requiresDependencyResolution = ResolutionScope.COMPILE, requiresProject = true)
/**
* This interface contains the methods for getting the data from the YANG
- * module.<br />
- * <br />
- * <i>Example of YANG module</i> <code><br/>
- * {@link #getName() <b><font color="#FF0000">module</font></b>} module_name{<br />
- {@link #getYangVersion() <b><font color="#8b4513">yang-version</font></b>} "1";<br /><br />
+ * module.<br>
+ * <br>
+ * <i>Example of YANG module</i> <code><br>
+ * {@link #getName() <b><font color="#FF0000">module</font></b>} module_name{<br>
+ {@link #getYangVersion() <b><font color="#8b4513">yang-version</font></b>} "1";<br><br>
- {@link #getNamespace() <b><font color="#00FF00">namespace</font></b>} "urn:module:namespace";<br />
- {@link #getPrefix() <b><font color="#0000FF">prefix</font></b><a name="prefix"></a>} "prefix";<br /><br />
+ {@link #getNamespace() <b><font color="#00FF00">namespace</font></b>} "urn:module:namespace";<br>
+ {@link #getPrefix() <b><font color="#0000FF">prefix</font></b><a name="prefix"></a>} "prefix";<br><br>
- {@link #getDescription() <b><font color="#b8860b">description</font></b>} "description test";<br />
- {@link #getReference() <b><font color="#008b8b">reference</font></b>} "reference test";<br /><br />
+ {@link #getDescription() <b><font color="#b8860b">description</font></b>} "description test";<br>
+ {@link #getReference() <b><font color="#008b8b">reference</font></b>} "reference test";<br><br>
- {@link #getOrganization() <b><font color="#606060">organization</font></b>} "John Doe, john.doe@email.com";<br />
- {@link #getContact() <b><font color="#FF9900">contact</font></b>} "http://www.opendaylight.org/";<br /><br />
+ {@link #getOrganization() <b><font color="#606060">organization</font></b>} "John Doe, john.doe@email.com";<br>
+ {@link #getContact() <b><font color="#FF9900">contact</font></b>} "http://www.opendaylight.org/";<br><br>
- {@link #getFeatures() <b><font color="#8b0000">feature</font></b>} feature-test{<br />
- description "description of some feature";<br />
- }</br>
+ {@link #getFeatures() <b><font color="#8b0000">feature</font></b>} feature-test{<br>
+ description "description of some feature";<br>
+ }<br>
- {@link #getNotifications() <b><font color="#b22222">notification</font></b>} notification-test;<br />
- {@link #getRpcs() <b><font color="#d2691e">rpc</font></b>} rpc-test;<br />
- <!-- {@link #getDeviations() <b><font color="#b8860b">deviation</font></b>} deviation-test;<br /> -->
- {@link #getIdentities() <b><font color="#bdb76b">identity</font></b>} identity-test;<br />
- {@link #getExtensionSchemaNodes() <b><font color="#808000">extension</font></b>} extension-test;<br />
+ {@link #getNotifications() <b><font color="#b22222">notification</font></b>} notification-test;<br>
+ {@link #getRpcs() <b><font color="#d2691e">rpc</font></b>} rpc-test;<br>
+ <!-- {@link #getDeviations() <b><font color="#b8860b">deviation</font></b>} deviation-test;<br> -->
+ {@link #getIdentities() <b><font color="#bdb76b">identity</font></b>} identity-test;<br>
+ {@link #getExtensionSchemaNodes() <b><font color="#808000">extension</font></b>} extension-test;<br>
- {@link #getRevision() <b><font color="#339900">revision</font></b>} 2011-08-27 {<br />
+ {@link #getRevision() <b><font color="#339900">revision</font></b>} 2011-08-27 {<br>
- {@link #getImports() <b><font color="#9400d3">import</font></b>} other_module {<br />
- prefix "other_module_prefix"<br />
- revision-date 2011-08-27<br />
- }<br /><br />
+ {@link #getImports() <b><font color="#9400d3">import</font></b>} other_module {<br>
+ prefix "other_module_prefix"<br>
+ revision-date 2011-08-27<br>
+ }<br><br>
- container cont {<br />
- }<br />
+ container cont {<br>
+ }<br>
- {@link #getAugmentations() <b><font color="#dc143c">augment</font></b>} "/cont" { ;<br />
- }<br />
+ {@link #getAugmentations() <b><font color="#dc143c">augment</font></b>} "/cont" { ;<br>
+ }<br>
}
</code>
/**
*
* Contains methods for accessing constraint declaration for valid data in form
- * of XPath expressions.<br />
- * <br />
- * <i>YANG example:<br />
+ * of XPath expressions.<br>
+ * <br>
+ * <i>YANG example:<br>
* <code>must "ifType != 'ethernet' or (ifType = 'ethernet' and ifMTU = 1500)";</code>
* </i>
*/
/**
* Create a new instance.
*
- * @param path path from root
- * @param hash intended hash code
+ * @param parent Parent SchemaPath
+ * @param qname next path element
* @return A new SchemaPath instance
*/
protected abstract SchemaPath createInstance(SchemaPath parent, QName qname);
* implementation perspective certain operations on a schema source may require it
* to be first transformed into a particular representation before they can be
* applied. Such transformations are affected via instances of
- * {@link SchemaSourceTransformation}.
+ * SchemaSourceTransformation.
*
* Typical examples of a schema source representation include:
* <ul>
* <li>a {@link com.google.common.io.ByteSource} - source for input streams
* containing source code
* <li>Parsed abstract syntax tree (AST), which is the result of a syntactic parser
+ * </ul>
*
* Implementations of this interface expected to comply with the {@link Immutable}
* contract.
* </ul>
*
* Source identifier is designated to be carry only necessary information
- * to look-up YANG model source and to be used by {@link AdvancedSchemaSourceProvider}
- * and similar.
+ * to look-up YANG model source and to be used by various SchemaSourceProviders.
*
* <b>Note:</b>On source retrieval layer it is impossible to distinguish
* between YANG module and/or submodule unless source is present.
* Where revision is date in format YYYY-mm-dd.
* <p>
*
- * @see http://tools.ietf.org/html/rfc6020#section-5.2
+ * @see <a href="http://tools.ietf.org/html/rfc6020#section-5.2">RFC6020</a>
*
* @return Filename for this source identifier.
*/
* a representation of that particular revision or throw {@link MissingSchemaSourceException}.
* <li> If the source identifier does not specify a revision, this method returns
* the newest available revision, or throws {@link MissingSchemaSourceException}.
+ * </ul>
*
* In either case the returned representation is required to report a non-null
* revision in the {@link SourceIdentifier} returned from
*/
package org.opendaylight.yangtools.yang.model.util;
+import com.google.common.annotations.Beta;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
Preconditions.checkArgument(module != null, "Module reference cannot be NULL");
Preconditions.checkArgument(nonCondXPath != null, "Non Conditional Revision Aware XPath cannot be NULL");
- String strXPath = nonCondXPath.toString();
+ final String strXPath = nonCondXPath.toString();
if (strXPath != null) {
Preconditions.checkArgument(strXPath.indexOf('[') == -1, "Revision Aware XPath may not contain a condition");
if (nonCondXPath.isAbsolute()) {
- List<QName> qnamedPath = xpathToQNamePath(context, module, strXPath);
+ final List<QName> qnamedPath = xpathToQNamePath(context, module, strXPath);
if (qnamedPath != null) {
return findNodeInSchemaContext(context, qnamedPath);
}
"Revision Aware XPath MUST be relative i.e. MUST contains ../, "
+ "for non relative Revision Aware XPath use findDataSchemaNode method");
- SchemaPath actualNodePath = actualSchemaNode.getPath();
+ final SchemaPath actualNodePath = actualSchemaNode.getPath();
if (actualNodePath != null) {
- Iterable<QName> qnamePath = resolveRelativeXPath(context, module, relativeXPath, actualSchemaNode);
+ final Iterable<QName> qnamePath = resolveRelativeXPath(context, module, relativeXPath, actualSchemaNode);
if (qnamePath != null) {
return findNodeInSchemaContext(context, qnamePath);
return findNodeInModule(module, path);
}
- private static SchemaNode findNodeInModule(Module module, Iterable<QName> path) {
+ /**
+ * Returns NotificationDefinition from Schema Context
+ *
+ * @param schema SchemaContext in which lookup should be performed.
+ * @param path Schema Path of notification
+ * @return Notification schema or null, if notification is not present in schema context.
+ */
+ @Beta
+ public static @Nullable NotificationDefinition getNotificationSchema(@Nonnull final SchemaContext schema,@Nonnull final SchemaPath path) {
+ Preconditions.checkNotNull(schema, "Schema context must not be null.");
+ Preconditions.checkNotNull(path, "Schema path must not be null.");
+ for (final NotificationDefinition potential : schema.getNotifications()) {
+ if (path.equals(potential.getPath())) {
+ return potential;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns RPC Input or Output Data container from RPC definition.
+ *
+ * @param schema SchemaContext in which lookup should be performed.
+ * @param path Schema path of RPC input/output data container
+ * @return Notification schema or null, if notification is not present in schema context.
+ */
+ @Beta
+ public static @Nullable ContainerSchemaNode getRpcDataSchema(@Nonnull final SchemaContext schema,@Nonnull final SchemaPath path) {
+ Preconditions.checkNotNull(schema, "Schema context must not be null.");
+ Preconditions.checkNotNull(path, "Schema path must not be null.");
+ final Iterator<QName> it = path.getPathFromRoot().iterator();
+ Preconditions.checkArgument(it.hasNext(), "Rpc must have QName.");
+ final QName rpcName = it.next();
+ Preconditions.checkArgument(it.hasNext(), "input or output must be part of path.");
+ final QName inOrOut = it.next();
+ for (final RpcDefinition potential : schema.getOperations()) {
+ if (rpcName.equals(potential.getQName())) {
+ return SchemaNodeUtils.getRpcDataSchema(potential, inOrOut);
+ }
+ }
+ return null;
+ }
+
+ private static SchemaNode findNodeInModule(final Module module, final Iterable<QName> path) {
Preconditions.checkArgument(module != null, "Parent reference cannot be NULL");
Preconditions.checkArgument(path != null, "Path reference cannot be NULL");
return null;
}
- QName current = path.iterator().next();
+ final QName current = path.iterator().next();
LOG.trace("Looking for node {} in module {}", current, module);
SchemaNode foundNode = null;
- Iterable<QName> nextPath = nextLevel(path);
+ final Iterable<QName> nextPath = nextLevel(path);
foundNode = module.getDataChildByName(current);
if (foundNode != null && nextPath.iterator().hasNext()) {
}
- private static SchemaNode findNodeIn(SchemaNode parent, Iterable<QName> path) {
+ private static SchemaNode findNodeIn(final SchemaNode parent, final Iterable<QName> path) {
Preconditions.checkArgument(parent != null, "Parent reference cannot be NULL");
Preconditions.checkArgument(path != null, "Path reference cannot be NULL");
return null;
}
- QName current = path.iterator().next();
+ final QName current = path.iterator().next();
LOG.trace("Looking for node {} in node {}", current, parent);
SchemaNode foundNode = null;
- Iterable<QName> nextPath = nextLevel(path);
+ final Iterable<QName> nextPath = nextLevel(path);
if (parent instanceof DataNodeContainer) {
- DataNodeContainer parentDataNodeContainer = (DataNodeContainer) parent;
+ final DataNodeContainer parentDataNodeContainer = (DataNodeContainer) parent;
foundNode = parentDataNodeContainer.getDataChildByName(current);
if (foundNode != null && nextPath.iterator().hasNext()) {
}
if (foundNode == null && parent instanceof RpcDefinition) {
- RpcDefinition parentRpcDefinition = (RpcDefinition) parent;
+ final RpcDefinition parentRpcDefinition = (RpcDefinition) parent;
if (current.getLocalName().equals("input")) {
foundNode = parentRpcDefinition.getInput();
}
private static RpcDefinition getRpcByName(final Module module, final QName name) {
- for (RpcDefinition rpc : module.getRpcs()) {
+ for (final RpcDefinition rpc : module.getRpcs()) {
if (rpc.getQName().equals(name)) {
return rpc;
}
}
private static NotificationDefinition getNotificationByName(final Module module, final QName name) {
- for (NotificationDefinition notification : module.getNotifications()) {
+ for (final NotificationDefinition notification : module.getNotifications()) {
if (notification.getQName().equals(name)) {
return notification;
}
}
private static GroupingDefinition getGroupingByName(final DataNodeContainer dataNodeContainer, final QName name) {
- for (GroupingDefinition grouping : dataNodeContainer.getGroupings()) {
+ for (final GroupingDefinition grouping : dataNodeContainer.getGroupings()) {
if (grouping.getQName().equals(name)) {
return grouping;
}
}
private static GroupingDefinition getGroupingByName(final RpcDefinition rpc, final QName name) {
- for (GroupingDefinition grouping : rpc.getGroupings()) {
+ for (final GroupingDefinition grouping : rpc.getGroupings()) {
if (grouping.getQName().equals(name)) {
return grouping;
}
Preconditions.checkArgument(parentModule != null, "Parent Module reference cannot be NULL");
Preconditions.checkArgument(xpath != null, "XPath string reference cannot be NULL");
- List<QName> path = new LinkedList<QName>();
- for (String pathComponent : SLASH_SPLITTER.split(xpath)) {
+ final List<QName> path = new LinkedList<QName>();
+ for (final String pathComponent : SLASH_SPLITTER.split(xpath)) {
if (!pathComponent.isEmpty()) {
path.add(stringPathPartToQName(context, parentModule, pathComponent));
}
final Iterator<String> prefixedName = COLON_SPLITTER.split(prefixedPathPart).iterator();
final String modulePrefix = prefixedName.next();
- Module module = resolveModuleForPrefix(context, parentModule, modulePrefix);
+ final Module module = resolveModuleForPrefix(context, parentModule, modulePrefix);
Preconditions.checkArgument(module != null, "Failed to resolve xpath: no module found for prefix %s in module %s",
modulePrefix, parentModule.getName());
return module;
}
- Set<ModuleImport> imports = module.getImports();
- for (ModuleImport mi : imports) {
+ final Set<ModuleImport> imports = module.getImports();
+ for (final ModuleImport mi : imports) {
if (prefix.equals(mi.getPrefix())) {
return context.findModuleByName(mi.getModuleName(), mi.getRevision());
}
// FIXME: is .contains() the right check here?
// FIXME: case ../../node1/node2/../node3/../node4
int colCount = 0;
- for (Iterator<String> it = xpaths.iterator(); it.hasNext() && it.next().contains(".."); ) {
+ for (final Iterator<String> it = xpaths.iterator(); it.hasNext() && it.next().contains(".."); ) {
++colCount;
}
*/
package org.opendaylight.yangtools.yang.model.util;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
import org.opendaylight.yangtools.yang.model.api.SchemaNode;
-import com.google.common.base.Optional;
-
public class SchemaNodeUtils {
private SchemaNodeUtils() {
}
return previous.orNull();
}
+
+ /**
+ * Returns RPC input or output schema based on supplied QName
+ *
+ * @param rpc RPC Definition
+ * @param qname input or output QName with namespace same as RPC
+ * @return input or output schema. Returns null if RPC does not have input/output specified.
+ */
+ public static @Nullable ContainerSchemaNode getRpcDataSchema(final @Nonnull RpcDefinition rpc, @Nonnull final QName qname) {
+ Preconditions.checkNotNull(rpc, "Rpc Schema must not be null");
+ Preconditions.checkNotNull(qname,"QName must not be null");
+ switch (qname.getLocalName()) {
+ case "input":
+ return rpc.getInput();
+ case "output":
+ return rpc.getOutput();
+ default:
+ throw new IllegalArgumentException("Supplied qname " + qname + " does not represent rpc input or output.");
+ }
+ }
}
*/
package org.opendaylight.yangtools.yang.model.util.repo;
-import org.opendaylight.yangtools.concepts.Delegator;
-
import com.google.common.annotations.Beta;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.concepts.Delegator;
/**
*
* @param <I> Input Schema Source Representation
* @param <O> Output Schema Source Representation
+ *
+ * @deprecated Replaced with {@link org.opendaylight.yangtools.yang.model.repo.util.AbstractSchemaSourceCache}
*/
+@Deprecated
public abstract class AbstractCachingSchemaSourceProvider<I, O> implements AdvancedSchemaSourceProvider<O>,
Delegator<AdvancedSchemaSourceProvider<I>> {
* containing source code
* <li>Parsed AST - abstract syntax tree, which is result of a parser, but still
* it is not linked against other schemas.
+ * </ul>
*
* <p>
* Conversion between representations should be done via implementations of
*
* @param <T>
* Schema source representation type provided by this implementation
+ *
+ * @deprecated Replaced with {@link org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider}
+ * and related APIs.
*/
+@Deprecated
public interface AdvancedSchemaSourceProvider<T> extends SchemaSourceProvider<T> {
/**
*/
package org.opendaylight.yangtools.yang.model.util.repo;
+import com.google.common.base.Charsets;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Charsets;
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-
/**
* Filesystem-based schema caching source provider
*
* @param <I>
* Input format in which schema source is represented.
*
+ * @deprecated Replaced with {@link org.opendaylight.yangtools.yang.model.repo.util.FilesystemSchemaSourceCache}
+ *
*/
+@Deprecated
public final class FilesystemSchemaCachingProvider<I> extends AbstractCachingSchemaSourceProvider<I, InputStream> {
private static final Logger LOG = LoggerFactory.getLogger(FilesystemSchemaCachingProvider.class);
public static final Pattern REVISION_PATTERN = Pattern.compile("\\d\\d\\d\\d-\\d\\d-\\d\\d");
* for other components.
*
* @param <F> Format in which YANG source is represented.
+ * @deprecated Repalced With {@link AdvancedSchemaSourceProvider}
*/
+@Deprecated
public interface SchemaSourceProvider<F> {
/**
*/
package org.opendaylight.yangtools.yang.model.util.repo;
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-
-import org.opendaylight.yangtools.concepts.Delegator;
-
import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import org.opendaylight.yangtools.concepts.Delegator;
/**
*
* Utility functions for {@link SchemaSourceProvider}
*
+ *
+ * @deprecated Utility classes for deprecated APIs.
*/
+@Deprecated
public final class SchemaSourceProviders {
@SuppressWarnings("rawtypes")
*
* @param <I> Input schema source representation
* @param <O> Output schema source representation
+ *
+ * @deprecated Replaced with {@link org.opendaylight.yangtools.yang.model.repo.util.SchemaSourceTransformer}
*/
@Beta
+@Deprecated
public interface SchemaSourceTransformation<I, O> {
/**
*/
package org.opendaylight.yangtools.yang.model.util.repo;
-import org.opendaylight.yangtools.concepts.Immutable;
-
import com.google.common.base.Optional;
+import org.opendaylight.yangtools.concepts.Immutable;
/**
*
* http://tools.ietf.org/html/rfc6022#section-3.1 ).
*
*
+ * @deprecated Replaced with {@link org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier}
*/
+@Deprecated
public final class SourceIdentifier implements Immutable {
private final String name;
package org.opendaylight.yangtools.yang.model.util.repo;
-import org.opendaylight.yangtools.concepts.Delegator;
-
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.concepts.Delegator;
/**
*
* Representation of schema sources used by delegate
* @param <O>
* Representation of schema sources exposed by this provider
+ *
+ * @deprecated Replaced with {@link org.opendaylight.yangtools.yang.model.repo.util.SchemaSourceTransformer}
*/
+@Deprecated
public final class TransformingSourceProvider<I, O> implements //
AdvancedSchemaSourceProvider<O>, Delegator<AdvancedSchemaSourceProvider<I>> {
* @param yangModelStreams
* yang streams to parse
* @return Map of Yang Modules
- * @deprecated Use {@link YangContextParser#parseSources(java.util.Collection<com.google.common.io.ByteSource>)}
+ * @deprecated Use {@link YangContextParser#parseSources(java.util.Collection)}
*/
//TODO: when working with input streams do not swallow IOException, it should be propagated without having to wrap it in a runtime exception
//FIXME: it is not defined in which state are the returning streams.
string : STRING (PLUS STRING)*;
+// string validated in YangParserListenerImpl.handleUnknownNode()
identifier_stmt : IDENTIFIER string? (stmtend | (LEFT_BRACE unknown_statement* RIGHT_BRACE));
-unknown_statement : (YIN_ELEMENT_KEYWORD | YANG_VERSION_KEYWORD | WHEN_KEYWORD | VALUE_KEYWORD | USES_KEYWORD | UNITS_KEYWORD | UNIQUE_KEYWORD |
+// string validated in YangParserListenerImpl.handleUnknownNode()
+unknown_statement : (YIN_ELEMENT_KEYWORD | YANG_VERSION_KEYWORD | WHEN_KEYWORD | VALUE_KEYWORD | USES_KEYWORD | UNITS_KEYWORD | UNIQUE_KEYWORD |
TYPEDEF_KEYWORD | TYPE_KEYWORD | SUBMODULE_KEYWORD | RPC_KEYWORD | REVISION_DATE_KEYWORD | REVISION_KEYWORD |
REQUIRE_INSTANCE_KEYWORD | REFINE_KEYWORD | RANGE_KEYWORD | PRESENCE_KEYWORD | PREFIX_KEYWORD |
POSITION_KEYWORD | PATTERN_KEYWORD | PATH_KEYWORD | OUTPUT_KEYWORD | ORGANIZATION_KEYWORD| ORDERED_BY_KEYWORD | NOTIFICATION_KEYWORD|
placed outside of body_stmt.
*/
stmtsep : IDENTIFIER string? (stmtend | (LEFT_BRACE unknown_statement* RIGHT_BRACE));
-deviate_replace_stmt : DEVIATE_KEYWORD string /* REPLACE_KEYWORD */ (SEMICOLON | (LEFT_BRACE (identifier_stmt |type_stmt | units_stmt | default_stmt | config_stmt | mandatory_stmt | min_elements_stmt | max_elements_stmt )* RIGHT_BRACE));
-deviate_delete_stmt : DEVIATE_KEYWORD string /* DELETE_KEYWORD */ (SEMICOLON | (LEFT_BRACE (identifier_stmt |units_stmt | must_stmt | unique_stmt | default_stmt )* RIGHT_BRACE));
-deviate_add_stmt : DEVIATE_KEYWORD string /*ADD_KEYWORD*/ (SEMICOLON | (LEFT_BRACE (identifier_stmt |units_stmt | must_stmt | unique_stmt | default_stmt | config_stmt | mandatory_stmt | min_elements_stmt | max_elements_stmt )* RIGHT_BRACE));
-deviate_not_supported_stmt : DEVIATE_KEYWORD string /*NOT_SUPPORTED_KEYWORD*/ (SEMICOLON | (LEFT_BRACE identifier_stmt? RIGHT_BRACE));
+// string validated in DeviationBuilder.setDeviate() as REPLACE_KEYWORD
+deviate_replace_stmt : DEVIATE_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |type_stmt | units_stmt | default_stmt | config_stmt | mandatory_stmt | min_elements_stmt | max_elements_stmt )* RIGHT_BRACE));
+// string validated in DeviationBuilder.setDeviate() as DELETE_KEYWORD
+deviate_delete_stmt : DEVIATE_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |units_stmt | must_stmt | unique_stmt | default_stmt )* RIGHT_BRACE));
+// string validated in DeviationBuilder.setDeviate() as ADD_KEYWORD
+deviate_add_stmt : DEVIATE_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |units_stmt | must_stmt | unique_stmt | default_stmt | config_stmt | mandatory_stmt | min_elements_stmt | max_elements_stmt )* RIGHT_BRACE));
+// string validated in DeviationBuilder.setDeviate() as NOT_SUPPORTED_KEYWORD
+deviate_not_supported_stmt : DEVIATE_KEYWORD string (SEMICOLON | (LEFT_BRACE identifier_stmt? RIGHT_BRACE));
+// string validated in YangModelBasicValidationListener.enterDeviation_stmt()
deviation_stmt : DEVIATION_KEYWORD string LEFT_BRACE (identifier_stmt |description_stmt | reference_stmt | deviate_not_supported_stmt | deviate_add_stmt | deviate_replace_stmt | deviate_delete_stmt)+ RIGHT_BRACE;
+// string validated in YangModelBasicValidationListener.enterNotification_stmt()
notification_stmt : NOTIFICATION_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |if_feature_stmt | status_stmt | description_stmt | reference_stmt | typedef_stmt | grouping_stmt | data_def_stmt )* RIGHT_BRACE));
output_stmt : OUTPUT_KEYWORD LEFT_BRACE (identifier_stmt |typedef_stmt | grouping_stmt | data_def_stmt )* RIGHT_BRACE;
input_stmt : INPUT_KEYWORD LEFT_BRACE (identifier_stmt |typedef_stmt | grouping_stmt | data_def_stmt )* RIGHT_BRACE;
+// string valided in YangModelBasicValidationListener.enterRpc_stmt()
rpc_stmt : RPC_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |if_feature_stmt | status_stmt | description_stmt | reference_stmt | typedef_stmt | grouping_stmt | input_stmt | output_stmt )* RIGHT_BRACE));
+// string validated in ParserListenerUtils.stringFromStringContext()
when_stmt : WHEN_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |description_stmt | reference_stmt )* RIGHT_BRACE));
+// string validated in YangModelBasicValidationListener.enterAugment_stmt()
augment_stmt : AUGMENT_KEYWORD string LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | status_stmt | description_stmt | reference_stmt | data_def_stmt | case_stmt)* RIGHT_BRACE;
-uses_augment_stmt : AUGMENT_KEYWORD string LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | status_stmt | description_stmt | reference_stmt | data_def_stmt | case_stmt)* RIGHT_BRACE;
+// string not validated
+uses_augment_stmt : AUGMENT_KEYWORD string LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | status_stmt | description_stmt | reference_stmt | data_def_stmt | case_stmt)* RIGHT_BRACE;
refine_anyxml_stmts : (identifier_stmt |must_stmt | config_stmt | mandatory_stmt | description_stmt | reference_stmt )*;
refine_case_stmts : (identifier_stmt |description_stmt | reference_stmt )*;
refine_choice_stmts : (identifier_stmt |default_stmt | config_stmt | mandatory_stmt | description_stmt | reference_stmt )*;
refine_leaf_stmts : (identifier_stmt |must_stmt | default_stmt | config_stmt | mandatory_stmt | description_stmt | reference_stmt )*;
refine_container_stmts : (identifier_stmt |must_stmt | presence_stmt | config_stmt | description_stmt | reference_stmt )*;
refine_pom : (refine_container_stmts | refine_leaf_stmts | refine_leaf_list_stmts | refine_list_stmts | refine_choice_stmts | refine_case_stmts | refine_anyxml_stmts);
+// string validated in YangModelBasicValidationListener.enterRefine_stmt()
refine_stmt : REFINE_KEYWORD string (SEMICOLON | (LEFT_BRACE (refine_pom) RIGHT_BRACE));
+// string validated in YangModelBasicValidationListener.enterUses_stmt()
uses_stmt : USES_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | status_stmt | description_stmt | reference_stmt | refine_stmt | uses_augment_stmt )* RIGHT_BRACE));
+// string validated in YangModelBasicValidationListener.enterAnyxml_stmt()
anyxml_stmt : ANYXML_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | must_stmt | config_stmt | mandatory_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
+// string validated in YangModelBasicValidationListener.enterCase_stmt()
case_stmt : CASE_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | status_stmt | description_stmt | reference_stmt | data_def_stmt )* RIGHT_BRACE));
short_case_stmt : container_stmt | leaf_stmt | leaf_list_stmt | list_stmt | anyxml_stmt;
+// string validated in YangModelBasicValidationListener.enterChoice_stmt()
choice_stmt : CHOICE_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | default_stmt | config_stmt | mandatory_stmt | status_stmt | description_stmt | reference_stmt | short_case_stmt | case_stmt)* RIGHT_BRACE));
+// string validated in YangModelBasicValidationListener.enterUnique_stmt()
unique_stmt : UNIQUE_KEYWORD string stmtend;
+// string validated in YangModelBasicValidationListener.enterKey_stmt()
key_stmt : KEY_KEYWORD string stmtend;
+// string validated in YangModelBasicValidationListener.enterList_stmt()
list_stmt : LIST_KEYWORD string LEFT_BRACE (when_stmt | if_feature_stmt | must_stmt | key_stmt | unique_stmt | config_stmt | min_elements_stmt | max_elements_stmt | ordered_by_stmt | status_stmt | description_stmt | reference_stmt | typedef_stmt | grouping_stmt | data_def_stmt | identifier_stmt)* RIGHT_BRACE;
+// string validated in YangModelBasicValidationListener.enterLeaf_list_stmt()
leaf_list_stmt : LEAF_LIST_KEYWORD string LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | type_stmt | units_stmt | must_stmt | config_stmt | min_elements_stmt | max_elements_stmt | ordered_by_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE;
+// string validated in YangModelBasicValidationListener.enterLeaf_stmt()
leaf_stmt : LEAF_KEYWORD string LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | type_stmt | units_stmt | must_stmt | default_stmt | config_stmt | mandatory_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE;
+// string validated in YangModelBasicValidationListener.enterContainer_stmt()
container_stmt : CONTAINER_KEYWORD string (SEMICOLON | (LEFT_BRACE (when_stmt | if_feature_stmt | must_stmt | presence_stmt | config_stmt | status_stmt | description_stmt | reference_stmt | typedef_stmt | grouping_stmt | data_def_stmt | identifier_stmt)* RIGHT_BRACE));
+// string validated in YangModelBasicValidationListener.enterGrouping_stmt()
grouping_stmt : GROUPING_KEYWORD string (SEMICOLON | (LEFT_BRACE (status_stmt | description_stmt | reference_stmt | typedef_stmt | grouping_stmt | data_def_stmt | identifier_stmt)* RIGHT_BRACE));
+// string validated in ParserListenerUtils.createEnumPair()
value_stmt : VALUE_KEYWORD string stmtend;
-max_value_arg : /*UNBOUNDED_KEYWORD |*/ string;
-min_value_arg : /*UNBOUNDED_KEYWORD |*/ string;
+// string validated in ParserListenerUtils.parseMaxElements()
+max_value_arg : string;
+// string validated in ParserListenerUtils.parseMinElements()
+min_value_arg : string;
max_elements_stmt : MAX_ELEMENTS_KEYWORD max_value_arg stmtend;
min_elements_stmt : MIN_ELEMENTS_KEYWORD min_value_arg stmtend;
+// string validated in ParserListenerUtils.parseMust()
error_app_tag_stmt : ERROR_APP_TAG_KEYWORD string stmtend;
+// string validated in ParserListenerUtils.parseMust()
error_message_stmt : ERROR_MESSAGE_KEYWORD string stmtend;
+// string validated in ParserListenerUtils.parseMust()
must_stmt : MUST_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |error_message_stmt | error_app_tag_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
-ordered_by_arg : string; /*USER_KEYWORD | SYSTEM_KEYWORD;*/
+// string validated in YangModelBasicValidationListener.enterOrdered_by_arg() as USER_KEYWORD | SYSTEM_KEYWORD
+ordered_by_arg : string;
ordered_by_stmt : ORDERED_BY_KEYWORD ordered_by_arg stmtend;
+// string not validated
presence_stmt : PRESENCE_KEYWORD string stmtend;
-mandatory_arg :string; // TRUE_KEYWORD | FALSE_KEYWORD;
+// string validated in YangModelBasicValidationListener.enterMandatory_arg() as TRUE_KEYWORD | FALSE_KEYWORD
+mandatory_arg :string;
mandatory_stmt : MANDATORY_KEYWORD mandatory_arg stmtend;
-config_arg : string; // TRUE_KEYWORD | FALSE_KEYWORD;
+// string validated in YangModelBasicValidationListener.enterConfig_arg() as TRUE_KEYWORD | FALSE_KEYWORD
+config_arg : string;
config_stmt : CONFIG_KEYWORD config_arg stmtend;
-status_arg : string; /*CURRENT_KEYWORD | OBSOLETE_KEYWORD | DEPRECATED_KEYWORD; */
+// string validated in YangModelBasicValidationListener.enterStatus_arg() as CURRENT_KEYWORD | OBSOLETE_KEYWORD | DEPRECATED_KEYWORD
+status_arg : string;
status_stmt : STATUS_KEYWORD status_arg stmtend;
+// string validated in ParserListenerUtils.parseBit()
position_stmt : POSITION_KEYWORD string stmtend;
+// string validated in ParserListenerUtils.parseBit()
bit_stmt : BIT_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |position_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
bits_specification : bit_stmt (bit_stmt | identifier_stmt)*;
union_specification : type_stmt (identifier_stmt | type_stmt )*;
identityref_specification : base_stmt ;
instance_identifier_specification : (require_instance_stmt )?;
-require_instance_arg :string; // TRUE_KEYWORD | FALSE_KEYWORD;
+// string validated in ParserListenerUtils.isRequireInstance() as TRUE_KEYWORD | FALSE_KEYWORD
+require_instance_arg :string;
require_instance_stmt : REQUIRE_INSTANCE_KEYWORD require_instance_arg stmtend;
+// string validated in ParserListenerUtils.parseLeafrefPath()
path_stmt : PATH_KEYWORD string stmtend;
leafref_specification : path_stmt;
+// string validated in ParserListenerUtils.createEnumPair()
enum_stmt : ENUM_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |value_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
enum_specification : enum_stmt (identifier_stmt | enum_stmt )*;
+// string not validated
default_stmt : DEFAULT_KEYWORD string stmtend;
+// string validated in ParserListenerUtils.parsePatternConstraint()
pattern_stmt : PATTERN_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |error_message_stmt | error_app_tag_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
+// string validated in ParserListenerUtils.parseLengthConstraints()
length_stmt : LENGTH_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |error_message_stmt | error_app_tag_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
string_restrictions : (length_stmt | pattern_stmt )*;
+// string validated in ParserListenerUtils.parseFractionDigits()
fraction_digits_stmt : FRACTION_DIGITS_KEYWORD string stmtend;
decimal64_specification : (numerical_restrictions? (identifier_stmt)* fraction_digits_stmt | fraction_digits_stmt (identifier_stmt)* numerical_restrictions?);
+// string validated in ParserListenerUtils.parseRangeConstraints()
range_stmt : RANGE_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |error_message_stmt | error_app_tag_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
numerical_restrictions : range_stmt ;
type_body_stmts : (identifier_stmt)* (numerical_restrictions | decimal64_specification | string_restrictions | enum_specification | leafref_specification | identityref_specification | instance_identifier_specification | bits_specification | union_specification) (identifier_stmt)*;
+// string validated in YangModelBasicValidationListener.enterType_stmt()
type_stmt : TYPE_KEYWORD string (SEMICOLON | (LEFT_BRACE type_body_stmts RIGHT_BRACE));
+// string validated in YangModelBasicValidationListener.enterTypedef_stmt()
typedef_stmt : TYPEDEF_KEYWORD string LEFT_BRACE (identifier_stmt | type_stmt | units_stmt | default_stmt | status_stmt | description_stmt | reference_stmt )+ RIGHT_BRACE;
+// string validated in YangModelBasicValidationListener.enterIf_feature_stmt()
if_feature_stmt : IF_FEATURE_KEYWORD string stmtend;
+// string validated in YangModelBasicValidationListener.enterFeature_stmt()
feature_stmt : FEATURE_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt | if_feature_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
+// string validated in YangModelBasicValidationListener.enterBase_stmt()
base_stmt : BASE_KEYWORD string stmtend;
+// string validated in YangModelBasicValidationListener.enterIdentity_stmt()
identity_stmt : IDENTITY_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt | base_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
-yin_element_arg : string; // TRUE_KEYWORD | FALSE_KEYWORD;
+// string validated in YangModelBasicValidationListener.enterYin_element_arg() as TRUE_KEYWORD | FALSE_KEYWORD
+yin_element_arg : string;
yin_element_stmt : YIN_ELEMENT_KEYWORD yin_element_arg stmtend;
+
+// string validated in YangModelBasicValidationListener.enterArgument_stmt()
argument_stmt : ARGUMENT_KEYWORD string (SEMICOLON | (LEFT_BRACE identifier_stmt* yin_element_stmt? identifier_stmt* RIGHT_BRACE));
+// string validated in YangModelBasicValidationListener.enterExtension_stmt()
extension_stmt : EXTENSION_KEYWORD string (SEMICOLON | (LEFT_BRACE (argument_stmt | status_stmt | description_stmt | reference_stmt | unknown_statement)* RIGHT_BRACE));
+// string validated in YangModelBasicValidationListener.enterRevision_date_stmt()
revision_date_stmt : REVISION_DATE_KEYWORD string stmtend;
-revision_stmt : REVISION_KEYWORD string (SEMICOLON | (LEFT_BRACE (description_stmt )? (reference_stmt )? RIGHT_BRACE));
+// string validated in YangModelBasicValidationListener.enterRevision_stmt()
+revision_stmt : REVISION_KEYWORD string (SEMICOLON | (LEFT_BRACE stmtsep* (description_stmt )? (reference_stmt )? RIGHT_BRACE));
+// string not validated
units_stmt : UNITS_KEYWORD string stmtend;
+// string not validated
reference_stmt : REFERENCE_KEYWORD string stmtend;
+// string not validated
description_stmt : DESCRIPTION_KEYWORD string stmtend;
+// string not validated
contact_stmt : CONTACT_KEYWORD string stmtend;
+// string not validated
organization_stmt : ORGANIZATION_KEYWORD string stmtend;
-belongs_to_stmt : BELONGS_TO_KEYWORD string LEFT_BRACE prefix_stmt RIGHT_BRACE;
+// string validated in YangModelBasicValidationListener.enterBelongs_to_stmt()
+belongs_to_stmt : BELONGS_TO_KEYWORD string LEFT_BRACE stmtsep* prefix_stmt RIGHT_BRACE;
+// string validated in YangModelBasicValidationListener.enterPrefix_stmt()
prefix_stmt : PREFIX_KEYWORD string stmtend;
+// string validated in YangModelBasicValidationListener.enterNamespace_stmt()
namespace_stmt : NAMESPACE_KEYWORD string stmtend;
-include_stmt : INCLUDE_KEYWORD string (SEMICOLON | (LEFT_BRACE (revision_date_stmt )? RIGHT_BRACE));
-import_stmt : IMPORT_KEYWORD string LEFT_BRACE prefix_stmt (revision_date_stmt )? RIGHT_BRACE;
+// string validated in YangModelBasicValidationListener.enterInclude_stmt()
+include_stmt : INCLUDE_KEYWORD string (SEMICOLON | (LEFT_BRACE stmtsep* (revision_date_stmt )? RIGHT_BRACE));
+// string validated in YangModelBasicValidationListener.enterImport_stmt()
+import_stmt : IMPORT_KEYWORD string LEFT_BRACE stmtsep* prefix_stmt (revision_date_stmt )? RIGHT_BRACE;
+// string validated in YangModelBasicValidationListener.enterModule_header_stmts() and/or YangModelBasicValidationListener.enterSubmodule_header_stmts()
yang_version_stmt : YANG_VERSION_KEYWORD string stmtend;
data_def_stmt : container_stmt | leaf_stmt | leaf_list_stmt | list_stmt | choice_stmt | anyxml_stmt | uses_stmt;
body_stmts : (( identifier_stmt| extension_stmt | feature_stmt | identity_stmt | typedef_stmt | grouping_stmt | data_def_stmt | augment_stmt | rpc_stmt | notification_stmt | deviation_stmt) )*;
meta_stmts : (organization_stmt stmtsep* | contact_stmt stmtsep* | description_stmt stmtsep* | reference_stmt stmtsep*)*;
submodule_header_stmts : (yang_version_stmt stmtsep* | belongs_to_stmt stmtsep*)+ ;
module_header_stmts : (yang_version_stmt stmtsep* | namespace_stmt stmtsep* | prefix_stmt stmtsep*)+ ;
+// string validated in YangModelBasicValidationListener.enterSubmodule_stmt()
submodule_stmt : SUBMODULE_KEYWORD string LEFT_BRACE stmtsep* submodule_header_stmts linkage_stmts meta_stmts revision_stmts body_stmts RIGHT_BRACE;
-module_stmt : MODULE_KEYWORD string LEFT_BRACE stmtsep* module_header_stmts linkage_stmts meta_stmts revision_stmts body_stmts RIGHT_BRACE;
\ No newline at end of file
+// string validated in YangModelBasicValidationListener.enterModule_stmt()
+module_stmt : MODULE_KEYWORD string LEFT_BRACE stmtsep* module_header_stmts linkage_stmts meta_stmts revision_stmts body_stmts RIGHT_BRACE;
import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
+ key);
}
+ if (!(keyPart instanceof LeafSchemaNode)) {
+ throw new YangParseException(getModuleName(), getLine(), "List key : \"" + key
+ + "\" does not reference any Leaf of the List");
+ }
+
final QName qname = keyPart.getQName();
if (!keyDefinition.contains(qname)) {
keyDefinition.add(qname);
/**
* Sorts set <code>groupingDefinitions</code> according to the mutual
- * dependencies.<br />
+ * dependencies.<br>
*
* Elements of <code>groupingDefinitions</code> are firstly transformed to
* {@link org.opendaylight.yangtools.yang.parser.util.TopologicalSort.Node
* Node} interfaces and then are sorted by
* {@link org.opendaylight.yangtools.yang.parser.util.TopologicalSort#sort(Set)
- * sort()} method of <code>TopologicalSort</code>.<br />
- * <br />
+ * sort()} method of <code>TopologicalSort</code>.<br>
+ * <br>
*
*
- * <i>Definition of dependency relation:<br />
+ * <i>Definition of dependency relation:<br>
* The first <code>GroupingDefinition</code> object (in this context)
* depends on second <code>GroupingDefinition</code> object if the first one
* contains in its set of <code>UsesNode</code> (obtained through
/**
* Constraints:
* <ol>
- * <liNo duplicate uniques</li>
+ * <li>No duplicate uniques</li>
* </ol>
*/
@Override
* @see SubmoduleDependencyInfo
*
*/
+
public abstract class YangModelDependencyInfo {
private final String name;
* been referenced by other YANG sources, but source code for them is missing.
* <li>{@link #getMissingDependencies()} - map of {@link SourceIdentifier} and
* their imports for which source codes was not available.
+ * </ul>
*
* {@link YangSourceContext} may be associated with {@link SchemaSourceProvider}
* (see {@link #getDelegate()}, which was used for retrieval of sources during
*
*/
// FIXME: for some reason this class is Closeable even though close is never called and no resources are leaked
+@Deprecated
@ThreadSafe
public class YangSourceContext implements AdvancedSchemaSourceProvider<InputStream>, Closeable,
Delegator<AdvancedSchemaSourceProvider<InputStream>> {
/**
* Construct YANG Source Context
- *
+ *
* @param validSourcesSet Set of identifiers of valid sources
* @param missingSourcesSet Set of identifiers of missing sources
* @param missingDependenciesMap Map of identifiers of resolved sources and their missing imports.
- * @param sourceProvider Source provider which was used for context resolution or
+ * @param sourceProvider Source provider which was used for context resolution or
* null if provider was not used.
*/
YangSourceContext(final ImmutableSet<SourceIdentifier> validSourcesSet,
* </ul>
*
*/
+@Deprecated
@NotThreadSafe
public abstract class YangSourceContextResolver {
/**
- *
+ *
* State of source code resolution
- *
+ *
*/
public enum ResolutionState {
/**
- *
+ *
* Source was missing during source resolution
- *
+ *
*/
- MISSING_SOURCE,
+ MISSING_SOURCE,
/**
- *
- * One or multiple of dependencies of source are missing
- *
+ *
+ * One or multiple of dependencies of source are missing
+ *
*/
- MISSING_DEPENDENCY,
+ MISSING_DEPENDENCY,
/**
* Other error ocurred during resolution
- *
+ *
*/
- OTHER_ERROR,
+ OTHER_ERROR,
/**
* Source, its dependencies and its transient dependencies
* are resolved.
- *
+ *
*/
EVERYTHING_OK,
}
* <li>All sources which imported or included this source will be present in
* {@link YangSourceContext#getMissingDependencies()}</li>
* </ul>
- *
+ * </li></ul>
*
*
* @param identifier
* and there is {@link SchemaSourceProvider} able to retrieve YANG models.
*
*/
+@Deprecated
public final class YangSourceFromCapabilitiesResolver extends YangSourceContextResolver {
private final Iterable<QName> capabilities;
* {@link YangSourceContext}.
*
*/
+@Deprecated
@NotThreadSafe
public final class YangSourceFromDependencyInfoResolver extends YangSourceContextResolver {
--- /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.parser.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
+import org.opendaylight.yangtools.yang.parser.util.YangParseException;
+
+public class ListKeysTest {
+
+ @Test
+ public void correctListKeysTest() throws IOException, YangSyntaxErrorException, URISyntaxException {
+ File yangFile = new File(getClass().getResource("/list-keys-test/correct-list-keys-test.yang").toURI());
+
+ YangParserImpl parser = YangParserImpl.getInstance();
+ parser.parseFile(yangFile, yangFile.getParentFile());
+ }
+
+ @Test(expected = YangParseException.class)
+ public void incorrectListKeysTest1() throws IOException, YangSyntaxErrorException, URISyntaxException {
+ File yangFile = new File(getClass().getResource("/list-keys-test/incorrect-list-keys-test.yang").toURI());
+
+ YangParserImpl parser = YangParserImpl.getInstance();
+ parser.parseFile(yangFile, yangFile.getParentFile());
+ }
+
+ @Test(expected = YangParseException.class)
+ public void incorrectListKeysTest2() throws IOException, YangSyntaxErrorException, URISyntaxException {
+ File yangFile = new File(getClass().getResource("/list-keys-test/incorrect-list-keys-test2.yang").toURI());
+
+ YangParserImpl parser = YangParserImpl.getInstance();
+ parser.parseFile(yangFile, yangFile.getParentFile());
+ }
+
+ @Test(expected = YangParseException.class)
+ public void incorrectListKeysTest3() throws IOException, YangSyntaxErrorException, URISyntaxException {
+ File yangFile = new File(getClass().getResource("/list-keys-test/incorrect-list-keys-test3.yang").toURI());
+
+ YangParserImpl parser = YangParserImpl.getInstance();
+ parser.parseFile(yangFile, yangFile.getParentFile());
+ }
+
+ @Test(expected = YangParseException.class)
+ public void incorrectListKeysTest4() throws IOException, YangSyntaxErrorException, URISyntaxException {
+ File yangFile = new File(getClass().getResource("/list-keys-test/incorrect-list-keys-test4.yang").toURI());
+
+ YangParserImpl parser = YangParserImpl.getInstance();
+ parser.parseFile(yangFile, yangFile.getParentFile());
+ }
+
+}
fail("YangParseException should not be thrown");
}
}
+
+ @Test
+ public void unknownStatementsInStatementsTest() throws IOException, URISyntaxException {
+ File yangModule1 = new File(getClass().getResource("/yang-grammar-test/stmtsep-in-statements.yang").toURI());
+ File yangModule2 = new File(getClass().getResource("/yang-grammar-test/stmtsep-in-statements2.yang").toURI());
+ File yangSubModule = new File(getClass().getResource("/yang-grammar-test/stmtsep-in-statements-sub.yang").toURI());
+
+ List<File> yangs = new ArrayList<File>();
+ yangs.add(yangModule1);
+ yangs.add(yangModule2);
+ yangs.add(yangSubModule);
+
+ try {
+ YangParserImpl.getInstance().parseFiles(yangs);
+ } catch (YangParseException e) {
+ e.printStackTrace();
+ fail("YangParseException should not be thrown");
+ }
+ }
}
import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
import org.opendaylight.yangtools.yang.parser.impl.util.YangModelDependencyInfo;
+@Deprecated
public class DependencyResolverTest {
@Test
--- /dev/null
+module correct-list-keys-test {
+
+ namespace "correct-list-keys-test";
+ prefix "test";
+
+ list test1 {
+ key "test1_key";
+ leaf test1_key {
+ type string;
+ }
+ }
+
+ list test2 {
+ key "test2_key1 test2_key2 test2_key3";
+ leaf test2_key1 {
+ type string;
+ }
+ leaf test2_key2 {
+ type string;
+ }
+ leaf test2_key3 {
+ type string;
+ }
+ }
+
+ grouping grp_leaf {
+ leaf grp_leaf {
+ type string;
+ }
+ }
+
+ list test3 {
+ key "grp_leaf";
+ uses grp_leaf;
+ }
+
+ list test4 {
+ key "test4_key1 grp_leaf test4_key2";
+ uses grp_leaf;
+ leaf test4_key1 {
+ type string;
+ }
+ leaf test4_key2 {
+ type string;
+ }
+ }
+
+ list test5 {
+ key "aug_leaf";
+ }
+
+ augment /test5 {
+ leaf aug_leaf {
+ type string;
+ }
+ }
+
+ list test6 {
+ key "aug_leaf grp_leaf test6_key1";
+ uses grp_leaf;
+ leaf test6_key1 {
+ type string;
+ }
+ }
+
+ augment /test6 {
+ leaf aug_leaf {
+ type string;
+ }
+ }
+
+ list test7 {
+ key "grp_leaf";
+ }
+
+ augment /test7 {
+ uses grp_leaf;
+ }
+}
--- /dev/null
+module incorrect-list-keys-test {
+
+ namespace "incorrect-list-keys-test";
+ prefix "test";
+
+ list test1 {
+ key "test1_key1 test1_key2";
+ leaf test1_key1 {
+ type string;
+ }
+ list test1_key2 {
+ leaf test1_key2 {
+ type string;
+ }
+ }
+ }
+}
--- /dev/null
+module incorrect-list-keys-test2 {
+
+ namespace "incorrect-list-keys-test2";
+ prefix "test";
+
+ list test1 {
+ key "test1_key1 test1_key2";
+ leaf test1_key1 {
+ type string;
+ }
+ }
+}
--- /dev/null
+module incorrect-list-keys-test3 {
+
+ namespace "incorrect-list-keys-test3";
+ prefix "test";
+
+ grouping grp_leaf {
+ leaf grp_leaf {
+ type string;
+ }
+ list grp_list {
+ leaf grp_leaf {
+ type string;
+ }
+ }
+ }
+
+ list test1 {
+ key "grp_list";
+ uses grp_leaf;
+ }
+}
--- /dev/null
+module incorrect-list-keys-test4 {
+
+ namespace "incorrect-list-keys-test4";
+ prefix "test";
+
+ grouping grp_leaf {
+ list grp_leaf {
+ }
+ }
+
+ list test1 {
+ key "grp_leaf";
+ }
+
+ augment /test1 {
+ uses grp_leaf;
+ }
+}
--- /dev/null
+submodule subtest {
+ aaa {
+ bbb {
+ yang-version 1;
+ }
+ }
+
+ yang-version: 1;
+
+ belongs-to test {
+ aaa {
+ bbb {
+ yang-version 1;
+ }
+ }
+ prefix test;
+ }
+
+ revision 2015-01-14 {
+ ccc {
+ ddd {
+ yang-version 1;
+ }
+ }
+
+ description "Initial revision.";
+ }
+}
\ No newline at end of file
--- /dev/null
+module test {
+ aaa {
+ bbb {
+ yang-version 1;
+ }
+ }
+
+ yang-version: 1;
+ namespace "tst";
+ prefix test;
+
+ include subtest {
+ ccc {
+ ddd {
+ yang-version 1;
+ }
+ }
+ revision-date 2015-01-14;
+ }
+
+ import test2 {
+ eee {
+ fff {
+ yang-version 1;
+ }
+ }
+ prefix test2;
+ revision-date 2015-01-14;
+ }
+
+ revision 2015-01-14 {
+ ggg {
+ hhh {
+ yang-version 1;
+ }
+ }
+
+ description "Initial revision.";
+ }
+}
\ No newline at end of file
--- /dev/null
+module test2 {
+ aaa {
+ bbb {
+ yang-version 1;
+ }
+ }
+
+ yang-version: 1;
+ namespace "tst2";
+ prefix test2;
+
+ revision 2015-01-14 {
+ ccc {
+ ddd {
+ yang-version 1;
+ }
+ }
+
+ description "Initial revision.";
+ }
+}
\ No newline at end of file