Repository: incubator-brooklyn Updated Branches: refs/heads/master eab2d3999 -> 40edb8b51
Improve state transformers * Accept a list of single key-value maps so one file can contain multiple actions with same name * When renaming a class replace the new name in the class tag, type element, class attribute Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/596bc528 Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/596bc528 Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/596bc528 Branch: refs/heads/master Commit: 596bc528aa99023600ffdce2890b13346835b42a Parents: eab2d39 Author: Svetoslav Neykov <[email protected]> Authored: Tue Feb 24 15:54:26 2015 +0200 Committer: Svetoslav Neykov <[email protected]> Committed: Tue Feb 24 16:15:20 2015 +0200 ---------------------------------------------------------------------- .../rebind/transformer/CompoundTransformer.java | 23 +++++++++- .../transformer/CompoundTransformerLoader.java | 20 +++++++-- .../CompoundTransformerLoaderTest.java | 42 ++++++++--------- .../transformer/CompoundTransformerTest.java | 47 ++++++++++++++++++-- 4 files changed, 101 insertions(+), 31 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/596bc528/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 bb87783..550a80c 100644 --- a/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformer.java +++ b/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformer.java @@ -114,11 +114,18 @@ public class CompoundTransformer { * Replaces a tag, but while continuing to recurse. */ public Builder xmlRenameTag(String xpathToMatch, String newValue) { - return xmlReplaceItem(xpathToMatch, + return xmlReplaceItem(xpathToMatch, "<"+newValue+">" + "<xsl:apply-templates select=\"@*|node()\" />" + "</"+newValue+">"); } + + public Builder xmlChangeAttribute(String xpathToMatch, String newValue) { + return xmlReplaceItem(xpathToMatch, + "<xsl:attribute name='{local-name()}'>" + + newValue + + "</xsl:attribute>"); + } /** * Renames an explicit type name reference in brooklyn-xstream serialization. @@ -145,7 +152,7 @@ public class CompoundTransformer { * 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) { + public Builder renameClassTag(String oldVal, String newVal) { return xmlRenameTag(toXstreamClassnameFormat(oldVal), toXstreamClassnameFormat(newVal)); } /** @@ -181,6 +188,18 @@ public class CompoundTransformer { Preconditions.checkNotNull(newSymbolicName, "new_symbolic_name")+":"+Preconditions.checkNotNull(newVersion, "new_version")); } + /** + * Updates all references to a class to a new value + * @param oldName the old name of the class + * @param newName the new name of the class to be used instead + */ + public Builder renameClass(String oldName, String newName) { + return renameClassTag(oldName, newName) + .xmlChangeAttribute("//@class[.='" + oldName + "']", newName) + .renameType(oldName, newName); + //TODO update reference attributes + } + private String toXstreamClassnameFormat(String val) { // xstream format for inner classes is like <brooklyn.entity.rebind.transformer.CompoundTransformerTest_-OrigType> return (val.contains("$")) ? val.replace("$", "_-") : val; http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/596bc528/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 3465709..8a2d4bb 100644 --- a/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoader.java +++ b/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoader.java @@ -18,7 +18,12 @@ */ package brooklyn.entity.rebind.transformer; +import java.util.Collection; import java.util.Map; +import java.util.Map.Entry; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import brooklyn.entity.rebind.transformer.CompoundTransformer.Builder; import brooklyn.util.ResourceUtils; @@ -32,6 +37,7 @@ import com.google.common.collect.Iterables; @Beta public class CompoundTransformerLoader { + private static final Logger LOG = LoggerFactory.getLogger(CompoundTransformerLoader.class); // TODO Improve error handing so get nicer errors. // TODO Improve names (e.g. always camel case?) @@ -40,11 +46,13 @@ public class CompoundTransformerLoader { public static CompoundTransformer load(String contents) { CompoundTransformer.Builder builder = CompoundTransformer.builder(); Iterable<Object> toplevel = Yamls.parseAll(contents); - @SuppressWarnings("unchecked") - Map<String, Map<?,?>> rules = (Map<String, Map<?,?>>) ((Map<?,?>)Iterables.getOnlyElement(toplevel)); - for (Map.Entry<String, Map<?,?>> entry : rules.entrySet()) { - addRule(builder, entry.getKey(), entry.getValue()); + Collection<?> rules = (Collection<?>)Iterables.getOnlyElement(toplevel); + for (Object obj : rules) { + Map<?, ?> map = (Map<?, ?>)obj; + Entry<?, ?> entry = Iterables.getOnlyElement(map.entrySet()); + addRule(builder, (String)entry.getKey(), (Map<?, ?>)entry.getValue()); } + LOG.info("Loaded " + rules.size() + " transforms"); return builder.build(); } @@ -53,6 +61,10 @@ public class CompoundTransformerLoader { String oldVal = (String) args.get("old_val"); String newVal = (String) args.get("new_val"); builder.renameClass(oldVal, newVal); + } else if (name.equals("renameClassTag")) { + String oldVal = (String) args.get("old_val"); + String newVal = (String) args.get("new_val"); + builder.renameClassTag(oldVal, newVal); } else if (name.equals("renameType")) { String oldVal = (String) args.get("old_val"); String newVal = (String) args.get("new_val"); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/596bc528/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 d55e073..b23f1bd 100644 --- a/core/src/test/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoaderTest.java +++ b/core/src/test/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoaderTest.java @@ -34,29 +34,29 @@ public class CompoundTransformerLoaderTest { @Test public void testLoadsTransformerFromYaml() throws Exception { String contents = - "renameType:\n"+ - " old_val: myoldname\n"+ - " new_val: mynewname\n"+ - "renameClass:\n"+ - " old_val: myoldname\n"+ - " new_val: mynewname\n"+ - "renameField:\n"+ - " 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"+ + "- renameType:\n"+ + " old_val: myoldname\n"+ + " new_val: mynewname\n"+ + "- renameClassTag:\n"+ " old_val: myoldname\n"+ " new_val: mynewname\n"+ - "rawDataTransformer:\n"+ - " type: "+MyRawDataTransformer.class.getName()+"\n"; + "- renameField:\n"+ + " 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"+ + " old_val: myoldname\n"+ + " new_val: mynewname\n"+ + "- rawDataTransformer:\n"+ + " type: "+MyRawDataTransformer.class.getName()+"\n"; CompoundTransformer transformer = CompoundTransformerLoader.load(contents); Collection<RawDataTransformer> rawDataTransformers = transformer.getRawDataTransformers().get(BrooklynObjectType.ENTITY); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/596bc528/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 db3cbc2..50e31bf 100644 --- a/core/src/test/java/brooklyn/entity/rebind/transformer/CompoundTransformerTest.java +++ b/core/src/test/java/brooklyn/entity/rebind/transformer/CompoundTransformerTest.java @@ -57,6 +57,7 @@ import brooklyn.util.os.Os; import com.google.common.base.Objects; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; +import com.google.common.collect.Multimap; @SuppressWarnings("serial") public class CompoundTransformerTest extends RebindTestFixtureWithApp { @@ -148,6 +149,14 @@ public class CompoundTransformerTest extends RebindTestFixtureWithApp { Assert.assertEquals(xmlOutActual, xmlOutExpected); } + protected void assertXmlTransformation(CompoundTransformer transformer, String xmlIn, String xmlOutExpected) throws Exception { + BrooklynMementoRawData rawData = BrooklynMementoRawData.builder() + .entity("test", xmlIn) + .build(); + BrooklynMementoRawData rawDataOut = transformer.transform(rawData); + Assert.assertEquals(rawDataOut.getEntities().get("test"), xmlOutExpected); + } + @Test public void testNoopTransformation() throws Exception { CompoundTransformer transformer = CompoundTransformer.builder() @@ -166,7 +175,7 @@ public class CompoundTransformerTest extends RebindTestFixtureWithApp { origApp.setConfig(CONF1, new OrigType("myfieldval")); CompoundTransformer transformer = CompoundTransformer.builder() - .renameClass(OrigType.class.getName(), RenamedType.class.getName()) + .renameClassTag(OrigType.class.getName(), RenamedType.class.getName()) .build(); newApp = transformAndRebind(transformer); @@ -183,7 +192,7 @@ public class CompoundTransformerTest extends RebindTestFixtureWithApp { origApp.setConfig(CONF1, origPredicate); CompoundTransformer transformer = CompoundTransformer.builder() - .renameClass(origPredicate.getClass().getName(), RenamedIdEqualToPredicate.class.getName()) + .renameClassTag(origPredicate.getClass().getName(), RenamedIdEqualToPredicate.class.getName()) .renameField(RenamedIdEqualToPredicate.class.getName(), "val$paramVal", "val") .build(); @@ -266,9 +275,9 @@ public class CompoundTransformerTest extends RebindTestFixtureWithApp { } @Test - public void testRenameClassInXml() throws Exception { + public void testRenameClassTagInXml() throws Exception { CompoundTransformer transformer = CompoundTransformer.builder() - .renameClass("MyClassBefore", "MyClassAfter") + .renameClassTag("MyClassBefore", "MyClassAfter") .build(); String input = @@ -296,6 +305,36 @@ public class CompoundTransformerTest extends RebindTestFixtureWithApp { } @Test + public void testRenameClassInXml() throws Exception { + CompoundTransformer transformer = CompoundTransformer.builder() + .renameClass("MyClassBefore", "MyClassAfter") + .build(); + + String input = + "<entity myattrib=\"myval\">"+NEWLINE+ + " <type myattrib2=\"myval2\">MyClassBefore</type>"+NEWLINE+ + " <config>"+NEWLINE+ + " <test.conf1 class=\"MyClassBefore\">"+NEWLINE+ + " <MyClassBefore>"+NEWLINE+ + " </MyClassBefore>"+NEWLINE+ + " </test.conf1>"+NEWLINE+ + " </config>"+NEWLINE+ + "</entity>"; + String expected = + "<entity myattrib=\"myval\">"+NEWLINE+ + " <type myattrib2=\"myval2\">MyClassAfter</type>"+NEWLINE+ + " <config>"+NEWLINE+ + " <test.conf1 class=\"MyClassAfter\">"+NEWLINE+ + " <MyClassAfter>"+NEWLINE+ + " </MyClassAfter>"+NEWLINE+ + " </test.conf1>"+NEWLINE+ + " </config>"+NEWLINE+ + "</entity>"; + + assertXmlTransformation(transformer, input, expected); + } + + @Test public void testChangeCatalogItemIdExplicitVersionInXml() throws Exception { CompoundTransformer transformer = CompoundTransformer.builder() .changeCatalogItemId("foo", "1.0", "bar", "2.0")
