Skip to content

Commit 30b98e9

Browse files
alfeilexhohwille
andauthored
#1037: Fix devonfw-ide compatibility with XML templates (#1212)
Co-authored-by: Jörg Hohwiller <hohwille@users.noreply.github.com>
1 parent 9f839b2 commit 30b98e9

File tree

10 files changed

+117
-2
lines changed

10 files changed

+117
-2
lines changed

CHANGELOG.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ This file documents all notable changes to https://github.com/devonfw/IDEasy[IDE
66

77
Release with new features and bugfixes:
88

9+
* https://github.com/devonfw/IDEasy/issues/1037[#1037]: Add devonfw-ide legacy support for merging XML templates without namespace
910
* https://github.com/devonfw/IDEasy/issues/1217[#1217]: Remove plugin recommendation feature in VSCode
1011
* https://github.com/devonfw/IDEasy/issues/1243[#1243]: Fix display of ide status although errors might occur
1112
* https://github.com/devonfw/IDEasy/issues/1233[#1233]: Fix dropdown width in MSI installer for drive selection

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

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.devonfw.tools.ide.environment.EnvironmentVariables;
2626
import com.devonfw.tools.ide.merge.FileMerger;
2727
import com.devonfw.tools.ide.merge.xml.matcher.ElementMatcher;
28+
import com.devonfw.tools.ide.variable.IdeVariables;
2829

2930
/**
3031
* {@link FileMerger} for XML files.
@@ -35,6 +36,8 @@ public class XmlMerger extends FileMerger implements XmlMergeSupport {
3536

3637
private static final TransformerFactory TRANSFORMER_FACTORY;
3738

39+
protected final boolean legacyXmlSupport;
40+
3841
/** The namespace URI for this XML merger. */
3942
public static final String MERGE_NS_URI = "https://github.com/devonfw/IDEasy/merge";
4043

@@ -57,6 +60,7 @@ public class XmlMerger extends FileMerger implements XmlMergeSupport {
5760
public XmlMerger(IdeContext context) {
5861

5962
super(context);
63+
this.legacyXmlSupport = Boolean.TRUE.equals(IdeVariables.IDE_XML_MERGE_LEGACY_SUPPORT_ENABLED.get(context));
6064
}
6165

6266
@Override
@@ -79,7 +83,7 @@ protected void doMerge(Path setup, Path update, EnvironmentVariables resolver, P
7983
if (workspaceDocument == null) {
8084
resultDocument = templateDocument.getDocument();
8185
} else {
82-
resultDocument = merge(templateDocument, workspaceDocument);
86+
resultDocument = merge(templateDocument, workspaceDocument, workspaceFileExists);
8387
if ((resultDocument == null) && !workspaceFileExists) {
8488
// if the merge failed due to incompatible roots and we have no workspace file
8589
// then at least we should take the resolved setup file as result
@@ -102,9 +106,10 @@ protected void doMerge(Path setup, Path update, EnvironmentVariables resolver, P
102106
* @param templateDocument the {@link XmlMergeDocument} representing the template xml file from the settings.
103107
* @param workspaceDocument the {@link XmlMergeDocument} of the actual source XML file (typically from the workspace of the real IDE) to merge with the
104108
* {@code templateDocument}.
109+
* @param workspaceFileExists indicates whether the workspace document already exists or if setup templates are loaded
105110
* @return the merged {@link Document}.
106111
*/
107-
public Document merge(XmlMergeDocument templateDocument, XmlMergeDocument workspaceDocument) {
112+
public Document merge(XmlMergeDocument templateDocument, XmlMergeDocument workspaceDocument, boolean workspaceFileExists) {
108113

109114
Document resultDocument;
110115
Path source = templateDocument.getPath();
@@ -119,6 +124,19 @@ public Document merge(XmlMergeDocument templateDocument, XmlMergeDocument worksp
119124
if (strategy == null) {
120125
strategy = XmlMergeStrategy.COMBINE; // default strategy used as fallback
121126
}
127+
if (templateRoot.lookupPrefix(MERGE_NS_URI) == null) {
128+
if (this.legacyXmlSupport) {
129+
if (workspaceFileExists) {
130+
strategy = XmlMergeStrategy.OVERRIDE;
131+
} else {
132+
strategy = XmlMergeStrategy.KEEP;
133+
}
134+
} else {
135+
this.context.warning(
136+
"XML merge namespace not found. If you are working in a legacy devonfw-ide project, please set IDE_XML_MERGE_LEGACY_SUPPORT_ENABLED=true to "
137+
+ "proceed correctly.");
138+
}
139+
}
122140
ElementMatcher elementMatcher = new ElementMatcher(this.context);
123141
strategy.merge(templateRoot, workspaceRoot, elementMatcher);
124142
resultDocument = workspaceDocument.getDocument();

cli/src/main/java/com/devonfw/tools/ide/variable/IdeVariables.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@ public interface IdeVariables {
8484
VariableDefinitionBoolean IDE_VARIABLE_SYNTAX_LEGACY_SUPPORT_ENABLED = new VariableDefinitionBoolean("IDE_VARIABLE_SYNTAX_LEGACY_SUPPORT_ENABLED", null,
8585
c -> Boolean.TRUE);
8686

87+
/**
88+
* {@link VariableDefinition} for support of legacy xml templates without XML merge namespace
89+
*/
90+
VariableDefinitionBoolean IDE_XML_MERGE_LEGACY_SUPPORT_ENABLED = new VariableDefinitionBoolean("IDE_XML_MERGE_LEGACY_SUPPORT_ENABLED", null,
91+
c -> Boolean.FALSE);
92+
8793
/** {@link VariableDefinition} for {@link com.devonfw.tools.ide.context.IdeContext#getProjectName() DEVON_IDE_CUSTOM_TOOLS}. */
8894
VariableDefinitionString DEVON_IDE_CUSTOM_TOOLS = new VariableDefinitionString("DEVON_IDE_CUSTOM_TOOLS");
8995

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

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,62 @@ void testFailOnAmbiguousMerge(@TempDir Path tempDir) throws Exception {
9191
;
9292

9393
}
94+
95+
/**
96+
* Tests for XML merge of legacy devonfw-ide templates without XML namespace prefix merge.
97+
*/
98+
@Test
99+
void testLegacySupportXmlMerge() {
100+
101+
// arrange
102+
String projectDevonfwIde = "devonfw-ide";
103+
IdeTestContext context = newContext(projectDevonfwIde);
104+
Path devonfwIdePath = TEST_PROJECTS_COPY.resolve(projectDevonfwIde).resolve("project");
105+
EnvironmentVariables variables = context.getVariables();
106+
variables.getByType(EnvironmentVariablesType.CONF).set("IDE_XML_MERGE_LEGACY_SUPPORT_ENABLED", "true");
107+
Path settingsWorkspaceFolder = devonfwIdePath.resolve("settings").resolve("workspace");
108+
Path settingsSetupPath = settingsWorkspaceFolder.resolve("setup").resolve("setup.xml");
109+
Path settingsUpdatePath = settingsWorkspaceFolder.resolve("update").resolve("update.xml");
110+
Path settingsUpdateWithNsPath = settingsWorkspaceFolder.resolve("update").resolve("updateWithNs.xml");
111+
Path workspaceSetupPath = devonfwIdePath.resolve("workspaces").resolve("main").resolve("setup.xml");
112+
Path workspaceUpdatePath = devonfwIdePath.resolve("workspaces").resolve("main").resolve("update.xml");
113+
Path workspaceUpdateWithNsPath = devonfwIdePath.resolve("workspaces").resolve("main").resolve("updateWithNs.xml");
114+
Path workspaceResultUpdateWithNsPath = devonfwIdePath.resolve("workspaces").resolve("main").resolve("expectedResultUpdateWithNs.xml");
115+
XmlMerger merger = new XmlMerger(context);
116+
117+
// act
118+
merger.doMerge(settingsSetupPath, settingsUpdatePath, variables, workspaceSetupPath);
119+
merger.doMerge(settingsSetupPath, settingsUpdatePath, variables, workspaceUpdatePath);
120+
merger.doMerge(settingsSetupPath, settingsUpdateWithNsPath, variables, workspaceUpdateWithNsPath);
121+
122+
// assert
123+
XmlAssert.assertThat(settingsSetupPath.toFile()).and(workspaceSetupPath.toFile()).areIdentical();
124+
XmlAssert.assertThat(settingsUpdatePath.toFile()).and(settingsUpdatePath.toFile()).areIdentical();
125+
XmlAssert.assertThat(workspaceUpdateWithNsPath.toFile()).and(workspaceResultUpdateWithNsPath.toFile()).areIdentical();
126+
127+
}
128+
129+
@Test
130+
void testLegacySupportWarningWhenEnvNotSetAndNoNamespace() {
131+
132+
// arrange
133+
String projectDevonfwIde = "devonfw-ide";
134+
IdeTestContext context = newContext(projectDevonfwIde);
135+
Path devonfwIdePath = TEST_PROJECTS_COPY.resolve(projectDevonfwIde).resolve("project");
136+
EnvironmentVariables variables = context.getVariables();
137+
Path settingsWorkspaceFolder = devonfwIdePath.resolve("settings").resolve("workspace");
138+
Path settingsSetupPath = settingsWorkspaceFolder.resolve("setup").resolve("setup.xml");
139+
Path settingsUpdatePath = settingsWorkspaceFolder.resolve("update").resolve("update.xml");
140+
Path workspaceSetupPath = devonfwIdePath.resolve("workspaces").resolve("main").resolve("setup.xml");
141+
XmlMerger merger = new XmlMerger(context);
142+
143+
// act
144+
merger.doMerge(settingsSetupPath, settingsUpdatePath, variables, workspaceSetupPath);
145+
146+
// assert
147+
assertThat(context).logAtWarning().hasEntries(
148+
"XML merge namespace not found. If you are working in a legacy devonfw-ide project, please set IDE_XML_MERGE_LEGACY_SUPPORT_ENABLED=true to "
149+
+ "proceed correctly.");
150+
}
151+
94152
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<root>
3+
<element name="elem1" attr1="setupValue">This is the kept setup XML file</element>
4+
</root>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<root>
3+
<element name="elem2" attr1="updateValue">This is the updated XML file</element>
4+
</root>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<root xmlns:merge="https://github.com/devonfw/IDEasy/merge" merge:strategy="combine">
3+
<element name="elem1" attr1="updateNsValue1">This is an element of the updated XML file with namespace</element>
4+
<element name="elem2" attr2="updateNsValue2">This is another element of the updated XML file with namespace</element>
5+
<element1 merge:id="name()" attr1="newValue">New text 1</element1>
6+
</root>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<root>
3+
<element attr1="updateNsValue1" attr3="value3" name="elem1">This is an element of the updated XML file with namespace</element>
4+
<element1 attr1="newValue" attr2="oldValue">New text 1</element1>
5+
<element2 attr2="oldValue">2</element2>
6+
<element attr2="updateNsValue2" name="elem2">This is another element of the updated XML file with namespace</element>
7+
</root>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<root>
3+
<element name="elem1" attr1="workspaceValue" attr3="value3">This is the workspace XML file</element>
4+
<element1 attr2="oldValue">Old text 1</element1>
5+
</root>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<root>
3+
<element name="elem1" attr1="workspaceValue" attr3="value3">This is the old workspace XML file</element>
4+
<element1 attr2="oldValue">1</element1>
5+
<element2 attr2="oldValue">2</element2>
6+
</root>

0 commit comments

Comments
 (0)