add low-level transformer support for changing catalogItemId

Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/e82c9a67
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/e82c9a67
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/e82c9a67

Branch: refs/heads/master
Commit: e82c9a672ee7cdc2ae4f80d2ffc32a1152f92a63
Parents: 5e1d94e
Author: Alex Heneveld <[email protected]>
Authored: Wed Jan 28 17:01:55 2015 +0000
Committer: Alex Heneveld <[email protected]>
Committed: Thu Jan 29 11:40:43 2015 +0000

----------------------------------------------------------------------
 .../rebind/transformer/CompoundTransformer.java | 59 ++++++++++++++-----
 .../transformer/CompoundTransformerLoader.java  | 13 ++++-
 .../CompoundTransformerLoaderTest.java          |  9 ++-
 .../transformer/CompoundTransformerTest.java    | 60 +++++++++++++++++++-
 4 files changed, 125 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e82c9a67/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformer.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformer.java
 
b/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformer.java
index 26f6af5..bb87783 100644
--- 
a/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformer.java
+++ 
b/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformer.java
@@ -34,10 +34,11 @@ import brooklyn.util.text.Strings;
 import brooklyn.util.text.TemplateProcessor;
 
 import com.google.common.annotations.Beta;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Multimap;
-import com.google.common.annotations.VisibleForTesting;
 
 @Beta
 public class CompoundTransformer {
@@ -119,34 +120,66 @@ public class CompoundTransformer {
                 + "</"+newValue+">"); 
         }
 
-        /** Changes the contents inside a "type" tag:
-         * where the contents match the old value, they are changed to the new 
value.
+        /** 
+         * Renames an explicit type name reference in brooklyn-xstream 
serialization.
+         * <p>
+         * Really this changes the contents inside any tag named "type",
+         * where the contents match the oldVal, they are changed to the newVal.
          * <p> 
-         * In brooklyn/xstream, a "type" node typically gives the name of a 
java or catalog type to be used
-         * when creating an instance. */
+         * In brooklyn-xstream, the "type" node typically gives the name of a 
java or catalog type to be used
+         * when creating an instance; that's how this works. 
+         */
         public Builder renameType(String oldVal, String newVal) {
             return 
xmlReplaceItem("type/text()[.='"+toXstreamClassnameFormat(oldVal)+"']", 
toXstreamClassnameFormat(newVal));
             // previously this did a more complex looping, essentially
             // <when 
.=oldVal>newVal</when><otherwise><apply-templates/></otherwise>
             // but i think these are equivalent
         }
-        /** Changes an XML tag matching a given old value:
+        /** 
+         * Renames an implicit class name reference (a tag).
+         * <p>
+         * Really this changes any XML tag matching a given old value;
          * the tag is changed to the new value.
          * <p>
-         * In xstream many tags correspond to the java class of an object so 
this is a way to change 
-         * the java class (or xstream alias) of a persisted instance (or 
instance inside them). */
+         * In brooklyn-xstream many tags correspond to the java class of an 
object;
+         * that's how this works to to change the java class (or xstream 
alias) 
+         * of a persisted instance, included nested instances. 
+         */
         public Builder renameClass(String oldVal, String newVal) {
             return xmlRenameTag(toXstreamClassnameFormat(oldVal), 
toXstreamClassnameFormat(newVal));
         }
-        /** Changes an XML tag inside another tag: 
-         * where the outer tag and inner tag match the values given here,
-         * the inner tag is changed to the new value.
+        /** 
+         * Renames a field in xstream serialization.
          * <p>
-         * In stream tags corresponding to fields are contained in the tag 
corresponding to the class name,
-         * so this gives a way to change the name of a field which will be 
deserialized. */
+         * Really this changes an XML tag inside another tag, 
+         * where the outer tag and inner tag match the clazz and oldVal values 
given here,
+         * the inner tag is changed to the newVal.
+         * <p>
+         * In brooklyn-xstream, tags corresponding to fields are contained in 
the tag 
+         * corresponding to the class name; that's how this works.
+         */
         public Builder renameField(String clazz, String oldVal, String newVal) 
{
             return 
xmlRenameTag(toXstreamClassnameFormat(clazz)+"/"+toXstreamClassnameFormat(oldVal),
 toXstreamClassnameFormat(newVal));
         }
+        /** Changes the contents of an XML tag 'catalogItemId' where the
+         * old text matches oldSymbolicName and optionally oldVersion
+         * to have newSymbolicName and newVersion. 
+         * <p>
+         * This provides a programmatic way to change the catalogItemID. */
+        public Builder changeCatalogItemId(String oldSymbolicName, String 
oldVersion,
+                String newSymbolicName, String newVersion) {
+            if (oldVersion==null)
+                return changeCatalogItemId(oldSymbolicName, newSymbolicName, 
newVersion);
+            // warnings use underscore notation because that's what 
CompoundTransformerLoader uses
+            return xmlReplaceItem("catalogItemId/text()[.='"+
+                Preconditions.checkNotNull(oldSymbolicName, 
"old_symbolic_name")+":"+Preconditions.checkNotNull(oldVersion, 
"old_version")+"']", 
+                Preconditions.checkNotNull(newSymbolicName, 
"new_symbolic_name")+":"+Preconditions.checkNotNull(newVersion, "new_version"));
+        }
+        /** As {@link #changeCatalogItemId(String, String, String, String)} 
matching any old version. */
+        public Builder changeCatalogItemId(String oldSymbolicName, String 
newSymbolicName, String newVersion) {
+            return 
xmlReplaceItem("catalogItemId/text()[starts-with(.,'"+Preconditions.checkNotNull(oldSymbolicName,
 "old_symbolic_name")+":')]", 
+                Preconditions.checkNotNull(newSymbolicName, 
"new_symbolic_name")+":"+Preconditions.checkNotNull(newVersion, "new_version"));
+        }
 
         private String toXstreamClassnameFormat(String val) {
             // xstream format for inner classes is like 
<brooklyn.entity.rebind.transformer.CompoundTransformerTest_-OrigType>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e82c9a67/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoader.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoader.java
 
b/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoader.java
index 9d3cac1..3465709 100644
--- 
a/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoader.java
+++ 
b/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoader.java
@@ -62,13 +62,17 @@ public class CompoundTransformerLoader {
             String oldVal = (String) args.get("old_val");
             String newVal = (String) args.get("new_val");
             builder.renameField(clazz, oldVal, newVal);
+        } else if (name.equals("catalogItemId")) {
+            builder.changeCatalogItemId(
+                (String) args.get("old_symbolic_name"), 
checkString(args.get("old_version"), "old_version"),
+                (String) args.get("new_symbolic_name"), 
checkString(args.get("new_version"), "new_version"));
         } else if (name.equals("xslt")) {
             String url = (String) args.get("url");
             @SuppressWarnings("unchecked")
             Map<String,?> substitutions = (Map<String, ?>) 
args.get("substitutions");
             String xsltTemplate = 
ResourceUtils.create(CompoundTransformer.class).getResourceAsString(url);
             String xslt = 
TemplateProcessor.processTemplateContents(xsltTemplate, substitutions == null ? 
ImmutableMap.<String, String>of() : substitutions);
-            // TODO pass XSLT-style parameters instead, maybe?  that's more 
normal, 
+            // we could pass XSLT-style parameters instead, maybe?  that's 
more normal, 
             // but OTOH freemarker is maybe more powerful, given our other 
support there
             builder.xsltTransformer(xslt);
         } else if (name.equals("rawDataTransformer")) {
@@ -83,4 +87,11 @@ public class CompoundTransformerLoader {
             throw new IllegalStateException("Unsupported transform '"+name+"' 
("+args+")");
         }
     }
+
+    private static String checkString(Object object, String name) {
+        if (object!=null && !(object instanceof String)) {
+            throw new IllegalArgumentException("Argument '"+name+"' must be a 
string; numbers may need explicit quoting in YAML.");
+        }
+        return (String) object;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e82c9a67/core/src/test/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoaderTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoaderTest.java
 
b/core/src/test/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoaderTest.java
index 454e860..d55e073 100644
--- 
a/core/src/test/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoaderTest.java
+++ 
b/core/src/test/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoaderTest.java
@@ -44,6 +44,12 @@ public class CompoundTransformerLoaderTest {
                 "  class_name: myclassname\n"+
                 "  old_val: myoldname\n"+
                 "  new_val: mynewname\n"+
+                // low-level mechanism to change catalogItemId; used (and 
tested) by higher-level methods
+                // which use symbolic_name:version notation to avoid the 
unpleasant need for yaml quotes
+                "catalogItemId:\n"+
+                "  old_symbolic_name: myclassname\n"+
+                "  new_symbolic_name: myclassname\n"+
+                "  new_version: '2.0'\n"+
                 "xslt:\n"+
                 "  url: 
classpath://brooklyn/entity/rebind/transformer/impl/renameType.xslt\n"+
                 "  substitutions:\n"+
@@ -58,7 +64,8 @@ public class CompoundTransformerLoaderTest {
         assertTrue(Iterables.get(rawDataTransformers, 1) instanceof 
XsltTransformer);
         assertTrue(Iterables.get(rawDataTransformers, 2) instanceof 
XsltTransformer);
         assertTrue(Iterables.get(rawDataTransformers, 3) instanceof 
XsltTransformer);
-        assertTrue(Iterables.get(rawDataTransformers, 4) instanceof 
MyRawDataTransformer);
+        assertTrue(Iterables.get(rawDataTransformers, 4) instanceof 
XsltTransformer);
+        assertTrue(Iterables.get(rawDataTransformers, 5) instanceof 
MyRawDataTransformer);
     }
     
     public static class MyRawDataTransformer implements RawDataTransformer {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e82c9a67/core/src/test/java/brooklyn/entity/rebind/transformer/CompoundTransformerTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/brooklyn/entity/rebind/transformer/CompoundTransformerTest.java
 
b/core/src/test/java/brooklyn/entity/rebind/transformer/CompoundTransformerTest.java
index 49c1005..db3cbc2 100644
--- 
a/core/src/test/java/brooklyn/entity/rebind/transformer/CompoundTransformerTest.java
+++ 
b/core/src/test/java/brooklyn/entity/rebind/transformer/CompoundTransformerTest.java
@@ -294,7 +294,65 @@ public class CompoundTransformerTest extends 
RebindTestFixtureWithApp {
         
         assertSingleXmlTransformation(transformer, input, expected);
     }
-    
+
+    @Test
+    public void testChangeCatalogItemIdExplicitVersionInXml() throws Exception 
{
+        CompoundTransformer transformer = CompoundTransformer.builder()
+            .changeCatalogItemId("foo", "1.0", "bar", "2.0")
+            .build();
+
+        String input = 
+                "<entity myattrib=\"myval\">"+NEWLINE+
+                "  <catalogItemId>foo:1.0</catalogItemId>"+NEWLINE+
+                "  <config>ignore</config>"+NEWLINE+
+                "</entity>";
+        String expected = 
+            "<entity myattrib=\"myval\">"+NEWLINE+
+            "  <catalogItemId>bar:2.0</catalogItemId>"+NEWLINE+
+            "  <config>ignore</config>"+NEWLINE+
+            "</entity>";
+        
+        assertSingleXmlTransformation(transformer, input, expected);
+    }
+    @Test
+    public void testChangeCatalogItemIdExplicitVersionNonMatchInXml() throws 
Exception {
+        CompoundTransformer transformer = CompoundTransformer.builder()
+            .changeCatalogItemId("foo", "1.0", "bar", "2.0")
+            .build();
+
+        String input = 
+                "<entity myattrib=\"myval\">"+NEWLINE+
+                "  <catalogItemId>foo:1.1</catalogItemId>"+NEWLINE+
+                "  <config>ignore</config>"+NEWLINE+
+                "</entity>";
+        String expected = 
+            "<entity myattrib=\"myval\">"+NEWLINE+
+            "  <catalogItemId>foo:1.1</catalogItemId>"+NEWLINE+
+            "  <config>ignore</config>"+NEWLINE+
+            "</entity>";
+        
+        assertSingleXmlTransformation(transformer, input, expected);
+    }
+    @Test
+    public void testChangeCatalogItemIdAnyVersionInXml() throws Exception {
+        CompoundTransformer transformer = CompoundTransformer.builder()
+            .changeCatalogItemId("foo", "bar", "2.0")
+            .build();
+
+        String input = 
+                "<entity myattrib=\"myval\">"+NEWLINE+
+                "  <catalogItemId>foo:1.2</catalogItemId>"+NEWLINE+
+                "  <config>ignore</config>"+NEWLINE+
+                "</entity>";
+        String expected = 
+            "<entity myattrib=\"myval\">"+NEWLINE+
+            "  <catalogItemId>bar:2.0</catalogItemId>"+NEWLINE+
+            "  <config>ignore</config>"+NEWLINE+
+            "</entity>";
+        
+        assertSingleXmlTransformation(transformer, input, expected);
+    }
+
     protected TestApplication transformAndRebind(CompoundTransformer 
transformer) throws Exception {
         RebindTestUtils.waitForPersisted(origApp);
         BrooklynMementoRawData newRawData = transform(origManagementContext, 
transformer);

Reply via email to