*/
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);
}
*/
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) {
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
--- /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);
+
+ }
+
+}
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;
}
uses two-level-list;
}
}
+
+ notification two-level-list-changed {
+ uses two-level-list;
+ }
+
+ rpc get-top {
+ output {
+ uses two-level-list;
+ }
+ }
}