2 * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.mdsal.binding.javav2.dom.codec.impl.context.base;
11 import com.google.common.annotations.Beta;
12 import com.google.common.base.Optional;
13 import com.google.common.collect.ImmutableCollection;
14 import java.io.IOException;
15 import java.util.List;
16 import javax.annotation.Nonnull;
17 import javax.annotation.Nullable;
18 import org.opendaylight.mdsal.binding.javav2.dom.codec.api.codecs.BindingNormalizedNodeCachingCodec;
19 import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.MissingSchemaException;
20 import org.opendaylight.mdsal.binding.javav2.spec.base.TreeArgument;
21 import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
22 import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingStreamEventWriter;
23 import org.opendaylight.mdsal.binding.javav2.spec.runtime.TreeNodeSerializer;
24 import org.opendaylight.yangtools.yang.common.QName;
25 import org.opendaylight.yangtools.yang.common.QNameModule;
26 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
27 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
28 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
29 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
30 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
31 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
32 import sun.reflect.generics.reflectiveObjects.NotImplementedException;
35 abstract class DataContainerCodecContext<D extends TreeNode, T> extends NodeCodecContext<D> {
37 private final DataContainerCodecPrototype<T> prototype;
38 private volatile TreeNodeSerializer eventStreamSerializer;
40 protected DataContainerCodecContext(final DataContainerCodecPrototype<T> prototype) {
41 this.prototype = prototype;
46 public final T getSchema() {
47 return prototype.getSchema();
50 protected final QNameModule namespace() {
51 return prototype.getNamespace();
54 protected final CodecContextFactory factory() {
55 return prototype.getFactory();
59 protected YangInstanceIdentifier.PathArgument getDomPathArgument() {
60 return prototype.getYangArg();
64 * Returns nested node context using supplied YANG Instance Identifier
66 * @param arg Yang Instance Identifier Argument
67 * @return Context of child
68 * @throws IllegalArgumentException If supplied argument does not represent valid child.
72 public abstract NodeCodecContext<?> yangPathArgumentChild(final YangInstanceIdentifier.PathArgument arg);
75 * Returns nested node context using supplied Binding Instance Identifier
76 * and adds YANG instance identifiers to supplied list.
78 * @param arg Binding Instance Identifier Argument
79 * @return Context of child or null if supplied {@code arg} does not represent valid child.
80 * @throws IllegalArgumentException If supplied argument does not represent valid child.
82 @SuppressWarnings("unchecked")
85 public DataContainerCodecContext<?,?> bindingPathArgumentChild(@Nonnull final TreeArgument<?> arg,
86 final List<PathArgument> builder) {
87 final DataContainerCodecContext<?,?> child = streamChild((Class<? extends TreeNode>) arg.getType());
88 if (builder != null) {
89 child.addYangPathArgument(arg,builder);
95 * Returns de-serialized Binding Path Argument from YANG instance identifier.
97 * @param domArg input path argument
98 * @return returns binding path argument
100 @SuppressWarnings("rawtypes")
101 protected TreeArgument getBindingPathArgument(final YangInstanceIdentifier.PathArgument domArg) {
105 @SuppressWarnings("rawtypes")
106 protected final TreeArgument bindingArg() {
107 return prototype.getBindingArg();
111 @SuppressWarnings("unchecked")
113 public final Class<D> getBindingClass() {
114 return Class.class.cast(prototype.getBindingClass());
118 * Returns child context as if it was walked by
119 * {@link BindingStreamEventWriter}. This means that to enter case, one
120 * must issue getChild(ChoiceClass).getChild(CaseClass).
122 * @param childClass input child class
123 * @return Context of child node or null, if supplied class is not subtree child
124 * @throws IllegalArgumentException If supplied child class is not valid in specified context.
128 public abstract <DV extends TreeNode> DataContainerCodecContext<DV,?> streamChild(@Nonnull final Class<DV> childClass) throws IllegalArgumentException;
131 * Returns child context as if it was walked by
132 * {@link BindingStreamEventWriter}. This means that to enter case, one
133 * must issue getChild(ChoiceClass).getChild(CaseClass).
135 * @param childClass input child class
136 * @return Context of child or Optional absent is supplied class is not applicable in context.
139 public abstract <DV extends TreeNode> Optional<DataContainerCodecContext<DV, ?>> possibleStreamChild(@Nonnull
140 final Class<DV> childClass);
143 public String toString() {
144 return getClass().getSimpleName() + " [" + prototype.getBindingClass() + "]";
149 public BindingNormalizedNodeCachingCodec<D> createCachingCodec(
150 @Nonnull final ImmutableCollection<Class<? extends TreeNode>> cacheSpecifier) {
152 //TODO: implement in cache-related patches to come
153 throw new NotImplementedException();
156 BindingStreamEventWriter createWriter(final NormalizedNodeStreamWriter domWriter) {
158 //TODO: streamWriter to come
159 throw new NotImplementedException();
163 protected final <V> V childNonNull(@Nullable final V nullable, final YangInstanceIdentifier.PathArgument child,
164 final String message, final Object... args) {
165 if (nullable != null) {
168 MissingSchemaException.checkModulePresent(factory().getRuntimeContext().getSchemaContext(), child);
169 throw IncorrectNestingException.create(message, args);
173 protected final <V> V childNonNull(@Nullable final V nullable, final QName child, final String message,
174 final Object... args) {
175 if (nullable != null) {
178 MissingSchemaException.checkModulePresent(factory().getRuntimeContext().getSchemaContext(), child);
179 throw IncorrectNestingException.create(message, args);
183 protected final <V> V childNonNull(@Nullable final V nullable, final Class<?> childClass, final String message,
184 final Object... args) {
185 if (nullable != null) {
188 MissingSchemaForClassException.check(factory().getRuntimeContext(), childClass);
189 MissingClassInLoadingStrategyException.check(factory().getRuntimeContext().getStrategy(), childClass);
190 throw IncorrectNestingException.create(message, args);
193 TreeNodeSerializer eventStreamSerializer() {
194 if(eventStreamSerializer == null) {
195 eventStreamSerializer = factory().getEventStreamSerializer(getBindingClass());
197 return eventStreamSerializer;
202 public NormalizedNode<?, ?> serialize(@Nonnull final D data) {
203 final NormalizedNodeResult result = new NormalizedNodeResult();
204 // We create DOM stream writer which produces normalized nodes
205 final NormalizedNodeStreamWriter domWriter = ImmutableNormalizedNodeStreamWriter.from(result);
206 writeAsNormalizedNode(data, domWriter);
207 return result.getResult();
211 public void writeAsNormalizedNode(final D data, final NormalizedNodeStreamWriter writer) {
213 eventStreamSerializer().serialize(data, createWriter(writer));
214 } catch (final IOException e) {
215 throw new IllegalStateException("Failed to serialize Binding DTO",e);