2

I am working on a project which uses multiple ontologies defined over several files. I am hoping to use Jena to generate the java classes to help with development but I can't seem to find a way to have Jena process multiple files as a maven goal.

I have never used Jena through maven before but I have used it on the command line (never for multiple ontologies at the same time).

The relevant part of my pom.xml is listed below (this was largely copied from the Jena website):

<plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <executions>
                <execution>
                    <phase>generate-sources</phase>
                    <goals>
                        <goal>java</goal>
                    </goals>
                    <configuration>
                        <mainClass>jena.schemagen</mainClass>
                        <commandlineArgs>
                            --inference \
                            -i ${basedir}/src/main/resources/ontologies/exception.owl \
                            --package com.borwell.dstl.mexs.ontology \
                            -o ${project.build.directory}/generated-sources/java \
                        </commandlineArgs>
                        <commandlineArgs>
                            --inference \
                            -i ${basedir}/src/main/resources/ontologies/location.owl \
                            --package com.borwell.dstl.mexs.ontology \
                            -o ${project.build.directory}/generated-sources/java \
                        </commandlineArgs>
                    </configuration>
                </execution>
            </executions>
        </plugin>
</plugins>

I have had a good look around on the Jena website and other sites (my googlefoo is usually quite good) but I have been unable to find anyone else having this problem or any documentation explaining how to do this. Any help on this would be very useful.

Ed Mackenzie
  • 679
  • 6
  • 16
  • 1
    Have never used Jena before, but with regards to maven you could simply define 2 executions of the maven-exec-plugin and have jena execute twice that way. Would that not solve your problem? – DB5 Mar 26 '14 at 14:46

3 Answers3

3

I wrote a custom Maven task for Jena Schemagen, which is now part of the standard Jena distribution. See the documentation here

Ian Dickinson
  • 12,875
  • 11
  • 40
  • 67
2

EDIT

This Answer now exists and calls out a more standard solution. Namely, the existence of a schemagen-maven plugin that the poster had developed which is included in the standard Jena distribution.

Original Answer

You have two options, create a custom maven plugin (which is actually not that difficult) or shell out to something outside maven to handle your needs. I made a hack in the past which I'll share with you. It's not pretty, but it works well.

This approach uses Maven Ant Tasks to call out to an ant build.xml from within the generate-sources phase of a maven build.

You begin by modifying your pom.xml to including the following:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-antrun-plugin</artifactId>
            <version>1.7</version>
            <executions>
                <execution>
                    <phase>generate-sources</phase>
                    <goals>
                        <goal>run</goal>
                    </goals>
                    <configuration>
                        <target>
                            <taskdef resource="net/sf/antcontrib/antcontrib.properties"
                                classpathref="maven.runtime.classpath" />
                            <property name="runtime-classpath" refid="maven.runtime.classpath" />
                            <ant antfile="${basedir}/src/main/ant/build.xml"
                                inheritRefs="true">
                                <target name="my.generate-sources" />
                            </ant>
                        </target>
                    </configuration>
                </execution>
            </executions>
            <dependencies>
                <dependency>
                    <groupId>ant-contrib</groupId>
                    <artifactId>ant-contrib</artifactId>
                    <version>1.0b3</version>
                    <exclusions>
                        <exclusion>
                            <groupId>ant</groupId>
                            <artifactId>ant</artifactId>
                        </exclusion>
                    </exclusions>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

In the build.xml file (which, as you can see, is located in src/main/ant/build.xml, is the following.

<?xml version="1.0" encoding = "UTF-8"?>
<!DOCTYPE project>
<project name="my" default="my.error">

    <property name="vocab.out.root" location="${basedir}/src/main/java" />
    <property name="vocab.package" value = "put something here" />
    <property name="vocab.ns" value="put something here" />

    <path id="my.vocabulary">
        <fileset dir="${basedir}/src/main/resources/put something here" casesensitive="yes" >
            <include name="**/*.owl" />
        </fileset>
    </path>

    <scriptdef language="javascript" name="make-proper">
        <attribute name="string" /> 
        <attribute name="to" />
        <![CDATA[
            var raw_string = attributes.get( "string" );
            var string_elements = raw_string.split('-');
            var nameComponents;
            var finalName = "";

            var i;
            for(i = 0; i < string_elements.length; i++){
                 var element = string_elements[i];
                 finalName += element.substr(0,1).toUpperCase() + element.substr(1);
            }

            project.setProperty( attributes.get( "to" ), finalName );
        ]]>
    </scriptdef>

    <!-- target for processing a file -->
    <target name="my.schemagen-file">

        <echo message="${vocab.file}" />

        <!-- for constructing vocab file name -->
        <local name="source.file.dir" />
        <dirname property="source.file.dir" file="${vocab.file}" />
        <local name="source.file" />
        <basename property="source.file" file="${vocab.file}" suffix=".owl" />
        <local name="vocab.name" />
        <make-proper string="${source.file}" to="vocab.name" />

        <!-- for constructing destination file name -->
        <local name="vocab.package.path" />
        <propertyregex property="vocab.package.path" input="${vocab.package}" regexp="\." replace="/" global="true" />
        <local name="dest.file" />
        <property name="dest.file" value="${vocab.out.root}/${vocab.package.path}/${vocab.name}.java" />

        <!-- Determine if we should build, then build -->       
        <outofdate>
            <sourcefiles path="${vocab.file}" />
            <targetfiles path="${dest.file}" />
            <sequential>
                <!-- Actual construction of the destination file -->
                <echo message="--inference --ontology -i ${vocab.file} -a ${vocab.ns} --package ${vocab.package} -o ${vocab.out.root} -n ${vocab.name}" />
                <java classname="jena.schemagen" classpath="${runtime-classpath}">
                    <arg line="--ontology --nostrict -i ${vocab.file} -a ${vocab.ns} --package ${vocab.package} -o ${vocab.out.root} -n ${vocab.name}" />
                </java>
            </sequential>
        </outofdate>
    </target>

    <!-- Maven antrun target to generate sources -->
    <target name="my.generate-sources">
        <foreach target="my.schemagen-file" param="vocab.file" inheritall="true">
            <path refid="my.vocabulary"/>
        </foreach>
    </target>

    <target name="my.error">
        <fail message="This is not intended to be executed from the command line. Execute generate-sources goal using maven; ex:\nmvn generate-sources" />
    </target>
</project>

Walking you through the whole thing.

  1. The maven-antrun-plugin executes our build script , making sure that antcontrib are available as well as the maven.runtime.classpath. This ensures that properties that would be available within maven are available within the ant task as well.
  2. If build.xml is called without specifying a task, it intentionally fails. This helps to keep you from using it wrong.
  3. If the my.generate-sources target is executed, then we can use foreach from antcontrib in order to process each file within your specified directory. Adjust this file pattern however you need to. Note that an assumed extension of .owl is used elsewhere.
  4. For each owl file, the my.schemagen-file target is called. I utilize local variables in order make this function.
  5. A custom ant task (defined in javascript, named make-proper) helps to generate the destination file names for your files. I use a convention where my vocabulary files are in some-hyphenated-lowercase-structure.owl. My desired class name for that would be SomeHyphenatedLowercaseStructure.java. You should customize this however you see fit.
  6. For each derived file name, we test to see if it exists and if it is out of date. This convenience only allows schemagen to run if the source file is newer than the destination file. We use the outofdate task to do this.
  7. We run schemagen. I use flags specific to OWL vocabularies. You can adjust this however best suits your system.
Community
  • 1
  • 1
Rob Hall
  • 2,693
  • 16
  • 22
  • Nice suggestions! However I had missed the ability to call multiple executions of the same thing - pointed out by DB5. I will your suggestions in mind for the future though! Thanks – Ed Mackenzie Apr 02 '14 at 12:33
0

After more generalised searching and thanks to DB5 I have found the solution to be multiple executions. I was hoping for a more elegant solution but this does work.

Credit to DB5

Community
  • 1
  • 1
Ed Mackenzie
  • 679
  • 6
  • 16
  • 1
    It would be useful to add some description of your solution or link to the relevant answer. As it stands, the answer just links to the profile of a user without any guidance. – Rob Hall Apr 03 '14 at 16:06
  • I was referring to the comment from DB5 on my original question which provided the obvious solution. – Ed Mackenzie Apr 14 '14 at 15:55