Transform QName value in identity leaf
[yangtools.git] / yang / yang-data-transform / src / main / java / org / opendaylight / yangtools / transform / QNameTransformingStreamWriter.java
index 0085ae061b15b78f830ce310b13a714d29a19efc..7a838f515f05018a66fbea56371bb17bf2168d16 100644 (file)
@@ -7,33 +7,31 @@
  */
 package org.opendaylight.yangtools.transform;
 
-import com.google.common.base.Function;
-import com.google.common.collect.ForwardingObject;
 import com.google.common.collect.ImmutableSet;
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
-import javax.annotation.Nonnull;
+import java.util.function.Function;
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.ForwardingNormalizedNodeStreamWriter;
 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
 
 /**
- *
  * Stateless Normalized Node Stream Writer decorator, which performs QName translation.
  *
+ * <p>
  * This class serves as base for Normalized Node Stream Writer decorators with option to transform
  * QNames by user-implemented {@link #transform(QName)} function.
- *
  */
-public abstract class QNameTransformingStreamWriter extends ForwardingObject implements NormalizedNodeStreamWriter {
+public abstract class QNameTransformingStreamWriter extends ForwardingNormalizedNodeStreamWriter {
 
     // FIXME: Probably use loading cache to decrease memory
-    @Override
-    protected abstract NormalizedNodeStreamWriter delegate();
 
     /**
      * Returns decorator, which uses supplied function to transform QNames.
@@ -49,21 +47,18 @@ public abstract class QNameTransformingStreamWriter extends ForwardingObject imp
 
             @Override
             protected NormalizedNodeStreamWriter delegate() {
-              return delegate;
+                return delegate;
             }
 
             @Override
             protected QName transform(final QName key) {
                 return transformation.apply(key);
             }
-
         };
     }
 
     /**
-     * Returns decorator, which uses supplied map to transform QNames.
-     *
-     * QNames not present in map are left unchanged.
+     * Returns decorator, which uses supplied map to transform QNames. QNames not present in map are left unchanged.
      *
      * @param delegate Underlying normalized node stream writer
      * @param mapping Immutable map which represent mapping from original to new values.
@@ -75,9 +70,8 @@ public abstract class QNameTransformingStreamWriter extends ForwardingObject imp
     }
 
     /**
-     * Returns decorator, which uses supplied map to transform QNameModules.
-     *
-     * QNameModules not present in map are left unchanged.
+     * Returns decorator, which uses supplied map to transform QNameModules. QNameModules not present in map are left
+     * unchanged.
      *
      * @param delegate Underlying normalized node stream writer
      * @param mapping Immutable map which represent mapping from original to new values.
@@ -88,95 +82,99 @@ public abstract class QNameTransformingStreamWriter extends ForwardingObject imp
         return fromFunction(delegate, new QNameModuleReplacementFunction(mapping));
     }
 
-    /**
-     * Transforms a QName to new mapping.
-     *
-     * NOTE: If QName should be unchanged implementation needs to return original QName.
-     *
-     * @param key QName to transform.
-     * @return Returns new value of QName.
-     */
-    protected abstract @Nonnull QName transform(@Nonnull QName key);
-
     @Override
-    public void leafNode(final NodeIdentifier name, final Object value) throws IOException, IllegalArgumentException {
-        delegate().leafNode(transform(name), value);
+    public void startLeafNode(final NodeIdentifier name) throws IOException {
+        super.startLeafNode(transform(name));
     }
 
     @Override
-    public void startLeafSet(final NodeIdentifier name, final int childSizeHint) throws IOException, IllegalArgumentException {
-        delegate().startLeafSet(transform(name), childSizeHint);
+    public void startLeafSet(final NodeIdentifier name, final int childSizeHint) throws IOException {
+        super.startLeafSet(transform(name), childSizeHint);
     }
 
     @Override
-    public void leafSetEntryNode(final Object value) throws IOException, IllegalArgumentException {
-        delegate().leafSetEntryNode(value);
+    public void startOrderedLeafSet(final NodeIdentifier name, final int childSizeHint) throws IOException {
+        super.startOrderedLeafSet(transform(name), childSizeHint);
     }
 
     @Override
-    public void startContainerNode(final NodeIdentifier name, final int childSizeHint) throws IOException, IllegalArgumentException {
-        delegate().startContainerNode(transform(name), childSizeHint);
+    public void startLeafSetEntryNode(final NodeWithValue<?> name) throws IOException {
+        super.startLeafSetEntryNode(transform(name));
     }
 
     @Override
-    public void startUnkeyedList(final NodeIdentifier name, final int childSizeHint) throws IOException, IllegalArgumentException {
-        delegate().startUnkeyedList(transform(name), childSizeHint);
+    public void startContainerNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
+        super.startContainerNode(transform(name), childSizeHint);
     }
 
     @Override
-    public void startUnkeyedListItem(final NodeIdentifier name, final int childSizeHint) throws IOException, IllegalStateException {
-        delegate().startUnkeyedListItem(transform(name), childSizeHint);
+    public void startUnkeyedList(final NodeIdentifier name, final int childSizeHint) throws IOException {
+        super.startUnkeyedList(transform(name), childSizeHint);
     }
 
     @Override
-    public void startMapNode(final NodeIdentifier name, final int childSizeHint) throws IOException, IllegalArgumentException {
-        delegate().startMapNode(transform(name), childSizeHint);
+    public void startUnkeyedListItem(final NodeIdentifier name, final int childSizeHint) throws IOException {
+        super.startUnkeyedListItem(transform(name), childSizeHint);
     }
 
     @Override
-    public void startMapEntryNode(final NodeIdentifierWithPredicates identifier, final int childSizeHint) throws IOException,
-            IllegalArgumentException {
-        delegate().startMapEntryNode(transform(identifier), childSizeHint);
+    public void startMapNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
+        super.startMapNode(transform(name), childSizeHint);
     }
 
     @Override
-    public void startOrderedMapNode(final NodeIdentifier name, final int childSizeHint) throws IOException,
-            IllegalArgumentException {
-        delegate().startOrderedMapNode(transform(name), childSizeHint);
+    public void startMapEntryNode(final NodeIdentifierWithPredicates identifier, final int childSizeHint)
+            throws IOException {
+        super.startMapEntryNode(transform(identifier), childSizeHint);
     }
 
     @Override
-    public void startChoiceNode(final NodeIdentifier name, final int childSizeHint) throws IOException, IllegalArgumentException {
-        delegate().startChoiceNode(transform(name), childSizeHint);
+    public void startOrderedMapNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
+        super.startOrderedMapNode(transform(name), childSizeHint);
     }
 
     @Override
-    public void startAugmentationNode(final AugmentationIdentifier identifier) throws IOException, IllegalArgumentException {
-        delegate().startAugmentationNode(transform(identifier));
+    public void startChoiceNode(final NodeIdentifier name, final int childSizeHint) throws IOException {
+        super.startChoiceNode(transform(name), childSizeHint);
     }
 
     @Override
-    public void anyxmlNode(final NodeIdentifier name, final Object value) throws IOException, IllegalArgumentException {
-        delegate().anyxmlNode(transform(name), value);
+    public void startAugmentationNode(final AugmentationIdentifier identifier) throws IOException {
+        super.startAugmentationNode(transform(identifier));
     }
 
     @Override
-    public void endNode() throws IOException, IllegalStateException {
-        delegate().endNode();
+    public boolean startAnyxmlNode(final NodeIdentifier name, final Class<?> objectModel) throws IOException {
+        return super.startAnyxmlNode(transform(name), objectModel);
     }
 
     @Override
-    public void close() throws IOException {
-        delegate().close();
+    public void scalarValue(final Object value) throws IOException {
+        // identityref leaf nodes contain identity QName as a value - it needs to be transformed
+        super.scalarValue(value instanceof QName ? transform((QName) value) : value);
     }
 
-    @Override
-    public void flush() throws IOException {
-        delegate().flush();
-    }
+    /**
+     * Transforms a QName to new mapping.
+     *
+     * <p>
+     * NOTE: If QName should be unchanged implementation needs to return original QName.
+     *
+     * @param key QName to transform.
+     * @return Returns new value of QName.
+     */
+    protected abstract @NonNull QName transform(@NonNull QName key);
 
     private NodeIdentifier transform(final NodeIdentifier name) {
-        return new NodeIdentifier(transform(name.getNodeType()));
+        final QName original = name.getNodeType();
+        final QName transformed = transform(original);
+        return transformed == original ? name : new NodeIdentifier(transformed);
+    }
+
+    private <T> NodeWithValue<T> transform(final NodeWithValue<T> name) {
+        final QName original = name.getNodeType();
+        final QName transformed = transform(original);
+        return transformed == original ? name : new NodeWithValue<>(transformed, name.getValue());
     }
 
     private AugmentationIdentifier transform(final AugmentationIdentifier identifier) {
@@ -189,9 +187,9 @@ public abstract class QNameTransformingStreamWriter extends ForwardingObject imp
 
     private NodeIdentifierWithPredicates transform(final NodeIdentifierWithPredicates identifier) {
         Map<QName, Object> keyValues = new HashMap<>();
-        for (Map.Entry<QName, Object> original : identifier.getKeyValues().entrySet()) {
+        for (Map.Entry<QName, Object> original : identifier.entrySet()) {
             keyValues.put(transform(original.getKey()), original.getValue());
         }
-        return new NodeIdentifierWithPredicates(transform(identifier.getNodeType()), keyValues);
+        return NodeIdentifierWithPredicates.of(transform(identifier.getNodeType()), keyValues);
     }
 }