Fix checkstyle in mdsal-binding2-dom-codec
[mdsal.git] / binding2 / mdsal-binding2-dom-codec / src / main / java / org / opendaylight / mdsal / binding / javav2 / dom / codec / impl / context / base / DataContainerCodecContext.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies s.r.o. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.mdsal.binding.javav2.dom.codec.impl.context.base;
10
11 import com.google.common.annotations.Beta;
12 import com.google.common.base.Optional;
13 import com.google.common.collect.ImmutableCollection;
14 import com.google.common.collect.ImmutableSet;
15 import java.io.IOException;
16 import java.util.List;
17 import javax.annotation.Nonnull;
18 import javax.annotation.Nullable;
19 import org.opendaylight.mdsal.binding.javav2.dom.codec.api.BindingNormalizedNodeCachingCodec;
20 import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.MissingSchemaException;
21 import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.NonCachingCodec;
22 import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.cache.CachingNormalizedNodeCodec;
23 import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.serializer.BindingToNormalizedStreamWriter;
24 import org.opendaylight.mdsal.binding.javav2.spec.base.TreeArgument;
25 import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
26 import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingStreamEventWriter;
27 import org.opendaylight.mdsal.binding.javav2.spec.runtime.TreeNodeSerializer;
28 import org.opendaylight.yangtools.yang.common.QName;
29 import org.opendaylight.yangtools.yang.common.QNameModule;
30 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
31 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
32 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
33 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
34 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
35 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
36
37 @Beta
38 public abstract class DataContainerCodecContext<D extends TreeNode, T> extends NodeCodecContext<D> {
39
40     private final DataContainerCodecPrototype<T> prototype;
41     private volatile TreeNodeSerializer eventStreamSerializer;
42
43     protected DataContainerCodecContext(final DataContainerCodecPrototype<T> prototype) {
44         this.prototype = prototype;
45     }
46
47     @Nonnull
48     @Override
49     public final T getSchema() {
50         return prototype.getSchema();
51     }
52
53     protected final QNameModule namespace() {
54         return prototype.getNamespace();
55     }
56
57     protected final CodecContextFactory factory() {
58         return prototype.getFactory();
59     }
60
61     @Override
62     public YangInstanceIdentifier.PathArgument getDomPathArgument() {
63         return prototype.getYangArg();
64     }
65
66     /**
67      * Returns nested node context using supplied YANG Instance Identifier.
68      *
69      * @param arg Yang Instance Identifier Argument
70      * @return Context of child
71      * @throws IllegalArgumentException If supplied argument does not represent valid child.
72      */
73     @Nonnull
74     @Override
75     public abstract NodeCodecContext<?> yangPathArgumentChild(YangInstanceIdentifier.PathArgument arg);
76
77     /**
78      * Returns nested node context using supplied Binding Instance Identifier
79      * and adds YANG instance identifiers to supplied list.
80      *
81      * @param arg Binding Instance Identifier Argument
82      * @return Context of child or null if supplied {@code arg} does not represent valid child.
83      * @throws IllegalArgumentException If supplied argument does not represent valid child.
84      */
85     @SuppressWarnings("unchecked")
86     @Nonnull
87     @Override
88     public DataContainerCodecContext<?,?> bindingPathArgumentChild(@Nonnull final TreeArgument<?> arg,
89             final List<PathArgument> builder) {
90         final DataContainerCodecContext<?,?> child = streamChild((Class<? extends TreeNode>) arg.getType());
91         if (builder != null) {
92             child.addYangPathArgument(arg,builder);
93         }
94         return child;
95     }
96
97     /**
98      * Returns de-serialized Binding Path Argument from YANG instance identifier.
99      *
100      * @param domArg input path argument
101      * @return returns binding path argument
102      */
103     @SuppressWarnings("rawtypes")
104     protected TreeArgument getBindingPathArgument(final YangInstanceIdentifier.PathArgument domArg) {
105         return bindingArg();
106     }
107
108     @SuppressWarnings("rawtypes")
109     protected final TreeArgument bindingArg() {
110         return prototype.getBindingArg();
111     }
112
113     @Nonnull
114     @SuppressWarnings("unchecked")
115     @Override
116     public final Class<D> getBindingClass() {
117         return Class.class.cast(prototype.getBindingClass());
118     }
119
120     /**
121      * Returns child context as if it was walked by
122      * {@link BindingStreamEventWriter}. This means that to enter case, one
123      * must issue getChild(ChoiceClass).getChild(CaseClass).
124      *
125      * @param childClass input child class
126      * @return Context of child node or null, if supplied class is not subtree child
127      * @throws IllegalArgumentException
128      *             If supplied child class is not valid in specified context.
129      */
130     @Nonnull
131     @Override
132     public abstract <C extends TreeNode> DataContainerCodecContext<C,?> streamChild(@Nonnull Class<C> childClass)
133         throws IllegalArgumentException;
134
135     /**
136      * Returns child context as if it was walked by {@link BindingStreamEventWriter}. This means that to enter
137      * case, one must issue getChild(ChoiceClass).getChild(CaseClass).
138      *
139      * @param childClass input child class
140      * @return Context of child or Optional absent is supplied class is not applicable in context.
141      */
142     @Override
143     public abstract <C extends TreeNode> Optional<DataContainerCodecContext<C, ?>> possibleStreamChild(@Nonnull
144         Class<C> childClass);
145
146     @Override
147     public String toString() {
148         return getClass().getSimpleName() + " [" + prototype.getBindingClass() + "]";
149     }
150
151     @Nonnull
152     @Override
153     public BindingNormalizedNodeCachingCodec<D> createCachingCodec(
154             @Nonnull final ImmutableCollection<Class<? extends TreeNode>> cacheSpecifier) {
155         if (cacheSpecifier.isEmpty()) {
156             return new NonCachingCodec<D>(this);
157         }
158         return new CachingNormalizedNodeCodec<D>(this, ImmutableSet.copyOf(cacheSpecifier));
159     }
160
161     public BindingStreamEventWriter createWriter(final NormalizedNodeStreamWriter domWriter) {
162         return BindingToNormalizedStreamWriter.create(this, domWriter);
163     }
164
165     @Nonnull
166     protected final <V> V childNonNull(@Nullable final V nullable, final YangInstanceIdentifier.PathArgument child,
167             final String message, final Object... args) {
168         if (nullable != null) {
169             return nullable;
170         }
171         MissingSchemaException.checkModulePresent(factory().getRuntimeContext().getSchemaContext(), child);
172         throw IncorrectNestingException.create(message, args);
173     }
174
175     @Nonnull
176     protected final <V> V childNonNull(@Nullable final V nullable, final QName child, final String message,
177             final Object... args) {
178         if (nullable != null) {
179             return nullable;
180         }
181         MissingSchemaException.checkModulePresent(factory().getRuntimeContext().getSchemaContext(), child);
182         throw IncorrectNestingException.create(message, args);
183     }
184
185     @Nonnull
186     protected final <V> V childNonNull(@Nullable final V nullable, final Class<?> childClass, final String message,
187             final Object... args) {
188         if (nullable != null) {
189             return nullable;
190         }
191         MissingSchemaForClassException.check(factory().getRuntimeContext(), childClass);
192         MissingClassInLoadingStrategyException.check(factory().getRuntimeContext().getStrategy(), childClass);
193         throw IncorrectNestingException.create(message, args);
194     }
195
196     public TreeNodeSerializer eventStreamSerializer() {
197         if (eventStreamSerializer == null) {
198             eventStreamSerializer = factory().getEventStreamSerializer(getBindingClass());
199         }
200         return eventStreamSerializer;
201     }
202
203     @Nonnull
204     @Override
205     public NormalizedNode<?, ?> serialize(@Nonnull final D data) {
206         final NormalizedNodeResult result = new NormalizedNodeResult();
207         // We create DOM stream writer which produces normalized nodes
208         final NormalizedNodeStreamWriter domWriter = ImmutableNormalizedNodeStreamWriter.from(result);
209         writeAsNormalizedNode(data, domWriter);
210         return result.getResult();
211     }
212
213     @Override
214     public void writeAsNormalizedNode(final D data, final NormalizedNodeStreamWriter writer) {
215         try {
216             eventStreamSerializer().serialize(data, createWriter(writer));
217         } catch (final IOException e) {
218             throw new IllegalStateException("Failed to serialize Binding DTO",e);
219         }
220     }
221
222 }