devonfw / ide

Tool to automate setup and update of development environment (esp. for Java projects).
Apache License 2.0
33 stars 101 forks source link

Merge XML files into workspace #1277

Closed hohwille closed 1 year ago

hohwille commented 1 year ago

As a devonfw-ide user, I want to manage XML configuration files for my workspace so that specific sections get merged into my current IDE configration.

I noticed that even though I have changed an XML configuration file in settings/intellij/workspace/update/.intellij/config/options/ and reran devon intellij the changed settings have not been merged into my workspace (workspaces/main/.intellij/config/options/). I had to delete the XML file in my workspace and restart intellij again via devon to make it work.

In general merging XML is very complex. However, our XML merger is implemented rather naive: https://github.com/devonfw/ide/blob/10d3109754079a65573bdadb4782bf500983a0e3/configurator/src/main/java/com/devonfw/tools/ide/configurator/merge/XmlMerger.java#L28

In this story, we should first design a solution how to solve XML merging in general. For this we can get some inspirations and leanings from CobiGen. However, IMHO the CobiGen approach is too complex and we would have to maintain every new specific tag and attribute that IDEs could introduce in the future. Therefore, I rather think about a simple approach where we could somehow "annotate" the template XML file such that it will know which parts of the XML are actual "identifiers" and which are "values".

To outline the general problem lets have a look at the following example: XML Template from settings:

<root>
  <list>
    <item>
      <id>key1</id>
      <value>value1</value>
    </item>
  </list>
  <plugins>
    <plugin>FooPlugin</plugin>
  </plugins>
</root>

XML config in workspace:

<root>
  <list>
    <item>
      <id>key1</id>
      <value>value2</value>
      <optionalElement>something</optionalElement>
    </item>
   </list>
  <plugins>
    <plugin>BarPlugin</plugin>
  </plugins>
</root>

We might expect the merged result to be this:

<root>
  <list>
    <item>
      <id>key1</id>
      <value>value1</value>
      <optionalElement>something</optionalElement>
    </item>
   </list>
  <plugins>
    <plugin>BarPlugin</plugin>
    <plugin>FooPlugin</plugin>
  </plugins>
</root>

But how would our XmlMerger know that he has to merge existing item element with the same id being key1 and change its value from value2 to value1 while the plugin element will be added. We might have some heuristic saying that id is a special tag-name but looking at real examples from the mess that Intellij has created in its workspace config this will not work out. On the other hand, I do not want to go the CobiGen way and hard-code all the tag names and logic for Eclipse, Intellij, etc. into our XmlMerger. So my idea would be something like this for the template:

<root xmlns:ide="https://github.com/devonfw/ide" >
  <list>
    <item ide:kind="merge">
      <id ide:kind="id">key1</id>
      <value>value1</value>
    </item>
  </list>
  <plugins>
    <plugin ide:kind="merge-unique">FooPlugin</plugin>
  </plugins>
</root>

Our XmlMerger would understand the semantic of the ide namespace and remove that namespace during the merging process. However, this way, it can understand that it will merge elements matching to /root/list/item and if present in the existing XML file to merge into that one that has an id element being identical to the one from the template (excluding the ide namespace) and otherwise to append the entire item. The option merge-unique means that an element is both the id and the value. So far this is just a draft that needs some more rethinking. Maybe we also need to configure things like ide:add="end" vs. ide:add="start" and maybe even ide:add="ascending" but then end should be the default, that can be omitted.

alfeilex commented 1 year ago

Moved to IDEasy: https://github.com/devonfw/IDEasy/issues/43