Skip to content

Commit af1f59a

Browse files
authored
#1130: improve using variable FAIL_ON_AMBIGOUS_MERGE incl. documentation and test (#1158)
1 parent 10254a8 commit af1f59a

File tree

14 files changed

+99
-23
lines changed

14 files changed

+99
-23
lines changed

cli/src/main/java/com/devonfw/tools/ide/merge/DirectoryMerger.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
import com.devonfw.tools.ide.context.IdeContext;
1616
import com.devonfw.tools.ide.environment.EnvironmentVariables;
17-
import com.devonfw.tools.ide.merge.xmlmerger.XmlMerger;
17+
import com.devonfw.tools.ide.merge.xml.XmlMerger;
1818
import com.devonfw.tools.ide.util.FilenameUtil;
1919

2020
/**

cli/src/main/java/com/devonfw/tools/ide/merge/xmlmerger/XmlMergeDocument.java cli/src/main/java/com/devonfw/tools/ide/merge/xml/XmlMergeDocument.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.devonfw.tools.ide.merge.xmlmerger;
1+
package com.devonfw.tools.ide.merge.xml;
22

33
import java.nio.file.Path;
44

cli/src/main/java/com/devonfw/tools/ide/merge/xmlmerger/XmlMergeException.java cli/src/main/java/com/devonfw/tools/ide/merge/xml/XmlMergeException.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.devonfw.tools.ide.merge.xmlmerger;
1+
package com.devonfw.tools.ide.merge.xml;
22

33
/**
44
* {@link RuntimeException} for errors related to {@link XmlMerger}.

cli/src/main/java/com/devonfw/tools/ide/merge/xmlmerger/XmlMergeStrategy.java cli/src/main/java/com/devonfw/tools/ide/merge/xml/XmlMergeStrategy.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.devonfw.tools.ide.merge.xmlmerger;
1+
package com.devonfw.tools.ide.merge.xml;
22

33
import java.util.Locale;
44
import java.util.function.BiFunction;
@@ -9,7 +9,7 @@
99
import org.w3c.dom.Node;
1010
import org.w3c.dom.NodeList;
1111

12-
import com.devonfw.tools.ide.merge.xmlmerger.matcher.ElementMatcher;
12+
import com.devonfw.tools.ide.merge.xml.matcher.ElementMatcher;
1313

1414
/**
1515
* Enum of merge strategies for XML elements.

cli/src/main/java/com/devonfw/tools/ide/merge/xmlmerger/XmlMergeSupport.java cli/src/main/java/com/devonfw/tools/ide/merge/xml/XmlMergeSupport.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.devonfw.tools.ide.merge.xmlmerger;
1+
package com.devonfw.tools.ide.merge.xml;
22

33
import java.io.StringWriter;
44
import java.util.Objects;

cli/src/main/java/com/devonfw/tools/ide/merge/xmlmerger/XmlMerger.java cli/src/main/java/com/devonfw/tools/ide/merge/xml/XmlMerger.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.devonfw.tools.ide.merge.xmlmerger;
1+
package com.devonfw.tools.ide.merge.xml;
22

33
import java.io.BufferedWriter;
44
import java.io.InputStream;
@@ -24,7 +24,7 @@
2424
import com.devonfw.tools.ide.context.IdeContext;
2525
import com.devonfw.tools.ide.environment.EnvironmentVariables;
2626
import com.devonfw.tools.ide.merge.FileMerger;
27-
import com.devonfw.tools.ide.merge.xmlmerger.matcher.ElementMatcher;
27+
import com.devonfw.tools.ide.merge.xml.matcher.ElementMatcher;
2828

2929
/**
3030
* {@link FileMerger} for XML files.

cli/src/main/java/com/devonfw/tools/ide/merge/xmlmerger/matcher/ElementMatcher.java cli/src/main/java/com/devonfw/tools/ide/merge/xml/matcher/ElementMatcher.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.devonfw.tools.ide.merge.xmlmerger.matcher;
1+
package com.devonfw.tools.ide.merge.xml.matcher;
22

33
import java.util.HashMap;
44
import java.util.Map;
@@ -7,7 +7,7 @@
77
import org.w3c.dom.Element;
88

99
import com.devonfw.tools.ide.context.IdeContext;
10-
import com.devonfw.tools.ide.merge.xmlmerger.XmlMergeSupport;
10+
import com.devonfw.tools.ide.merge.xml.XmlMergeSupport;
1111

1212
/**
1313
* The ElementMatcher class is responsible for matching XML elements in a target document based on the provided update elements.

cli/src/main/java/com/devonfw/tools/ide/merge/xmlmerger/matcher/IdComputer.java cli/src/main/java/com/devonfw/tools/ide/merge/xml/matcher/IdComputer.java

+9-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.devonfw.tools.ide.merge.xmlmerger.matcher;
1+
package com.devonfw.tools.ide.merge.xml.matcher;
22

33
import javax.xml.xpath.XPath;
44
import javax.xml.xpath.XPathConstants;
@@ -10,23 +10,23 @@
1010
import org.w3c.dom.NodeList;
1111

1212
import com.devonfw.tools.ide.context.IdeContext;
13-
import com.devonfw.tools.ide.merge.xmlmerger.XmlMergeSupport;
13+
import com.devonfw.tools.ide.merge.xml.XmlMergeSupport;
1414

1515
/**
1616
* The IdComputer class is responsible for building XPath expressions and evaluating those expressions to match elements in a target document.
1717
*/
1818
public class IdComputer {
1919

20+
/** Name of the {@link com.devonfw.tools.ide.environment.EnvironmentVariables variable} to fail on ambiguous merge. */
21+
public static final String FAIL_ON_AMBIGOUS_MERGE = "FAIL_ON_AMBIGOUS_MERGE";
22+
2023
/** The value of merge:id that is used to evaluate the xpath expression. */
2124
private final String id;
2225

2326
private final IdeContext context;
2427

2528
private static final XPathFactory xPathFactory = XPathFactory.newInstance();
2629

27-
private final boolean throwExceptionOnMultipleMatches = Boolean.parseBoolean(System.getProperty("throwExceptionOnMultipleMatches", "false"));
28-
29-
3030
/**
3131
* The constructor.
3232
*
@@ -68,12 +68,11 @@ public Element evaluateExpression(Element templateElement, Element workspaceElem
6868
} else if (length == 0) {
6969
return null;
7070
} else {
71-
if (throwExceptionOnMultipleMatches) {
72-
throw new IllegalStateException(
73-
length + " matches found for XPath " + xpathExpr + " in workspace XML at " + XmlMergeSupport.getXPath(workspaceElement, true));
71+
String message = length + " matches found for XPath " + xpathExpr + " in workspace XML at " + XmlMergeSupport.getXPath(workspaceElement, true);
72+
if ("true".equals(this.context.getVariables().get(FAIL_ON_AMBIGOUS_MERGE))) {
73+
throw new IllegalStateException(message);
7474
} else {
75-
this.context.warning("Matches found: {} matches for XPath {} in workspace XML at {}",
76-
length, xpathExpr, XmlMergeSupport.getXPath(workspaceElement, true));
75+
this.context.warning(message);
7776
}
7877
return (Element) nodeList.item(0);
7978
}

cli/src/main/java/com/devonfw/tools/ide/merge/xmlmerger/matcher/NamespaceContextFromElement.java cli/src/main/java/com/devonfw/tools/ide/merge/xml/matcher/NamespaceContextFromElement.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.devonfw.tools.ide.merge.xmlmerger.matcher;
1+
package com.devonfw.tools.ide.merge.xml.matcher;
22

33
import java.util.Collections;
44
import java.util.Iterator;

cli/src/test/java/com/devonfw/tools/ide/merge/XmlMergerTest.java cli/src/test/java/com/devonfw/tools/ide/merge/xml/XmlMergerTest.java

+26-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.devonfw.tools.ide.merge;
1+
package com.devonfw.tools.ide.merge.xml;
22

33
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
44

@@ -7,6 +7,7 @@
77
import java.nio.file.Path;
88
import java.util.stream.Stream;
99

10+
import org.junit.jupiter.api.Test;
1011
import org.junit.jupiter.api.io.TempDir;
1112
import org.junit.jupiter.params.ParameterizedTest;
1213
import org.junit.jupiter.params.provider.MethodSource;
@@ -15,11 +16,11 @@
1516
import org.xmlunit.assertj3.XmlAssert;
1617

1718
import com.devonfw.tools.ide.context.AbstractIdeContextTest;
19+
import com.devonfw.tools.ide.context.IdeTestContext;
1820
import com.devonfw.tools.ide.context.IdeTestContextMock;
1921
import com.devonfw.tools.ide.environment.EnvironmentVariables;
2022
import com.devonfw.tools.ide.environment.EnvironmentVariablesPropertiesMock;
2123
import com.devonfw.tools.ide.environment.EnvironmentVariablesType;
22-
import com.devonfw.tools.ide.merge.xmlmerger.XmlMerger;
2324

2425
/**
2526
* Test of {@link XmlMerger}.
@@ -67,4 +68,27 @@ private static Stream<Path> xmlMergerTestCases() throws IOException {
6768

6869
return Files.list(XML_TEST_RESOURCES).filter(Files::isDirectory);
6970
}
71+
72+
@Test
73+
void testFailOnAmbiguousMerge(@TempDir Path tempDir) throws Exception {
74+
75+
// arrange
76+
IdeTestContext context = new IdeTestContext();
77+
EnvironmentVariables variables = context.getVariables();
78+
variables.getByType(EnvironmentVariablesType.CONF).set("FAIL_ON_AMBIGOUS_MERGE", "true");
79+
XmlMerger merger = new XmlMerger(context);
80+
Path folder = XML_TEST_RESOURCES.resolve("ambiguous-id");
81+
Path sourcePath = folder.resolve(SOURCE_XML);
82+
Path targetPath = tempDir.resolve(TARGET_XML);
83+
Files.copy(folder.resolve(TARGET_XML), targetPath, REPLACE_EXISTING);
84+
// act
85+
assertThatThrownBy(() -> {
86+
merger.doMerge(null, sourcePath, variables, targetPath);
87+
})
88+
// assert
89+
.hasRootCauseInstanceOf(IllegalStateException.class).hasRootCauseMessage(
90+
"2 matches found for XPath configuration[@default='true' and @type='JUnit'] in workspace XML at /project[@version='4']/component[@name='RunManager' @selected='Application.IDEasy']");
91+
;
92+
93+
}
7094
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project version="4">
3+
<component name="RunManager" selected="Application.IDEasy">
4+
<configuration default="true" type="JUnit" factoryName="JUnit">
5+
<shortenClasspath name="ARGS_FILE"/>
6+
<option name="METHOD_NAME" value=""/>
7+
<option name="TEST_OBJECT" value="class"/>
8+
<method v="2">
9+
<option name="Make" enabled="true"/>
10+
</method>
11+
</configuration>
12+
<!-- For our test we have this block duplicated -->
13+
<configuration default="true" type="JUnit" factoryName="JUnit">
14+
<shortenClasspath name="ARGS_FILE"/>
15+
<option name="METHOD_NAME" value=""/>
16+
<option name="TEST_OBJECT" value="class"/>
17+
</configuration>
18+
</component>
19+
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level"
20+
UseSingleDictionary="true" transferred="true"/>
21+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project version="4">
3+
<component name="RunManager" selected="Application.IDEasy">
4+
<configuration default="true" type="JUnit" factoryName="JUnit">
5+
<shortenClasspath name="broken"/>
6+
<option name="METHOD_NAME" value=""/>
7+
<option name="TEST_OBJECT" value="class"/>
8+
</configuration>
9+
<!-- For our test we have this block duplicated -->
10+
<configuration default="true" type="JUnit" factoryName="JUnit">
11+
<shortenClasspath name="ARGS_FILE"/>
12+
<option name="METHOD_NAME" value=""/>
13+
<option name="TEST_OBJECT" value="class"/>
14+
</configuration>
15+
</component>
16+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<project xmlns:merge="https://github.com/devonfw/IDEasy/merge" version="4">
3+
<component name="RunManager">
4+
<configuration default="true" type="JUnit" factoryName="JUnit" merge:id="configuration[@default='true' and @type='JUnit']">
5+
<shortenClasspath name="ARGS_FILE" merge:id="name()"/>
6+
<option name="METHOD_NAME" value=""/>
7+
<option name="TEST_OBJECT" value="class"/>
8+
<method v="2" merge:id="@v">
9+
<option name="Make" enabled="true"/>
10+
</method>
11+
</configuration>
12+
</component>
13+
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level"
14+
UseSingleDictionary="true" transferred="true"/>
15+
</project>

documentation/variables.adoc

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ Please note that we are trying to minimize any potential side-effect from `IDEas
3030
|*`IDE_VARIABLE_SYNTAX_LEGACY_SUPPORT_ENABLED`*|`true`|Enable/disable legacy support for devonfw-ide link:configurator.adoc[configuration templates] in IDE workspace folders.
3131
|`ECLIPSE_VMARGS`|`-Xms128M -Xmx768M -XX:MaxPermSize=256M`|JVM options for Eclipse
3232
|`PREFERRED_GIT_PROTOCOL`| |Allows to enforce a specific protocol for git. Options are `ssh` (for SSH) and `https`. If set any git URL will automatically be converted to the preferred protocol before IDEasy clones it. This option should only be set for individual users in `$IDE_HOME/conf/ide.properties` or `~/.ide/ide.properties` (and not in shared `settings`).
33+
|`FAIL_ON_AMBIGOUS_MERGE`| |If set to `true` the link:configurator.adoc#element-identification[merge:id] is ambiguous and the resulting XPath expression matches multiple elements. Typically the link:usage.adoc#admin[IDE admin] did something wrong in the workspace template configuration. However, we decided to log a warning if that happens and use the first match by default to prevent our users from being blocked or annoyed in case of such configuration error. With this property you can enforce that this is handled as error aborting the merge. If that happens the user sees the stacktrace of the error and gets asked if he want to continue in order to launch his IDE (IntelliJ, Eclipse, VSCode, etc.).
3334
|`«TOOL»_EDITION`|`«tool»`|The edition of the tool `«TOOL»` to install and use (e.g. `ECLIPSE_EDITION`, `INTELLIJ_EDITION` or `DOCKER_EDITION`). Default of `DOCKER_EDITION` is `rancher`.
3435
|`«TOOL»_VERSION`|`*`|The version of the tool `«TOOL»` to install and use (e.g. `ECLIPSE_VERSION` or `MVN_VERSION`).
3536
|`«TOOL»_BUILD_OPTS`| |The arguments provided to the build-tool `«TOOL»` in order to run a build. E.g.`clean install`

0 commit comments

Comments
 (0)