Add merge feature to override
authorMathieu Baudier <mbaudier@argeo.org>
Fri, 12 Sep 2008 13:42:32 +0000 (13:42 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Fri, 12 Sep 2008 13:42:32 +0000 (13:42 +0000)
git-svn-id: https://svn.argeo.org/slc/trunk@1590 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

15 files changed:
org.argeo.slc.agent/src/main/java/org/argeo/slc/ant/AntExecutionContext.java
org.argeo.slc.agent/src/main/java/org/argeo/slc/ant/deploy/SlcDeployTask.java
org.argeo.slc.agent/src/main/java/org/argeo/slc/ant/spring/ListArg.java [new file with mode: 0644]
org.argeo.slc.agent/src/main/java/org/argeo/slc/ant/spring/MapArg.java
org.argeo.slc.agent/src/main/java/org/argeo/slc/ant/spring/OverrideArg.java
org.argeo.slc.agent/src/main/java/org/argeo/slc/ant/spring/SpringArg.java
org.argeo.slc.agent/src/main/java/org/argeo/slc/ant/spring/SpringRegister.java
org.argeo.slc.agent/src/main/java/org/argeo/slc/ant/structure/SAwareTask.java
org.argeo.slc.agent/src/main/java/org/argeo/slc/ant/test/SlcCloseTestResultTask.java
org.argeo.slc.agent/src/main/java/org/argeo/slc/ant/test/SlcTestTask.java
org.argeo.slc.agent/src/main/java/org/argeo/slc/ant/unit/MinimalAntClasspathTestCase.java
org.argeo.slc.agent/src/test/java/org/argeo/slc/ant/DummyObject.java [new file with mode: 0644]
org.argeo.slc.agent/src/test/java/org/argeo/slc/ant/OverrideTest.java [new file with mode: 0644]
org.argeo.slc.agent/src/test/resources/org/argeo/slc/ant/acOverride.xml [new file with mode: 0644]
org.argeo.slc.agent/src/test/resources/org/argeo/slc/ant/buildOverride.xml [new file with mode: 0644]

index a010e7fad14cff66c84696e75adee3c5aca08ecf..75bfd340ecf0cc9bc65a2ef3d0e99ed81d5c5322 100644 (file)
@@ -18,6 +18,10 @@ public class AntExecutionContext implements SlcExecutionContext {
                return (T) context.getBean(name);
        }
 
+       public <T> T getAntRef(String antId) {
+               return (T) project.getReference(antId);
+       }
+
        public SlcExecution getSlcExecution() {
                return (SlcExecution) project
                                .getReference(AntConstants.REF_SLC_EXECUTION);
index e6d42db9aed3f68bdb21490680f7652fcafcf4bf..2055e3b66b9ca2d095f9511217d29b1202bb8f12 100644 (file)
@@ -27,17 +27,17 @@ public class SlcDeployTask extends SAwareTask {
 \r
                // set overridden references\r
                if (distributionArg != null) {\r
-                       deployment.setDistribution(distributionArg.getBeanInstance());\r
+                       deployment.setDistribution(distributionArg.getInstance());\r
                        log.trace("Overrides distribution");\r
                }\r
 \r
                if (deploymentDataArg != null) {\r
-                       deployment.setDeploymentData(deploymentDataArg.getBeanInstance());\r
+                       deployment.setDeploymentData(deploymentDataArg.getInstance());\r
                        log.trace("Overrides deployment data");\r
                }\r
 \r
                if (targetDataArg != null) {\r
-                       deployment.setTargetData(targetDataArg.getBeanInstance());\r
+                       deployment.setTargetData(targetDataArg.getInstance());\r
                        log.trace("Overrides target data");\r
                }\r
 \r
diff --git a/org.argeo.slc.agent/src/main/java/org/argeo/slc/ant/spring/ListArg.java b/org.argeo.slc.agent/src/main/java/org/argeo/slc/ant/spring/ListArg.java
new file mode 100644 (file)
index 0000000..7c270ee
--- /dev/null
@@ -0,0 +1,37 @@
+package org.argeo.slc.ant.spring;
+
+import java.util.List;
+import java.util.Vector;
+
+import org.argeo.slc.core.SlcException;
+
+/** List of overrides */
+public class ListArg {
+       private List<OverrideArg> list = new Vector<OverrideArg>();
+
+       /** Creates override sub tag. */
+       public OverrideArg createOverride() {
+               OverrideArg overrideArg = new OverrideArg();
+               list.add(overrideArg);
+               return overrideArg;
+       }
+
+       /** Gets as list of objects. */
+       public List<Object> getAsObjectList(List<Object> originalList) {
+               if (originalList != null && originalList.size() != list.size()) {
+                       throw new SlcException("Cannot merge lists of different sizes.");
+               }
+
+               List<Object> objectList = new Vector<Object>(list.size());
+
+               for (int i = 0; i < list.size(); i++) {
+                       OverrideArg arg = list.get(i);
+
+                       if (originalList != null)
+                               arg.setOriginal(originalList.get(i));
+
+                       objectList.add(arg.getObject());
+               }
+               return objectList;
+       }
+}
index eb45276448b7ce9b49a897e592b1245deb3b2a23..6f53994fe10ccf7f9dfc27b4c650d171d49b75b8 100644 (file)
@@ -19,17 +19,33 @@ public class MapArg {
                return arg;\r
        }\r
 \r
-       public Map<String, Object> getMap() {\r
-               if (map.size() == 0) {\r
-                       for (EntryArg arg : entries) {\r
-                               String key = arg.getKey();\r
-                               if (map.containsKey(key)) {\r
-                                       throw new SlcException("Key '" + key + "' already set.");\r
-                               } else {\r
-                                       map.put(key, arg.getValueStr());\r
-                               }\r
+       public Map<String, Object> getAsObjectMap(Map<String, Object> originalMap) {\r
+               Map<String, Object> objectMap = new TreeMap<String, Object>();\r
+               for (EntryArg arg : entries) {\r
+                       String key = arg.getKey();\r
+\r
+                       if (objectMap.containsKey(key)) {\r
+                               throw new SlcException("Key '" + key + "' already set.");\r
                        }\r
+\r
+                       if (originalMap != null && originalMap.containsKey(key)\r
+                                       && arg.getOverrideArg() != null)\r
+                               arg.getOverrideArg().setOriginal(originalMap.get(key));\r
+\r
+                       objectMap.put(key, arg.getObject());\r
+\r
                }\r
+               return objectMap;\r
+       }\r
+\r
+       /**\r
+        * Returns a cached reference if it was already called. This reference could\r
+        * have been modified externally and thus not anymore be in line with the\r
+        * configuration.\r
+        */\r
+       public Map<String, Object> getMap() {\r
+               if (map.size() == 0)\r
+                       map = getAsObjectMap(null);\r
                return map;\r
        }\r
 \r
@@ -46,7 +62,7 @@ public class MapArg {
                        this.key = key;\r
                }\r
 \r
-               public Object getValueStr() {\r
+               public Object getObject() {\r
                        if (overrideArg != null) {\r
                                return overrideArg.getObject();\r
                        } else if (valueStr != null) {\r
@@ -72,5 +88,10 @@ public class MapArg {
                                throw new BuildException("Value already set");\r
                        }\r
                }\r
+\r
+               public OverrideArg getOverrideArg() {\r
+                       return overrideArg;\r
+               }\r
+\r
        }\r
 }\r
index 6bd66ef7c512df24b984d697a08e5363639f5eda..645b59204cebf0d8edc9884b41815f6e16d885b1 100644 (file)
@@ -1,17 +1,23 @@
 package org.argeo.slc.ant.spring;\r
 \r
 import java.util.List;\r
-import java.util.Vector;\r
+import java.util.Map;\r
 \r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
 import org.apache.tools.ant.BuildException;\r
 \r
 /** Ant type allowing to override bean properties. */\r
 public class OverrideArg extends SpringArg<Object> {\r
+       private final static Log log = LogFactory.getLog(OverrideArg.class);\r
+\r
        private String name;\r
        private Object value;\r
-       private OverrideList overrideList;\r
+       private ListArg overrideList;\r
        private MapArg overrideMap;\r
 \r
+       private Boolean merge = false;\r
+\r
        /** The name of the property to override. */\r
        public String getName() {\r
                return name;\r
@@ -35,9 +41,9 @@ public class OverrideArg extends SpringArg<Object> {
        }\r
 \r
        /** Creates override list sub tag. */\r
-       public OverrideList createList() {\r
+       public ListArg createList() {\r
                checkValueAlreadySet();\r
-               overrideList = new OverrideList();\r
+               overrideList = new ListArg();\r
                return overrideList;\r
        }\r
 \r
@@ -53,13 +59,25 @@ public class OverrideArg extends SpringArg<Object> {
         */\r
        public Object getObject() {\r
                if (value != null) {\r
+                       if (log.isTraceEnabled())\r
+                               log.trace(this + "\t: Returns override object as value");\r
                        return value;\r
-               } else if (getBean() != null || getAntref() != null) {\r
-                       return getBeanInstance();\r
+               } else if (getBean() != null\r
+                               || getAntref() != null\r
+                               // works on original if no collection is defined\r
+                               || (getOriginal() != null && overrideList == null && overrideMap == null)) {\r
+                       if (log.isTraceEnabled())\r
+                               log.trace(this + "\t: Returns override object as instance");\r
+                       return getInstance();\r
                } else if (overrideList != null) {\r
-                       return overrideList.getAsObjectList();\r
+                       if (log.isTraceEnabled())\r
+                               log.trace(this + "\t: Returns override object as list");\r
+                       return overrideList.getAsObjectList((List<Object>) getOriginal());\r
                } else if (overrideMap != null) {\r
-                       return overrideMap.getMap();\r
+                       if (log.isTraceEnabled())\r
+                               log.trace(this + "\t: Returns override object as map");\r
+                       return overrideMap\r
+                                       .getAsObjectMap((Map<String, Object>) getOriginal());\r
                } else {\r
                        throw new BuildException("Value or bean not set.");\r
                }\r
@@ -68,28 +86,18 @@ public class OverrideArg extends SpringArg<Object> {
        protected void checkValueAlreadySet() {\r
                super.checkValueAlreadySet();\r
                if (value != null || overrideList != null || overrideMap != null) {\r
-                       throw new BuildException("Value already set.");\r
+                       if (!getMerge()) {\r
+                               throw new BuildException("Value already set.");\r
+                       }\r
                }\r
        }\r
 \r
-       /** List of overrides */\r
-       protected class OverrideList {\r
-               private List<OverrideArg> list = new Vector<OverrideArg>();\r
-\r
-               /** Creates override sub tag. */\r
-               public OverrideArg createOverride() {\r
-                       OverrideArg overrideArg = new OverrideArg();\r
-                       list.add(overrideArg);\r
-                       return overrideArg;\r
-               }\r
+       public Boolean getMerge() {\r
+               return merge;\r
+       }\r
 \r
-               /** Gets as list of objects. */\r
-               public List<Object> getAsObjectList() {\r
-                       List<Object> objectList = new Vector<Object>();\r
-                       for (OverrideArg arg : list) {\r
-                               objectList.add(arg.getObject());\r
-                       }\r
-                       return objectList;\r
-               }\r
+       public void setMerge(Boolean merge) {\r
+               this.merge = merge;\r
        }\r
+\r
 }\r
index c84c96567d80d0df8e7e9a9558e09277db91fca5..3f3bb3c1d126ebfb4d9878f665b97aed4ffef095 100644 (file)
@@ -3,7 +3,8 @@ package org.argeo.slc.ant.spring;
 import java.util.List;\r
 import java.util.Vector;\r
 \r
-import org.apache.tools.ant.BuildException;\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
 import org.apache.tools.ant.types.DataType;\r
 import org.argeo.slc.ant.AntConstants;\r
 import org.argeo.slc.core.SlcException;\r
@@ -14,13 +15,20 @@ import org.springframework.context.ApplicationContext;
 \r
 /** Abstract Ant type wrapping a Spring bean. */\r
 public class SpringArg<T> extends DataType {\r
+       private final static Log log = LogFactory.getLog(SpringArg.class);\r
+\r
        private List<OverrideArg> overrides = new Vector<OverrideArg>();\r
 \r
        private String bean;\r
        private String antref;\r
+       /**\r
+        * Reference to the original object, used to merge overrides. <b>this object\r
+        * will be modified</b>.\r
+        */\r
+       private T original;\r
 \r
        // cache bean instance to avoid reading it twice if it is a prototype\r
-       private T beanInstance = null;\r
+       private T instance = null;\r
 \r
        /** The <u>name</u> of the underlying bean, as set through the attribute. */\r
        public String getBean() {\r
@@ -47,35 +55,43 @@ public class SpringArg<T> extends DataType {
         * Retrieve the instance of the bean, and sets the overridden properties.\r
         * <b>The value is cached.</b>\r
         */\r
-       public T getBeanInstance() {\r
-               if (beanInstance == null) {\r
+       public T getInstance() {\r
+               if (instance == null) {\r
+                       if (log.isTraceEnabled())\r
+                               log.trace(this + "\t: Creates instance");\r
+\r
                        if (bean != null) {\r
-                               beanInstance = (T) getContext().getBean(bean);\r
-                               if (beanInstance == null)\r
+                               instance = (T) getContext().getBean(bean);\r
+                               if (instance == null)\r
                                        throw new SlcException("No object found for Spring bean "\r
                                                        + bean);\r
                        } else if (antref != null) {\r
-                               beanInstance = (T) getProject().getReference(antref);\r
-                               if (beanInstance == null)\r
+                               instance = (T) getProject().getReference(antref);\r
+                               if (instance == null)\r
                                        throw new SlcException("No object found for Ant reference "\r
                                                        + antref);\r
+                       } else if (original != null) {\r
+                               instance = original;\r
                        } else {\r
                                throw new SlcException(\r
                                                "Don't know how to retrieve bean instance");\r
                        }\r
 \r
-                       setOverridenProperties(beanInstance);\r
+                       setOverridenProperties(instance);\r
 \r
                        // FIXME: why are we doing this? Could not find any object using it\r
-                       if (beanInstance instanceof InitializingBean) {\r
+                       if (instance instanceof InitializingBean) {\r
                                try {\r
-                                       ((InitializingBean) beanInstance).afterPropertiesSet();\r
+                                       ((InitializingBean) instance).afterPropertiesSet();\r
                                } catch (Exception e) {\r
                                        throw new SlcException("Could not initialize bean", e);\r
                                }\r
                        }\r
+               } else {\r
+                       if (log.isTraceEnabled())\r
+                               log.trace(this + "\t: Returns cached instance");\r
                }\r
-               return beanInstance;\r
+               return instance;\r
        }\r
 \r
        protected void setOverridenProperties(Object obj) {\r
@@ -86,8 +102,16 @@ public class SpringArg<T> extends DataType {
                                                "The name of the property to override has to be set.");\r
                        }\r
 \r
-                       // LogFactory.getLog(getClass()).debug(\r
-                       // "Prop " + override.getName());\r
+                       if (log.isTraceEnabled())\r
+                               log.trace(this + "\t: Overrides property " + override.getName()\r
+                                               + " with " + override);\r
+\r
+                       if (override.getMerge() == true) {\r
+                               // if override is marked as merged retrieve the value and set is\r
+                               // as original\r
+                               override.setOriginal(wrapper.getPropertyValue(override\r
+                                               .getName()));\r
+                       }\r
                        wrapper.setPropertyValue(override.getName(), override.getObject());\r
                }\r
 \r
@@ -107,9 +131,33 @@ public class SpringArg<T> extends DataType {
        }\r
 \r
        protected void checkValueAlreadySet() {\r
-               if (antref != null || bean != null) {\r
-                       throw new BuildException("Value already set.");\r
+               if (antref != null || bean != null || original != null) {\r
+                       throw new SlcException("Instance value already defined.");\r
                }\r
        }\r
 \r
+       public void setOriginal(T original) {\r
+               checkValueAlreadySet();\r
+               this.original = original;\r
+       }\r
+\r
+       public T getOriginal() {\r
+               return original;\r
+       }\r
+\r
+       @Override\r
+       public String toString() {\r
+               StringBuffer buf = new StringBuffer(getClass().getSimpleName());\r
+               if (bean != null) {\r
+                       buf.append("#bean=").append(bean);\r
+               } else if (antref != null) {\r
+                       buf.append("#antref=").append(antref);\r
+               } else if (original != null) {\r
+                       buf.append("#orig=").append(original.hashCode());\r
+               } else {\r
+                       buf.append("#noid");\r
+               }\r
+               buf.append("#").append(hashCode());\r
+               return buf.toString();\r
+       }\r
 }\r
index c550e3d4ec825412a81ddc9d58b64463a7aef7b0..a7d88f254f225745079a711302e456670b4779ea 100644 (file)
@@ -15,7 +15,7 @@ public class SpringRegister extends AbstractSpringTask {
        @Override
        public void execute() throws BuildException {
                for (BeanArg bean : beans) {
-                       Object instance = bean.getBeanInstance();
+                       Object instance = bean.getInstance();
                        if (bean.getAntid() != null) {
                                getProject().addReference(bean.getAntid(), instance);
                        } else {
index 343db96444868e3f4743de3dddb3d519b9f60105..134b2c1506e47fbaf0ae7d569e0e9c3b5ccb6b33 100644 (file)
@@ -82,7 +82,7 @@ public abstract class SAwareTask extends AbstractSpringTask {
 \r
                // notify registered args\r
                for (SpringArg arg : sAwareArgs) {\r
-                       Object obj = arg.getBeanInstance();\r
+                       Object obj = arg.getInstance();\r
 \r
                        if (obj instanceof StructureAware) {\r
                                StructureAware<TreeSPath> sAwareT = (StructureAware<TreeSPath>) obj;\r
@@ -155,6 +155,6 @@ public abstract class SAwareTask extends AbstractSpringTask {
 \r
 class StructureElementArg extends SpringArg {\r
        public StructureElement getStructureElement() {\r
-               return (StructureElement) getBeanInstance();\r
+               return (StructureElement) getInstance();\r
        }\r
 }
\ No newline at end of file
index 9eeb1e0cf81fdbed2783b7fc6eb888cae16bde0a..7aab47597b48c896df3e1447f180e84f9b3ce3e4 100644 (file)
@@ -22,7 +22,7 @@ public class SlcCloseTestResultTask extends SAwareTask {
                if (!mode.equals(StructureRegistry.READ)) {\r
                        for (SpringArg<TestResult> result : results) {\r
                                try {\r
-                                       result.getBeanInstance().close();\r
+                                       result.getInstance().close();\r
                                } catch (RuntimeException e) {\r
                                        log.error("Could not close result "\r
                                                        + (result.getBean() != null ? result.getBean()\r
index 66bda639b1b59b25c22c43c8434ee17d3b107873..fa22269c222487a7c7c2de514a64531277aaa0b3 100644 (file)
@@ -67,22 +67,22 @@ public class SlcTestTask extends SAwareTask {
 \r
                // set overridden references\r
                if (testDataArg != null) {\r
-                       testRun.setTestData(testDataArg.getBeanInstance());\r
+                       testRun.setTestData(testDataArg.getInstance());\r
                        log.trace("Overrides test data");\r
                }\r
 \r
                if (testDefinitionArg != null) {\r
-                       testRun.setTestDefinition(testDefinitionArg.getBeanInstance());\r
+                       testRun.setTestDefinition(testDefinitionArg.getInstance());\r
                        log.trace("Overrides test definition");\r
                }\r
 \r
                if (deployedSystemArg != null) {\r
-                       testRun.setDeployedSystem(deployedSystemArg.getBeanInstance());\r
+                       testRun.setDeployedSystem(deployedSystemArg.getInstance());\r
                        log.trace("Overrides deployed system");\r
                }\r
 \r
                if (testResultArg != null) {\r
-                       testRun.setTestResult(testResultArg.getBeanInstance());\r
+                       testRun.setTestResult(testResultArg.getInstance());\r
                        log.trace("Overrides test result");\r
                }\r
 \r
index e86887e249ef70d2b3e485675eecb1080f5cb559..bf6c0b603da303add6d37d3d7041018f15fb6c46 100644 (file)
@@ -4,12 +4,15 @@ import java.io.File;
 import java.util.UUID;
 
 import org.argeo.slc.ant.AntConstants;
+import org.argeo.slc.ant.AntExecutionContext;
 import org.argeo.slc.ant.AntSlcApplication;
 import org.argeo.slc.core.process.SlcExecution;
+import org.argeo.slc.runtime.SlcExecutionOutput;
 import org.argeo.slc.unit.AbstractSpringTestCase;
 import org.springframework.core.io.FileSystemResource;
 
-public class MinimalAntClasspathTestCase extends AbstractSpringTestCase {
+public class MinimalAntClasspathTestCase extends AbstractSpringTestCase
+               implements SlcExecutionOutput<AntExecutionContext> {
        protected void execute(String scriptPath) {
                AntSlcApplication slcApp = new AntSlcApplication();
                slcApp.setRootDir(new FileSystemResource(new File("src/test/resources")
@@ -24,7 +27,11 @@ public class MinimalAntClasspathTestCase extends AbstractSpringTestCase {
                                scriptPath);
                slcExecution.setUser("user");
 
-               slcApp.execute(slcExecution, null, null, null);
+               slcApp.execute(slcExecution, null, null, this);
+       }
+
+       /** to be overridden */
+       public void postExecution(AntExecutionContext executionContext) {
        }
 
 }
diff --git a/org.argeo.slc.agent/src/test/java/org/argeo/slc/ant/DummyObject.java b/org.argeo.slc.agent/src/test/java/org/argeo/slc/ant/DummyObject.java
new file mode 100644 (file)
index 0000000..5998760
--- /dev/null
@@ -0,0 +1,55 @@
+package org.argeo.slc.ant;
+
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.Vector;
+
+public class DummyObject {
+       private String name;
+       private Long value;
+       private DummyObject other;
+       private List<DummyObject> children = new Vector<DummyObject>();
+       private Map<String, DummyObject> map = new TreeMap<String, DummyObject>();
+
+       public String getName() {
+               return name;
+       }
+
+       public void setName(String name) {
+               this.name = name;
+       }
+
+       public Long getValue() {
+               return value;
+       }
+
+       public void setValue(Long value) {
+               this.value = value;
+       }
+
+       public DummyObject getOther() {
+               return other;
+       }
+
+       public void setOther(DummyObject other) {
+               this.other = other;
+       }
+
+       public List<DummyObject> getChildren() {
+               return children;
+       }
+
+       public void setChildren(List<DummyObject> children) {
+               this.children = children;
+       }
+
+       public Map<String, DummyObject> getMap() {
+               return map;
+       }
+
+       public void setMap(Map<String, DummyObject> map) {
+               this.map = map;
+       }
+
+}
diff --git a/org.argeo.slc.agent/src/test/java/org/argeo/slc/ant/OverrideTest.java b/org.argeo.slc.agent/src/test/java/org/argeo/slc/ant/OverrideTest.java
new file mode 100644 (file)
index 0000000..d49521a
--- /dev/null
@@ -0,0 +1,64 @@
+package org.argeo.slc.ant;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.ant.unit.MinimalAntClasspathTestCase;
+
+public class OverrideTest extends MinimalAntClasspathTestCase {
+       private Log log = LogFactory.getLog(getClass());
+
+       public void testSimpleRun() {
+               execute("/org/argeo/slc/ant/buildOverride.xml");
+       }
+
+       @Override
+       public void postExecution(AntExecutionContext executionContext) {
+               log.info("Analyzing context after execution...");
+
+               DummyObject dummy1UnModified = executionContext
+                               .getAntRef("dummy1.unmodified");
+               assertEquals("dummy2", dummy1UnModified.getOther().getName());
+               assertEquals(2, dummy1UnModified.getChildren().size());
+               assertEquals(2, dummy1UnModified.getMap().size());
+
+               DummyObject dummy1Modif1 = executionContext.getAntRef("dummy1.modif1");
+               assertEquals("dummy1.modif1", dummy1Modif1.getName());
+               assertEquals("dummy3", dummy1Modif1.getOther().getName());
+
+               DummyObject dummy1Modif2 = executionContext.getAntRef("dummy1.modif2");
+               assertEquals(1, dummy1Modif2.getChildren().size());
+               assertEquals("dummy3", dummy1Modif2.getChildren().get(0).getName());
+
+               DummyObject dummy1Modif3 = executionContext.getAntRef("dummy1.modif3");
+               assertEquals(2, dummy1Modif3.getChildren().size());
+               assertEquals("dummy3", dummy1Modif3.getChildren().get(0).getName());
+               assertEquals("dummy2", dummy1Modif3.getChildren().get(1).getName());
+
+               DummyObject dummy1Modif4 = executionContext.getAntRef("dummy1.modif4");
+               assertEquals(2, dummy1Modif4.getChildren().size());
+               assertEquals("dummy3", dummy1Modif4.getChildren().get(0).getName());
+               assertEquals("dummy1.modif1", dummy1Modif4.getChildren().get(0)
+                               .getOther().getName());
+               assertEquals("dummy2", dummy1Modif4.getChildren().get(1).getName());
+               assertEquals(1, dummy1Modif4.getChildren().get(1).getChildren().size());
+               assertEquals("dummy3", dummy1Modif4.getChildren().get(1).getChildren()
+                               .get(0).getName());
+
+               DummyObject dummy1Modif5 = executionContext.getAntRef("dummy1.modif5");
+               assertEquals(2, dummy1Modif5.getMap().size());
+               assertEquals("dummy3", dummy1Modif5.getMap().get("key1").getName());
+               assertEquals("dummy2", dummy1Modif5.getMap().get("key2").getName());
+               
+               DummyObject dummy1Modif6 = executionContext.getAntRef("dummy1.modif6");
+               assertEquals(2, dummy1Modif6.getMap().size());
+               assertEquals("dummy2.merged", dummy1Modif6.getMap().get("key1").getName());
+               assertEquals("dummy3.merged", dummy1Modif6.getMap().get("key2").getName());
+               
+       }
+
+       @Override
+       protected String getApplicationContextLocation() {
+               return inPackage("acOverride.xml");
+       }
+
+}
diff --git a/org.argeo.slc.agent/src/test/resources/org/argeo/slc/ant/acOverride.xml b/org.argeo.slc.agent/src/test/resources/org/argeo/slc/ant/acOverride.xml
new file mode 100644 (file)
index 0000000..c9c3911
--- /dev/null
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+
+       <bean id="dummy1" parent="template.dummy" scope="prototype">
+               <property name="name" value="dummy1" />
+               <property name="other" ref="dummy2" />
+               <property name="children">
+                       <list>
+                               <ref bean="dummy2" />
+                               <ref bean="dummy3" />
+                       </list>
+               </property>
+               <property name="map">
+                       <map>
+                               <entry key="key1">
+                                       <ref bean="dummy2" />
+                               </entry>
+                               <entry key="key2">
+                                       <ref bean="dummy3" />
+                               </entry>
+                       </map>
+               </property>
+       </bean>
+
+       <bean id="dummy2" parent="template.dummy" scope="prototype">
+               <property name="name" value="dummy2" />
+       </bean>
+
+       <bean id="dummy3" parent="template.dummy" scope="prototype">
+               <property name="name" value="dummy3" />
+       </bean>
+
+       <!-- Templates -->
+       <bean id="template.dummy" class="org.argeo.slc.ant.DummyObject"
+               abstract="true">
+       </bean>
+
+
+
+</beans>
\ No newline at end of file
diff --git a/org.argeo.slc.agent/src/test/resources/org/argeo/slc/ant/buildOverride.xml b/org.argeo.slc.agent/src/test/resources/org/argeo/slc/ant/buildOverride.xml
new file mode 100644 (file)
index 0000000..67f889a
--- /dev/null
@@ -0,0 +1,77 @@
+<project default="test">\r
+\r
+       <target name="test">\r
+               <slc.register>
+                       <object antid="dummy1.unmodified" bean="dummy1" />
+                       <object antid="dummy1.modif1" bean="dummy1">
+                               <override name="name" value="dummy1.modif1" />
+                               <override name="other" bean="dummy3" />
+                       </object>
+                       <object antid="dummy1.modif2" bean="dummy1">
+                               <override name="children">
+                                       <list>
+                                               <override bean="dummy3" />
+                                       </list>
+                               </override>
+                       </object>
+                       <object antid="dummy1.modif3" bean="dummy1">
+                               <override name="children" merge="true">
+                                       <list>
+                                               <override>
+                                                       <override name="name" value="dummy3" />
+                                               </override>
+                                               <override>
+                                                       <override name="name" value="dummy2" />
+                                               </override>
+                                       </list>
+                               </override>
+                       </object>
+                       <object antid="dummy1.modif4" bean="dummy1">
+                               <override name="children" merge="true">
+                                       <list>
+                                               <override>
+                                                       <override name="name" value="dummy3" />
+                                                       <override name="other" antref="dummy1.modif1" />
+                                               </override>
+                                               <override>
+                                                       <override name="name" value="dummy2" />
+                                                       <override name="children">
+                                                               <list>
+                                                                       <override bean="dummy3" />
+                                                               </list>
+                                                       </override>
+                                               </override>
+                                       </list>
+                               </override>
+                       </object>
+                       <object antid="dummy1.modif5" bean="dummy1">
+                               <override name="map">
+                                       <map>
+                                               <entry key="key1">
+                                                       <override bean="dummy3" />
+                                               </entry>
+                                               <entry key="key2">
+                                                       <override bean="dummy2" />
+                                               </entry>
+                                       </map>
+                               </override>
+                       </object>
+                       <object antid="dummy1.modif6" bean="dummy1">
+                               <override name="map" merge="true">
+                                       <map>
+                                               <entry key="key1">
+                                                       <override>
+                                                               <override name="name" value="dummy2.merged" />
+                                                       </override>
+                                               </entry>
+                                               <entry key="key2">
+                                                       <override>
+                                                               <override name="name" value="dummy3.merged" />
+                                                       </override>
+                                               </entry>
+                                       </map>
+                               </override>
+                       </object>
+               </slc.register>\r
+       </target>\r
+</project>
\ No newline at end of file