Remove Augmentation{Identifier,Node}
[yangtools.git] / data / yang-data-transform / src / main / java / org / opendaylight / yangtools / transform / QNameTransformingStreamWriter.java
1 /*
2  * Copyright (c) 2015 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.transform;
9
10 import java.io.IOException;
11 import java.util.HashMap;
12 import java.util.Map;
13 import java.util.function.Function;
14 import org.eclipse.jdt.annotation.NonNull;
15 import org.opendaylight.yangtools.yang.common.QName;
16 import org.opendaylight.yangtools.yang.common.QNameModule;
17 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
20 import org.opendaylight.yangtools.yang.data.api.schema.stream.ForwardingNormalizedNodeStreamWriter;
21 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
22
23 /**
24  * Stateless Normalized Node Stream Writer decorator, which performs QName translation.
25  *
26  * <p>
27  * This class serves as base for Normalized Node Stream Writer decorators with option to transform
28  * QNames by user-implemented {@link #transform(QName)} function.
29  */
30 public abstract class QNameTransformingStreamWriter extends ForwardingNormalizedNodeStreamWriter {
31
32     // FIXME: Probably use loading cache to decrease memory
33
34     /**
35      * Returns decorator, which uses supplied function to transform QNames.
36      *
37      * @param delegate Underlying normalized node stream writer
38      * @param transformation Transformation function, function is required to return non-null
39      *        values.
40      * @return decorator, which uses supplied function to transform QNames.
41      */
42     public static NormalizedNodeStreamWriter fromFunction(final NormalizedNodeStreamWriter delegate,
43             final Function<QName, QName> transformation) {
44         return new QNameTransformingStreamWriter() {
45
46             @Override
47             protected NormalizedNodeStreamWriter delegate() {
48                 return delegate;
49             }
50
51             @Override
52             protected QName transform(final QName key) {
53                 return transformation.apply(key);
54             }
55         };
56     }
57
58     /**
59      * Returns decorator, which uses supplied map to transform QNames. QNames not present in map are left unchanged.
60      *
61      * @param delegate Underlying normalized node stream writer
62      * @param mapping Immutable map which represent mapping from original to new values.
63      * @return decorator, which uses supplied mapping to transform QNames.
64      */
65     public static NormalizedNodeStreamWriter createQNameReplacing(final NormalizedNodeStreamWriter delegate,
66             final Map<QName, QName> mapping) {
67         return fromFunction(delegate, new QNameReplacementFunction(mapping));
68     }
69
70     /**
71      * Returns decorator, which uses supplied map to transform QNameModules. QNameModules not present in map are left
72      * unchanged.
73      *
74      * @param delegate Underlying normalized node stream writer
75      * @param mapping Immutable map which represent mapping from original to new values.
76      * @return decorator, which uses supplied mapping to transform QNameModules.
77      */
78     public static NormalizedNodeStreamWriter createQNameModuleReplacing(final NormalizedNodeStreamWriter delegate,
79             final Map<QNameModule, QNameModule> mapping) {
80         return fromFunction(delegate, new QNameModuleReplacementFunction(mapping));
81     }
82
83     @Override
84     public void startLeafNode(final NodeIdentifier name) throws IOException {
85         super.startLeafNode(transform(name));
86     }
87
88     @Override
89     public void startLeafSet(final NodeIdentifier name, final int childSizeHint) throws IOException {
90         super.startLeafSet(transform(name), childSizeHint);
91     }
92
93     @Override
94     public void startOrderedLeafSet(final NodeIdentifier name, final int childSizeHint) throws IOException {
95         super.startOrderedLeafSet(transform(name), childSizeHint);
96     }
97
98     @Override
99     public void startLeafSetEntryNode(final NodeWithValue<?> name) throws IOException {
100         super.startLeafSetEntryNode(transform(name));
101     }
102
103     @Override
104     public void startContainerNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
105         super.startContainerNode(transform(name), childSizeHint);
106     }
107
108     @Override
109     public void startUnkeyedList(final NodeIdentifier name, final int childSizeHint) throws IOException {
110         super.startUnkeyedList(transform(name), childSizeHint);
111     }
112
113     @Override
114     public void startUnkeyedListItem(final NodeIdentifier name, final int childSizeHint) throws IOException {
115         super.startUnkeyedListItem(transform(name), childSizeHint);
116     }
117
118     @Override
119     public void startMapNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
120         super.startMapNode(transform(name), childSizeHint);
121     }
122
123     @Override
124     public void startMapEntryNode(final NodeIdentifierWithPredicates identifier, final int childSizeHint)
125             throws IOException {
126         super.startMapEntryNode(transform(identifier), childSizeHint);
127     }
128
129     @Override
130     public void startOrderedMapNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
131         super.startOrderedMapNode(transform(name), childSizeHint);
132     }
133
134     @Override
135     public void startChoiceNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
136         super.startChoiceNode(transform(name), childSizeHint);
137     }
138
139     @Override
140     public boolean startAnyxmlNode(final NodeIdentifier name, final Class<?> objectModel) throws IOException {
141         return super.startAnyxmlNode(transform(name), objectModel);
142     }
143
144     @Override
145     public void scalarValue(final Object value) throws IOException {
146         // identityref leaf nodes contain identity QName as a value - it needs to be transformed
147         super.scalarValue(value instanceof QName ? transform((QName) value) : value);
148     }
149
150     /**
151      * Transforms a QName to new mapping.
152      *
153      * <p>
154      * NOTE: If QName should be unchanged implementation needs to return original QName.
155      *
156      * @param key QName to transform.
157      * @return Returns new value of QName.
158      */
159     protected abstract @NonNull QName transform(@NonNull QName key);
160
161     private NodeIdentifier transform(final NodeIdentifier name) {
162         final QName original = name.getNodeType();
163         final QName transformed = transform(original);
164         return transformed == original ? name : new NodeIdentifier(transformed);
165     }
166
167     private <T> NodeWithValue<T> transform(final NodeWithValue<T> name) {
168         final QName original = name.getNodeType();
169         final QName transformed = transform(original);
170         return transformed == original ? name : new NodeWithValue<>(transformed, name.getValue());
171     }
172
173     private NodeIdentifierWithPredicates transform(final NodeIdentifierWithPredicates identifier) {
174         Map<QName, Object> keyValues = new HashMap<>();
175         for (Map.Entry<QName, Object> original : identifier.entrySet()) {
176             keyValues.put(transform(original.getKey()), original.getValue());
177         }
178         return NodeIdentifierWithPredicates.of(transform(identifier.getNodeType()), keyValues);
179     }
180 }