2 * Copyright (c) 2015 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.yangtools.transform;
10 import com.google.common.collect.ImmutableSet;
11 import java.io.IOException;
12 import java.util.HashMap;
14 import java.util.function.Function;
15 import org.eclipse.jdt.annotation.NonNull;
16 import org.opendaylight.yangtools.yang.common.QName;
17 import org.opendaylight.yangtools.yang.common.QNameModule;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
22 import org.opendaylight.yangtools.yang.data.api.schema.stream.ForwardingNormalizedNodeStreamWriter;
23 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
26 * Stateless Normalized Node Stream Writer decorator, which performs QName translation.
29 * This class serves as base for Normalized Node Stream Writer decorators with option to transform
30 * QNames by user-implemented {@link #transform(QName)} function.
32 public abstract class QNameTransformingStreamWriter extends ForwardingNormalizedNodeStreamWriter {
34 // FIXME: Probably use loading cache to decrease memory
37 * Returns decorator, which uses supplied function to transform QNames.
39 * @param delegate Underlying normalized node stream writer
40 * @param transformation Transformation function, function is required to return non-null
42 * @return decorator, which uses supplied function to transform QNames.
44 public static NormalizedNodeStreamWriter fromFunction(final NormalizedNodeStreamWriter delegate,
45 final Function<QName, QName> transformation) {
46 return new QNameTransformingStreamWriter() {
49 protected NormalizedNodeStreamWriter delegate() {
54 protected QName transform(final QName key) {
55 return transformation.apply(key);
61 * Returns decorator, which uses supplied map to transform QNames. QNames not present in map are left unchanged.
63 * @param delegate Underlying normalized node stream writer
64 * @param mapping Immutable map which represent mapping from original to new values.
65 * @return decorator, which uses supplied mapping to transform QNames.
67 public static NormalizedNodeStreamWriter createQNameReplacing(final NormalizedNodeStreamWriter delegate,
68 final Map<QName, QName> mapping) {
69 return fromFunction(delegate, new QNameReplacementFunction(mapping));
73 * Returns decorator, which uses supplied map to transform QNameModules. QNameModules not present in map are left
76 * @param delegate Underlying normalized node stream writer
77 * @param mapping Immutable map which represent mapping from original to new values.
78 * @return decorator, which uses supplied mapping to transform QNameModules.
80 public static NormalizedNodeStreamWriter createQNameModuleReplacing(final NormalizedNodeStreamWriter delegate,
81 final Map<QNameModule, QNameModule> mapping) {
82 return fromFunction(delegate, new QNameModuleReplacementFunction(mapping));
86 public void startLeafNode(final NodeIdentifier name) throws IOException {
87 super.startLeafNode(transform(name));
91 public void startLeafSet(final NodeIdentifier name, final int childSizeHint) throws IOException {
92 super.startLeafSet(transform(name), childSizeHint);
96 public void startOrderedLeafSet(final NodeIdentifier name, final int childSizeHint) throws IOException {
97 super.startOrderedLeafSet(transform(name), childSizeHint);
101 public void startLeafSetEntryNode(final NodeWithValue<?> name) throws IOException {
102 super.startLeafSetEntryNode(transform(name));
106 public void startContainerNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
107 super.startContainerNode(transform(name), childSizeHint);
111 public void startUnkeyedList(final NodeIdentifier name, final int childSizeHint) throws IOException {
112 super.startUnkeyedList(transform(name), childSizeHint);
116 public void startUnkeyedListItem(final NodeIdentifier name, final int childSizeHint) throws IOException {
117 super.startUnkeyedListItem(transform(name), childSizeHint);
121 public void startMapNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
122 super.startMapNode(transform(name), childSizeHint);
126 public void startMapEntryNode(final NodeIdentifierWithPredicates identifier, final int childSizeHint)
128 super.startMapEntryNode(transform(identifier), childSizeHint);
132 public void startOrderedMapNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
133 super.startOrderedMapNode(transform(name), childSizeHint);
137 public void startChoiceNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
138 super.startChoiceNode(transform(name), childSizeHint);
142 public void startAugmentationNode(final AugmentationIdentifier identifier) throws IOException {
143 super.startAugmentationNode(transform(identifier));
147 public boolean startAnyxmlNode(final NodeIdentifier name, final Class<?> objectModel) throws IOException {
148 return super.startAnyxmlNode(transform(name), objectModel);
152 public void startYangModeledAnyXmlNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
153 super.startYangModeledAnyXmlNode(transform(name), childSizeHint);
157 public void scalarValue(final Object value) throws IOException {
158 // identityref leaf nodes contain identity QName as a value - it needs to be transformed
159 super.scalarValue(value instanceof QName ? transform((QName) value) : value);
163 * Transforms a QName to new mapping.
166 * NOTE: If QName should be unchanged implementation needs to return original QName.
168 * @param key QName to transform.
169 * @return Returns new value of QName.
171 protected abstract @NonNull QName transform(@NonNull QName key);
173 private NodeIdentifier transform(final NodeIdentifier name) {
174 final QName original = name.getNodeType();
175 final QName transformed = transform(original);
176 return transformed == original ? name : new NodeIdentifier(transformed);
179 private <T> NodeWithValue<T> transform(final NodeWithValue<T> name) {
180 final QName original = name.getNodeType();
181 final QName transformed = transform(original);
182 return transformed == original ? name : new NodeWithValue<>(transformed, name.getValue());
185 private AugmentationIdentifier transform(final AugmentationIdentifier identifier) {
186 ImmutableSet.Builder<QName> builder = ImmutableSet.builder();
187 for (QName original : identifier.getPossibleChildNames()) {
188 builder.add(transform(original));
190 return new AugmentationIdentifier(builder.build());
193 private NodeIdentifierWithPredicates transform(final NodeIdentifierWithPredicates identifier) {
194 Map<QName, Object> keyValues = new HashMap<>();
195 for (Map.Entry<QName, Object> original : identifier.entrySet()) {
196 keyValues.put(transform(original.getKey()), original.getValue());
198 return NodeIdentifierWithPredicates.of(transform(identifier.getNodeType()), keyValues);