--- /dev/null
+/*
+ * Copyright (c) 2018 ZTE, 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.mdsal.binding.javav2.dom.codec.impl.context.base;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableCollection;
+import java.lang.reflect.Method;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.api.BindingNormalizedNodeCachingCodec;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.api.BindingTreeNodeCodec;
+import org.opendaylight.mdsal.binding.javav2.spec.base.TreeArgument;
+import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
+import org.opendaylight.yangtools.concepts.Codec;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+@Beta
+public final class AnyxmlNodeCodecContext<D extends TreeNode> extends NodeCodecContext<D>
+ implements NodeContextSupplier {
+
+ private final YangInstanceIdentifier.PathArgument yangIdentifier;
+ private final Codec<Object, Object> valueCodec;
+ private final Method getter;
+ private final DataSchemaNode schema;
+
+ AnyxmlNodeCodecContext(final DataSchemaNode schema, final Codec<Object, Object> codec, final Method getter,
+ final SchemaContext schemaContext) {
+ this.yangIdentifier = new YangInstanceIdentifier.NodeIdentifier(schema.getQName());
+ this.valueCodec = Preconditions.checkNotNull(codec);
+ this.getter = Preconditions.checkNotNull(getter);
+ this.schema = Preconditions.checkNotNull(schema);
+ }
+
+ @Override
+ public YangInstanceIdentifier.PathArgument getDomPathArgument() {
+ return yangIdentifier;
+ }
+
+ public Codec<Object, Object> getValueCodec() {
+ return valueCodec;
+ }
+
+ @Nonnull
+ @Override
+ public D deserialize(@Nonnull final NormalizedNode<?, ?> normalizedNode) {
+ throw new UnsupportedOperationException("Anyxml can not be deserialized to TreeNode");
+ }
+
+ @Nonnull
+ @Override
+ public NodeCodecContext<?> get() {
+ return this;
+ }
+
+ public Method getGetter() {
+ return getter;
+ }
+
+ @Nonnull
+ @Override
+ public BindingTreeNodeCodec<?> bindingPathArgumentChild(@Nonnull final TreeArgument<?> arg,
+ final List<YangInstanceIdentifier.PathArgument> builder) {
+ throw new IllegalArgumentException("Anyxml does not have children");
+ }
+
+ @Nonnull
+ @Override
+ public BindingNormalizedNodeCachingCodec<D> createCachingCodec(
+ @Nonnull final ImmutableCollection<Class<? extends TreeNode>> cacheSpecifier) {
+ throw new UnsupportedOperationException("Anyxml does not support caching codec.");
+ }
+
+ @Nonnull
+ @Override
+ public Class<D> getBindingClass() {
+ throw new UnsupportedOperationException("Anyxml does not have DataObject representation");
+ }
+
+ @Nonnull
+ @Override
+ public NormalizedNode<?, ?> serialize(@Nonnull final D data) {
+ throw new UnsupportedOperationException("Separate serialization of Anyxml node is not supported.");
+ }
+
+ @Override
+ public void writeAsNormalizedNode(final D data, final NormalizedNodeStreamWriter writer) {
+ throw new UnsupportedOperationException("Separate serialization of Anyxml node is not supported.");
+ }
+
+ @Nonnull
+ @Override
+ public <E extends TreeNode> BindingTreeNodeCodec<E> streamChild(@Nonnull final Class<E> childClass) {
+ throw new IllegalArgumentException("Anyxml does not have children");
+ }
+
+ @Override
+ public <E extends TreeNode> Optional<? extends BindingTreeNodeCodec<E>> possibleStreamChild(
+ @Nonnull final Class<E> childClass) {
+ throw new IllegalArgumentException("Anyxml does not have children");
+ }
+
+ @Nonnull
+ @Override
+ public BindingTreeNodeCodec<?> yangPathArgumentChild(final YangInstanceIdentifier.PathArgument child) {
+ throw new IllegalArgumentException("Anyxml does not have children");
+ }
+
+ @Override
+ protected Object deserializeObject(final NormalizedNode<?, ?> normalizedNode) {
+ if (normalizedNode instanceof AnyXmlNode) {
+ return valueCodec.deserialize(normalizedNode.getValue());
+ }
+ return null;
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ @Override
+ public TreeArgument deserializePathArgument(final YangInstanceIdentifier.PathArgument arg) {
+ Preconditions.checkArgument(getDomPathArgument().equals(arg));
+ return null;
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public YangInstanceIdentifier.PathArgument serializePathArgument(final TreeArgument arg) {
+ return getDomPathArgument();
+ }
+
+ @Nonnull
+ @Override
+ public DataSchemaNode getSchema() {
+ return schema;
+ }
+}
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
return getLeafNodesUsingReflection(parentClass, getterToLeafSchema);
}
+ @Override
+ public ImmutableMap<String, AnyxmlNodeCodecContext<?>> getAnyxmlNodes(final Class<?> parentClass,
+ final DataNodeContainer childSchema) {
+ final Map<String, DataSchemaNode> getterToAnyxmlSchema = new HashMap<>();
+ for (final DataSchemaNode anyxml : childSchema.getChildNodes()) {
+ if (anyxml instanceof AnyXmlSchemaNode) {
+ getterToAnyxmlSchema.put(getGetterName(anyxml.getQName(), false), anyxml);
+ }
+ }
+ return getAnyxmlNodesUsingReflection(parentClass, getterToAnyxmlSchema);
+ }
+
private static String getGetterName(final QName qname, final TypeDefinition<?> typeDef) {
final String suffix =
JavaIdentifierNormalizer.normalizeSpecificIdentifier(qname.getLocalName(), JavaIdentifier.CLASS);
return "get" + suffix;
}
+ private static String getGetterName(final QName qname, final boolean booleanOrEmpty) {
+ final String suffix =
+ JavaIdentifierNormalizer.normalizeSpecificIdentifier(qname.getLocalName(), JavaIdentifier.CLASS);
+ if (booleanOrEmpty) {
+ return "is" + suffix;
+ }
+ return "get" + suffix;
+ }
+
private ImmutableMap<String, LeafNodeCodecContext<?>> getLeafNodesUsingReflection(final Class<?> parentClass,
final Map<String, DataSchemaNode> getterToLeafSchema) {
final Map<String, LeafNodeCodecContext<?>> leaves = new HashMap<>();
return ImmutableMap.copyOf(leaves);
}
+ private ImmutableMap<String, AnyxmlNodeCodecContext<?>> getAnyxmlNodesUsingReflection(final Class<?> parentClass,
+ final Map<String, DataSchemaNode> getterToAnyxmlSchema) {
+ final Map<String, AnyxmlNodeCodecContext<?>> anyxmls = new HashMap<>();
+ for (final Method method : parentClass.getMethods()) {
+ if (method.getParameterTypes().length == 0) {
+ final DataSchemaNode schema = getterToAnyxmlSchema.get(method.getName());
+ if (schema instanceof AnyXmlSchemaNode) {
+ final Class<?> valueType = method.getReturnType();
+ final Codec<Object, Object> codec = (Codec) getAnyxmlCodec();
+ final AnyxmlNodeCodecContext<?> anyxmlNodeCtx =
+ new AnyxmlNodeCodecContext<>(schema, codec, method, context.getSchemaContext());
+ anyxmls.put(schema.getQName().getLocalName(), anyxmlNodeCtx);
+ }
+ }
+ }
+ return ImmutableMap.copyOf(anyxmls);
+ }
+
private Codec<Object, Object> getCodec(final Class<?> valueType, final DataSchemaNode schema) {
Preconditions.checkArgument(schema instanceof TypedDataSchemaNode, "Unsupported leaf node type %s", schema);
*/
ImmutableMap<String, LeafNodeCodecContext<?>> getLeafNodes(Class<?> type, DataNodeContainer schema);
+ /**
+ * Returns anyxml nodes for supplied data container and parent class.
+ *
+ * @param type Binding type for which anyxml should be loaded.
+ * @param schema Instantiated schema of binding type.
+ * @return Map of local name to anyxml node context.
+ */
+ ImmutableMap<String, AnyxmlNodeCodecContext<?>> getAnyxmlNodes(Class<?> type, DataNodeContainer schema);
+
/**
* Returns Path argument codec for list item.
*
}
protected abstract Object deserializeObject(NormalizedNode<?, ?> normalizedNode);
-}
\ No newline at end of file
+}
private static final Comparator<Method> METHOD_BY_ALPHABET = Comparator.comparing(Method::getName);
private final ImmutableMap<String, LeafNodeCodecContext<?>> leafChild;
+ private final ImmutableMap<String, AnyxmlNodeCodecContext<?>> anyxmlChild;
private final ImmutableMap<YangInstanceIdentifier.PathArgument, NodeContextSupplier> byYang;
private final ImmutableSortedMap<Method, NodeContextSupplier> byMethod;
private final ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> byStreamClass;
super(prototype);
this.leafChild = factory().getLeafNodes(getBindingClass(), getSchema());
+ this.anyxmlChild = factory().getAnyxmlNodes(getBindingClass(), getSchema());
final Map<Class<?>, Method> clsToMethod = BindingReflections.getChildrenClassToMethod(getBindingClass());
byYangBuilder.put(leaf.getDomPathArgument(), leaf);
}
+ for (final AnyxmlNodeCodecContext<?> anyxml : anyxmlChild.values()) {
+ byMethodBuilder.put(anyxml.getGetter(), anyxml);
+ byYangBuilder.put(anyxml.getDomPathArgument(), anyxml);
+ }
+
for (final Entry<Class<?>, Method> childDataObj : clsToMethod.entrySet()) {
final DataContainerCodecPrototype<?> childProto = loadChildPrototype(childDataObj.getKey());
byMethodBuilder.put(childDataObj.getValue(), childProto);
return IncorrectNestingException.checkNonNull(value, "Leaf %s is not valid for %s", name, getBindingClass());
}
+ public final AnyxmlNodeCodecContext<?> getAnyxmlChild(final String name) {
+ final AnyxmlNodeCodecContext<?> value = anyxmlChild.get(name);
+ return IncorrectNestingException.checkNonNull(value, "Anyxml %s is not valid for %s", name, getBindingClass());
+ }
+
private DataContainerCodecPrototype<?> loadChildPrototype(final Class<?> childClass) {
final DataSchemaNode origDef = factory().getRuntimeContext().getSchemaDefinition(childClass);
// Direct instantiation or use in same module in which grouping
import java.util.Map.Entry;
import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.context.CaseNodeCodecContext;
import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.context.KeyedListNodeCodecContext;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.context.base.AnyxmlNodeCodecContext;
import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.context.base.DataContainerCodecContext;
import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.context.base.LeafNodeCodecContext;
import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.context.base.NodeCodecContext;
return new AbstractMap.SimpleEntry<>(domArg, domValue);
}
+ private Map.Entry<NodeIdentifier, Object> serializeAnyxml(final String localName, final Object value) {
+ Preconditions.checkArgument(current() instanceof TreeNodeCodecContext);
+
+ final TreeNodeCodecContext<?, ?> currentCasted = (TreeNodeCodecContext<?, ?>) current();
+ final AnyxmlNodeCodecContext<?> anyxmlContext = currentCasted.getAnyxmlChild(localName);
+
+ final NodeIdentifier domArg = (NodeIdentifier) anyxmlContext.getDomPathArgument();
+ final Object domValue = anyxmlContext.getValueCodec().serialize(value);
+ emitSchema(anyxmlContext.getSchema());
+ return new AbstractMap.SimpleEntry<>(domArg, domValue);
+ }
+
@Override
public void leafNode(final String localName, final Object value) throws IOException {
final Entry<NodeIdentifier, Object> dom = serializeLeaf(localName, value);
@Override
public void anyxmlNode(final String name, final Object value) throws IOException {
- final Entry<NodeIdentifier, Object> dom = serializeLeaf(name, value);
+ final Entry<NodeIdentifier, Object> dom = serializeAnyxml(name, value);
getDelegate().anyxmlNode(dom.getKey(), dom.getValue());
}