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.collect.ImmutableCollection;
11 import com.google.common.collect.ImmutableSet;
12 import java.io.IOException;
13 import java.util.List;
14 import java.util.Optional;
15 import org.eclipse.jdt.annotation.NonNull;
16 import org.eclipse.jdt.annotation.Nullable;
17 import org.opendaylight.mdsal.binding.dom.codec.api.BindingDataObjectCodecTreeNode;
18 import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeCachingCodec;
19 import org.opendaylight.yangtools.yang.binding.BindingObject;
20 import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
21 import org.opendaylight.yangtools.yang.binding.DataObject;
22 import org.opendaylight.yangtools.yang.binding.DataObjectSerializer;
23 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
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.schema.NormalizedNode;
28 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
29 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
30 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
31 import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
33 abstract class DataContainerCodecContext<D extends DataObject, T extends WithStatus> extends NodeCodecContext
34 implements BindingDataObjectCodecTreeNode<D> {
36 private final DataContainerCodecPrototype<T> prototype;
37 private volatile DataObjectSerializer eventStreamSerializer;
39 protected DataContainerCodecContext(final DataContainerCodecPrototype<T> prototype) {
40 this.prototype = prototype;
44 public final T getSchema() {
45 return prototype.getSchema();
49 public final ChildAddressabilitySummary getChildAddressabilitySummary() {
50 return prototype.getChildAddressabilitySummary();
53 protected final QNameModule namespace() {
54 return prototype.getNamespace();
57 protected final CodecContextFactory factory() {
58 return prototype.getFactory();
62 protected YangInstanceIdentifier.PathArgument getDomPathArgument() {
63 return prototype.getYangArg();
67 * Returns nested node context using supplied YANG Instance Identifier.
69 * @param arg Yang Instance Identifier Argument
70 * @return Context of child
71 * @throws IllegalArgumentException If supplied argument does not represent valid child.
74 public abstract NodeCodecContext yangPathArgumentChild(YangInstanceIdentifier.PathArgument arg);
77 * Returns nested node context using supplied Binding Instance Identifier
78 * and adds YANG instance identifiers to supplied list.
80 * @param arg Binding Instance Identifier Argument
81 * @return Context of child or null if supplied {@code arg} does not represent valid child.
82 * @throws IllegalArgumentException If supplied argument does not represent valid child.
85 public DataContainerCodecContext<?, ?> bindingPathArgumentChild(final PathArgument arg,
86 final List<YangInstanceIdentifier.PathArgument> builder) {
87 final DataContainerCodecContext<?,?> child = streamChild(arg.getType());
88 if (builder != null) {
89 child.addYangPathArgument(arg,builder);
95 * Returns deserialized Binding Path Argument from YANG instance identifier.
97 protected PathArgument getBindingPathArgument(final YangInstanceIdentifier.PathArgument domArg) {
101 protected final PathArgument bindingArg() {
102 return prototype.getBindingArg();
105 @SuppressWarnings("unchecked")
107 public final Class<D> getBindingClass() {
108 return Class.class.cast(prototype.getBindingClass());
112 public abstract <C extends DataObject> DataContainerCodecContext<C, ?> streamChild(Class<C> childClass);
115 * Returns child context as if it was walked by {@link BindingStreamEventWriter}. This means that to enter case, one
116 * must issue getChild(ChoiceClass).getChild(CaseClass).
118 * @param childClass child class
119 * @return Context of child or Optional.empty is supplied class is not applicable in context.
122 public abstract <C extends DataObject> Optional<DataContainerCodecContext<C,?>> possibleStreamChild(
123 Class<C> childClass);
126 public String toString() {
127 return getClass().getSimpleName() + " [" + prototype.getBindingClass() + "]";
131 public BindingNormalizedNodeCachingCodec<D> createCachingCodec(
132 final ImmutableCollection<Class<? extends BindingObject>> cacheSpecifier) {
133 if (cacheSpecifier.isEmpty()) {
134 return new NonCachingCodec<>(this);
136 return new CachingNormalizedNodeCodec<>(this, ImmutableSet.copyOf(cacheSpecifier));
139 BindingStreamEventWriter createWriter(final NormalizedNodeStreamWriter domWriter) {
140 return BindingToNormalizedStreamWriter.create(this, domWriter);
143 protected final <V> @NonNull V childNonNull(final @Nullable V nullable,
144 final YangInstanceIdentifier.PathArgument child, final String message, final Object... args) {
145 if (nullable != null) {
148 MissingSchemaException.checkModulePresent(factory().getRuntimeContext().getSchemaContext(), child);
149 throw IncorrectNestingException.create(message, args);
152 protected final <V> @NonNull V childNonNull(final @Nullable V nullable, final QName child, final String message,
153 final Object... args) {
154 if (nullable != null) {
157 MissingSchemaException.checkModulePresent(factory().getRuntimeContext().getSchemaContext(), child);
158 throw IncorrectNestingException.create(message, args);
161 protected final <V> @NonNull V childNonNull(final @Nullable V nullable, final Class<?> childClass,
162 final String message, final Object... args) {
163 if (nullable != null) {
166 MissingSchemaForClassException.check(factory().getRuntimeContext(), childClass);
167 MissingClassInLoadingStrategyException.check(factory().getRuntimeContext().getStrategy(), childClass);
168 throw IncorrectNestingException.create(message, args);
171 DataObjectSerializer eventStreamSerializer() {
172 if (eventStreamSerializer == null) {
173 eventStreamSerializer = factory().getEventStreamSerializer(getBindingClass());
175 return eventStreamSerializer;
179 public NormalizedNode<?, ?> serialize(final D data) {
180 final NormalizedNodeResult result = new NormalizedNodeResult();
181 // We create DOM stream writer which produces normalized nodes
182 final NormalizedNodeStreamWriter domWriter = ImmutableNormalizedNodeStreamWriter.from(result);
183 writeAsNormalizedNode(data, domWriter);
184 return result.getResult();
188 public void writeAsNormalizedNode(final D data, final NormalizedNodeStreamWriter writer) {
190 eventStreamSerializer().serialize(data, createWriter(writer));
191 } catch (final IOException e) {
192 throw new IllegalStateException("Failed to serialize Binding DTO",e);