2 * Copyright (c) 2014 Cisco Systems, Inc. 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
8 package org.opendaylight.mdsal.binding.dom.codec.impl;
10 import com.google.common.base.Optional;
11 import com.google.common.collect.ImmutableCollection;
12 import com.google.common.collect.ImmutableSet;
13 import java.io.IOException;
14 import java.util.List;
15 import javax.annotation.Nonnull;
16 import javax.annotation.Nullable;
17 import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeCachingCodec;
18 import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
19 import org.opendaylight.yangtools.yang.binding.DataObject;
20 import org.opendaylight.yangtools.yang.binding.DataObjectSerializer;
21 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
22 import org.opendaylight.yangtools.yang.common.QName;
23 import org.opendaylight.yangtools.yang.common.QNameModule;
24 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
25 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
26 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
27 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
28 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
29 import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
31 abstract class DataContainerCodecContext<D extends DataObject, T extends WithStatus> extends NodeCodecContext<D> {
33 private final DataContainerCodecPrototype<T> prototype;
34 private volatile DataObjectSerializer eventStreamSerializer;
36 protected DataContainerCodecContext(final DataContainerCodecPrototype<T> prototype) {
37 this.prototype = prototype;
41 public final T getSchema() {
42 return prototype.getSchema();
45 protected final QNameModule namespace() {
46 return prototype.getNamespace();
49 protected final CodecContextFactory factory() {
50 return prototype.getFactory();
54 protected YangInstanceIdentifier.PathArgument getDomPathArgument() {
55 return prototype.getYangArg();
59 * Returns nested node context using supplied YANG Instance Identifier.
61 * @param arg Yang Instance Identifier Argument
62 * @return Context of child
63 * @throws IllegalArgumentException If supplied argument does not represent valid child.
66 public abstract NodeCodecContext<?> yangPathArgumentChild(YangInstanceIdentifier.PathArgument arg);
69 * Returns nested node context using supplied Binding Instance Identifier
70 * and adds YANG instance identifiers to supplied list.
72 * @param arg Binding Instance Identifier Argument
73 * @return Context of child or null if supplied {@code arg} does not represent valid child.
74 * @throws IllegalArgumentException If supplied argument does not represent valid child.
78 public DataContainerCodecContext<?,?> bindingPathArgumentChild(final PathArgument arg,
79 final List<YangInstanceIdentifier.PathArgument> builder) {
80 final DataContainerCodecContext<?,?> child = streamChild(arg.getType());
82 if (builder != null) {
83 child.addYangPathArgument(arg,builder);
87 throw new IllegalArgumentException("Supplied argument is not valid child");
91 * Returns deserialized Binding Path Argument from YANG instance identifier.
93 protected PathArgument getBindingPathArgument(final YangInstanceIdentifier.PathArgument domArg) {
97 protected final PathArgument bindingArg() {
98 return prototype.getBindingArg();
101 @SuppressWarnings("unchecked")
103 public final Class<D> getBindingClass() {
104 return Class.class.cast(prototype.getBindingClass());
108 * Returns child context as if it was walked by {@link BindingStreamEventWriter}. This means that to enter case, one
109 * must issue getChild(ChoiceClass).getChild(CaseClass).
111 * @param childClass child class
112 * @return Context of child node or null, if supplied class is not subtree child
113 * @throws IllegalArgumentException If supplied child class is not valid in specified context.
116 public abstract @Nullable <C extends DataObject> DataContainerCodecContext<C, ?> streamChild(Class<C> childClass);
119 * Returns child context as if it was walked by {@link BindingStreamEventWriter}. This means that to enter case, one
120 * must issue getChild(ChoiceClass).getChild(CaseClass).
122 * @param childClass child class
123 * @return Context of child or Optional absent is supplied class is not applicable in context.
126 public abstract <C extends DataObject> Optional<DataContainerCodecContext<C,?>> possibleStreamChild(
127 Class<C> childClass);
130 public String toString() {
131 return getClass().getSimpleName() + " [" + prototype.getBindingClass() + "]";
135 public BindingNormalizedNodeCachingCodec<D> createCachingCodec(
136 final ImmutableCollection<Class<? extends DataObject>> cacheSpecifier) {
137 if (cacheSpecifier.isEmpty()) {
138 return new NonCachingCodec<>(this);
140 return new CachingNormalizedNodeCodec<>(this,ImmutableSet.copyOf(cacheSpecifier));
143 BindingStreamEventWriter createWriter(final NormalizedNodeStreamWriter domWriter) {
144 return BindingToNormalizedStreamWriter.create(this, domWriter);
148 protected final <V> V childNonNull(@Nullable final V nullable, final YangInstanceIdentifier.PathArgument child,
149 final String message, final Object... args) {
150 if (nullable != null) {
153 MissingSchemaException.checkModulePresent(factory().getRuntimeContext().getSchemaContext(), child);
154 throw IncorrectNestingException.create(message, args);
158 protected final <V> V childNonNull(@Nullable final V nullable, final QName child, final String message,
159 final Object... args) {
160 if (nullable != null) {
163 MissingSchemaException.checkModulePresent(factory().getRuntimeContext().getSchemaContext(), child);
164 throw IncorrectNestingException.create(message, args);
168 protected final <V> V childNonNull(@Nullable final V nullable, final Class<?> childClass, final String message,
169 final Object... args) {
170 if (nullable != null) {
173 MissingSchemaForClassException.check(factory().getRuntimeContext(), childClass);
174 MissingClassInLoadingStrategyException.check(factory().getRuntimeContext().getStrategy(), childClass);
175 throw IncorrectNestingException.create(message, args);
178 DataObjectSerializer eventStreamSerializer() {
179 if (eventStreamSerializer == null) {
180 eventStreamSerializer = factory().getEventStreamSerializer(getBindingClass());
182 return eventStreamSerializer;
186 public NormalizedNode<?, ?> serialize(final D data) {
187 final NormalizedNodeResult result = new NormalizedNodeResult();
188 // We create DOM stream writer which produces normalized nodes
189 final NormalizedNodeStreamWriter domWriter = ImmutableNormalizedNodeStreamWriter.from(result);
190 writeAsNormalizedNode(data, domWriter);
191 return result.getResult();
195 public void writeAsNormalizedNode(final D data, final NormalizedNodeStreamWriter writer) {
197 eventStreamSerializer().serialize(data, createWriter(writer));
198 } catch (final IOException e) {
199 throw new IllegalStateException("Failed to serialize Binding DTO",e);