views:

244

answers:

3

Hi,

I'm currently writing some kind of a Maven POM preprocessor that assembles a POM for a project from multiple input files (basically a template and a module specific file). The files are hierarchically ordered (template = most general, module specific = least general). The problem is now to merge these files into a single POM file.

Long story short or if you're not familiar with Maven: a POM looks like this (shortened):

<project>
  <modelVersion>4.0.0</modelVersion>
  <dependencies>
    <dependency>
      <groupId>org.apache.maven</groupId>
      <artifactId>maven-core</artifactId>
    </dependency>
  </dependencies>
</project>

Basically the merger shall replace all values of the more general file with the values of the more specific file (i.e. singletons, e.g. the <modelVersion> above) but there are certain elements where the merger shall add the more certain element to a parent (i.e. collections, e.g. <dependency> elements shall always be added to the <dependencies> element and no <dependency> element shall be replaced by another).

A more detailed example with definition of desired output:

File A:

<project>
  <modelVersion>A</modelVersion>
  <dependencies>
    <dependency>
      <groupId>groupIdA</groupId>
      <artifactId>artifactIdA</artifactId>
    </dependency>
  </dependencies>
</project>

File B:

<project>
  <modelVersion>B</modelVersion>
  <dependencies>
    <dependency>
      <groupId>groupIdB</groupId>
      <artifactId>artifactIdB</artifactId>
    </dependency>
  </dependencies>
</project>

Desired output:

<project>
  <modelVersion>B</modelVersion>
  <dependencies>
    <dependency>
      <groupId>groupIdA</groupId>
      <artifactId>artifactIdA</artifactId>
    </dependency>
    <dependency>
      <groupId>groupIdB</groupId>
      <artifactId>artifactIdB</artifactId>
    </dependency>
  </dependencies>
</project>

The set of collection type elements are known and should be configurable (preferably via a set of XPath expressions).

A Java based solution is appreciated.

What looked most promising so far was the tool mentioned here but the MERGE action produces something like

<dependency>
  <groupId>groupIdAgroupIdB</groupId>
  <artifactId>artifactIdAartifactIdB</artifactId>
</dependency>

when merging, which is not what I need.

Any ideas? Thanks for your help!

A: 

But isn't that all the purpose of the parent pom ? providing default value for most of used elements ?

Riduidel
I'm not running a normal Maven build. Instead, I'm running a preprocessor that just builds the POM (i.e., it also builds the parent POM, so there's nothing there to inherit from).The purpose behind this is that the preprocessor is part of a plugin that assembles projects dynamically from various modules that are spread across a subversion repo.
Patrick Bergner
A: 

I think that goal help:effective-pom [1] works exacly like you want. Even if not, You can look into sources how they did this.

[1] http://maven.apache.org/plugins/maven-help-plugin/effective-pom-mojo.html

Michał Mech
If I would be running a normal Maven build, you would be right. Please see the comment I gave to Riduidel's answer about the purpose of this question. I will look into the sources of the help plugin anyway. Thanks for that hint.
Patrick Bergner
I just looked up the code of help:effective-pom. They have the possibility to speak to the org.apache.maven.model.Model class as the help goal can only be executed on existing projects. That's not true for my purpose as I just have a bunch of java.io.File objects that shall be merged. That's also why my question was more targeted towards a general XML merge approach with customizable behavior for certain nodes.
Patrick Bergner
A: 

I don't have a Java solution, but if you're interested in a Windows tool, Project: Merge will do that just fine. You'll have to tell it which values it should choose (because it wont second guess for two-way merges), but it will do it.

You can set up the format specification for element identification so that it knows to use the character data inside <groupId> to identify <dependency> elements. Once that's done it should work fine.

James
Thanks for your answer, James. The tool looks good, but unfortunately a Windows only tool is no use for my purpose. I hacked together something myself in Java since posting the question, but I doubt it's 100% reliable. ;-)
Patrick Bergner
Ah that's fair enough. I wasn't convinced a Windows tools would be any use to you, but I figured I'd mention it on the off chance. Do you think a Java version of the tool would be worth me looking into?
James