Merge "Revert "Composite node <-> normalized node serializer and deserializer""
[yangtools.git] / yang / yang-data-impl / src / main / java / org / opendaylight / yangtools / yang / data / impl / schema / transform / base / serializer / NodeSerializerDispatcher.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. 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 package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer;
9
10 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
11 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
12 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
13 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
14 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
15 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
16 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
17 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
18 import org.opendaylight.yangtools.yang.data.api.schema.MixinNode;
19 import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializerFactory;
20 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
21 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
22 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
23 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
24 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
25
26 import com.google.common.base.Preconditions;
27 import com.google.common.collect.Iterables;
28
29 /**
30  *
31  * Dispatches the serialization process of nodes according to schema and returns the serialized elements.
32  *
33  * @param <E> type of serialized elements
34  */
35 public interface NodeSerializerDispatcher<E> {
36
37     Iterable<E> dispatchChildElement(Object childSchema,
38             DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> dataContainerChild);
39
40     /**
41      * Abstract implementation that implements the dispatch conditions. Only requires serializers to be provided.
42      * The same instance of serializer can be provided in case it is immutable.
43      */
44     public static abstract class BaseNodeSerializerDispatcher<E> implements NodeSerializerDispatcher<E> {
45         private final FromNormalizedNodeSerializerFactory<E> factory;
46
47         protected BaseNodeSerializerDispatcher(final FromNormalizedNodeSerializerFactory<E> factory) {
48             this.factory = Preconditions.checkNotNull(factory);
49         }
50
51         @Override
52         public final Iterable<E> dispatchChildElement(Object childSchema,
53                 DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> dataContainerChild) {
54             if (dataContainerChild instanceof ContainerNode) {
55                 return onContainerNode(childSchema, dataContainerChild);
56             } else if (dataContainerChild instanceof LeafNode<?>) {
57                 return onLeafNode(childSchema, dataContainerChild);
58             } else if (dataContainerChild instanceof MixinNode) {
59                 if (dataContainerChild instanceof LeafSetNode<?>) {
60                     return onLeafListNode(childSchema, dataContainerChild);
61                 } else if (dataContainerChild instanceof MapNode) {
62                     return onListNode(childSchema, dataContainerChild);
63                 } else if (dataContainerChild instanceof ChoiceNode) {
64                     return onChoiceNode(childSchema, dataContainerChild);
65                 } else if (dataContainerChild instanceof AugmentationNode) {
66                     return onAugmentationSchema(childSchema, dataContainerChild);
67                 }
68             }
69             throw new IllegalArgumentException("Unable to serialize " + childSchema);
70         }
71
72         private Iterable<E> onAugmentationSchema(Object childSchema,
73                 DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> dataContainerChild) {
74             checkSchemaCompatibility(childSchema, AugmentationSchema.class, dataContainerChild);
75             return factory.getAugmentationNodeSerializer().serialize((AugmentationSchema) childSchema,
76                     (AugmentationNode) dataContainerChild);
77         }
78
79         private Iterable<E> onChoiceNode(Object childSchema,
80                 DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> dataContainerChild) {
81             checkSchemaCompatibility(childSchema, org.opendaylight.yangtools.yang.model.api.ChoiceNode.class,
82                     dataContainerChild);
83             return factory.getChoiceNodeSerializer()
84                     .serialize((org.opendaylight.yangtools.yang.model.api.ChoiceNode) childSchema,
85                             (ChoiceNode) dataContainerChild);
86         }
87
88         private Iterable<E> onListNode(Object childSchema,
89                 DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> dataContainerChild) {
90             checkSchemaCompatibility(childSchema, ListSchemaNode.class, dataContainerChild);
91             return factory.getMapNodeSerializer().serialize((ListSchemaNode) childSchema, (MapNode) dataContainerChild);
92         }
93
94         private Iterable<E> onLeafListNode(Object childSchema,
95                 DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> dataContainerChild) {
96             checkSchemaCompatibility(childSchema, LeafListSchemaNode.class, dataContainerChild);
97             return factory.getLeafSetNodeSerializer().serialize((LeafListSchemaNode) childSchema,
98                     (LeafSetNode<?>) dataContainerChild);
99         }
100
101         private Iterable<E> onLeafNode(Object childSchema,
102                 DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> dataContainerChild) {
103             checkSchemaCompatibility(childSchema, LeafSchemaNode.class, dataContainerChild);
104             Iterable<E> elements = factory.getLeafNodeSerializer().serialize((LeafSchemaNode) childSchema,
105                     (LeafNode<?>) dataContainerChild);
106             checkOnlyOneSerializedElement(elements, dataContainerChild);
107             return elements;
108         }
109
110         private static void checkOnlyOneSerializedElement(Iterable<?> elements,
111                 DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> dataContainerChild) {
112             final int size = Iterables.size(elements);
113             Preconditions.checkArgument(size == 1,
114                     "Unexpected count of elements for entry serialized from: %s, should be 1, was: %s",
115                     dataContainerChild, size);
116         }
117
118         private Iterable<E> onContainerNode(Object childSchema,
119                 DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> dataContainerChild) {
120             checkSchemaCompatibility(childSchema, ContainerSchemaNode.class, dataContainerChild);
121
122             Iterable<E> elements = factory.getContainerNodeSerializer().serialize((ContainerSchemaNode) childSchema,
123                     (ContainerNode) dataContainerChild);
124             checkOnlyOneSerializedElement(elements, dataContainerChild);
125             return elements;
126         }
127
128         private static void checkSchemaCompatibility(Object childSchema, Class<?> containerSchemaNodeClass,
129                 DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> dataContainerChild) {
130             Preconditions.checkArgument(containerSchemaNodeClass.isAssignableFrom(childSchema.getClass()),
131                     "Incompatible schema: %s with node: %s, expected: %s", childSchema, dataContainerChild,
132                     containerSchemaNodeClass);
133         }
134     }
135 }