In the last example we demonstrated a sub projection pretending a non existing element.
This time we like to define some model classes for a Jenkins job configuration and project existing elements to them. But there is one little hurdle: We can not know the exact XML structure, because Jenkins plugins contribute new elements with different names. Our model would have to include one class for each contributed element, but we like to keep the number of model classes low.
The solution to this shows:
Instead of defining one model class for each element, we project all elements doing the same stuff to the same model object. This is done by using XPath wildcards that will simply select all elements in a defined subtree. Of course we define a getter method to give us the element name, so we can use our model to find out what which elements are really in there.
Our example should read all builder and all publisher elements in the configuration file. We like to know the element names of both, so we define a super interface "ModelElement" and let our model objects extend it.
public interface ModelElement { /** * Getter may use XPath functions. * @return Name of the XML Element which is projected to this object. */ @XBRead ( "name()" ) String getName(); } |
public interface Publisher extends ModelElement{ /** * The Plugin name is located in an attribute of the configuration element. * @return The plugin name which contributed this element. */ @XBRead ( "@plugin" ) String getPlugin(); } |
public interface Builder extends ModelElement { /** * Builder may invoke ant targets, maven goals or shell commands. * @return The builders task, whatever this element is. */ @XBRead ( "child::targets | child::command" ) String getTargetsOrCommands(); } |
Now that we have our model objects defined, we need to define how to retrieve them.
public interface JenkinsJobConfig { @XBRead ( "//publishers/*" ) List<Publisher> getPublishers(); @XBRead ( "//prebuilders/* | //builders/* | //postbuilders/*" ) List<Builder> getAllBuilders(); } |
public class TestJenkinsConfigParsing extends TutorialTestCase { private JenkinsJobConfig config; @Before public void readJobConfig() throws IOException { config = new XBProjector().io().fromURLAnnotation(JenkinsJobConfig. class ); } @Test public void testBuilderReading() { for (Builder builder: config.getAllBuilders()) { System.out.println( "Builder: " +builder.getName()+ " executes " +builder.getTargetsOrCommands() ); } } @Test public void testPublishers() { List<Publisher> publishers = config.getPublishers(); for (Publisher p : publishers) { System.out.println( "Publisher:" + p.getName() + " contributed by plugin " +p.getPlugin()); } } } |