<!--
  ~ Copyright (c) 2011, The Broad Institute
  ~
  ~ Permission is hereby granted, free of charge, to any person
  ~ obtaining a copy of this software and associated documentation
  ~ files (the "Software"), to deal in the Software without
  ~ restriction, including without limitation the rights to use,
  ~ copy, modify, merge, publish, distribute, sublicense, and/or sell
  ~ copies of the Software, and to permit persons to whom the
  ~ Software is furnished to do so, subject to the following
  ~ conditions:
  ~
  ~ The above copyright notice and this permission notice shall be
  ~ included in all copies or substantial portions of the Software.
  ~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  ~ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  ~ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  ~ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  ~ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  ~ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  ~ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  ~ OTHER DEALINGS IN THE SOFTWARE.
  -->

<project name="Sting" default="dist" basedir="." xmlns:ivy="antlib:org.apache.ivy.ant">
    <description>Compile and distribute the Sting toolkit</description>
    <property name="build.sysclasspath" value="first" />

    <property name="build.dir" value="build" />
    <property name="dist.dir" value="dist" />
    <property name="external.dir" value="external" />
    <property name="java.source.dir" value="java/src" />
    <property name="java.classes" value="${build.dir}/java/classes" />
    <property name="resource.file" value="StingText.properties" />
    <property name="resource.path" value="${java.classes}/StingText.properties" />

    <property name="scala.source.dir" value="scala/src" />
    <property name="scala.classes" value="${build.dir}/scala/classes" />

    <property name="queue-extensions.source.dir" value="${build.dir}/queue-extensions/src" />
    
    <!-- where to find the tribble distro -->
    <property name="tribble.dir" value="tribble" />

    <!-- where to find 'findbugs', which you must set if you plan to use 'ant findbugs' -->
    <property name="findbugs.home" value="./findbugs"/>

    <!-- do we want to halt on failure of a unit test? default to yes (Bamboo uses 'no') -->
    <property name="halt" value="yes" />
    
    <!-- should our unit test output go to a file or the screen?
    false means it goes to the screen (default) true to file -->
    <property name="usefile" value="false" />

    <!-- If running the 'package' task, this property controls the name of the xml file to package -->
    <property name="package.xml.dir" value="packages" />
    <property name="executable" value="GenomeAnalysisTK" />

    <property environment="env"/>

    <property name="drmaa.jar" value="${env.SGE_ROOT}/lib/drmaa.jar" />

    <patternset id="java.source.pattern">
        <include name="**/*.java"/>
        <exclude name="**/playground/**" unless="include.playground" />
        <exclude name="**/oneoffprojects/**" unless="include.oneoffs" />
    </patternset>

    <fileset id="java.source.files" dir="${java.source.dir}">
        <patternset refid="java.source.pattern" />
    </fileset>

    <fileset id="external.source.files" dir="${external.dir}" erroronmissingdir="false">
        <patternset refid="java.source.pattern" />
    </fileset>

    <fileset id="java.class.files" dir="${java.classes}" erroronmissingdir="false">
        <include name="**/*.class"/>
    </fileset>

    <!-- the path for resources that need to go into the GATK jar;
         any additional resources should go into this set. -->
    <path id="gatk.resources">
        <fileset dir="${java.source.dir}">
            <include name="**/**/templates/*" />
        </fileset>
    </path>

    <patternset id="dependency.mask" includes="*.jar">
      <exclude name="testng*.jar" />
      <exclude name="bcel*.jar" />
    </patternset>
    
    <path id="external.dependencies">
      <fileset dir="lib">
        <patternset refid="dependency.mask" />
      </fileset>
    </path>

    <path id="build.results">
      <fileset dir="dist">
        <patternset refid="dependency.mask" />
      </fileset>
    </path>

    <!-- Path to scala dependencies. -->
    <path id="scala.dependencies">
        <path refid="external.dependencies" />
        <pathelement location="${java.classes}" />
        <!-- Need the resources as we will be running a command line program which needs the help text. -->
        <pathelement location="${resource.path}" />
        <!-- Add any previously compiled scala classes to the path. -->
        <pathelement location="${scala.classes}" />
    </path>

    <target name="init.resolve" unless="init.resolve.done">
        <!-- ivy properties -->
        <property name="ivy.install.version" value="2.2.0"/>
        <property name="ivy.home" value="${user.home}/.ant"/>
        <property name="ivy.jar.dir" value="${ivy.home}/lib"/>
        <property name="ivy.jar.file" value="ivy-${ivy.install.version}.jar"/>
        <property name="ivy.settings.dir" value="settings"/>
        <property file="${ivy.settings.dir}/ivysettings.properties"/>
  
      <mkdir dir="lib"/>
      <mkdir dir="${ivy.jar.dir}"/>
      <get src="http://repo1.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/${ivy.jar.file}"
           dest="${ivy.jar.dir}/${ivy.jar.file}"
           usetimestamp="true"/>
      <taskdef resource="org/apache/ivy/ant/antlib.xml"
               uri="antlib:org.apache.ivy.ant"
               classpath="${ivy.jar.dir}/${ivy.jar.file}"/>
      <ivy:settings file="${ivy.settings.dir}/ivysettings.xml"/>
        <property name="init.resolve.done" value="true"/>
    </target>

    <target name="init.gridengine" depends="init" if="include.gridengine">
        <copy todir="lib" file="${drmaa.jar}"/>
    </target>

    <target name="resolve" depends="init.resolve,init,init.gridengine"
            description="locate and download library dependencies">
        <property name="ivy.conf" value="default"/>
      <ivy:retrieve file="ivy.xml" conf="${ivy.conf}" />
      <!-- Remove old versions of ivy jars AFTER the ivy:retrieve has been class loaded. -->
      <delete file="${ivy.jar.dir}/ivy-2.0.0.jar"/>
      <delete file="${ivy.jar.dir}/ivy-2.2.0-rc1.jar"/>
    </target>

    <target name="init.buildall">
        <!-- Set the properties needed to build everything -->
        <property name="gatk.target" value="oneoffs"/>
        <property name="scala.target" value="core"/>
    </target>

    <!-- define some key locations that might change based on how the build is run -->
    <target name="init">
      <!-- define build version and timestamp -->
      <exec executable="svnversion" outputproperty="build.version" failonerror="true">
        <arg value="--no-newline"/>
      </exec>
      <tstamp>
        <format property="build.timestamp" pattern="yyyy/MM/dd HH:mm:ss"/>
      </tstamp>

        <!-- Set target based on STING_BUILD_TYPE environment variable -->
        <condition property="sting.target" value="core" else="${env.STING_BUILD_TYPE}">
            <equals arg1="${env.STING_BUILD_TYPE}" arg2="$${env.STING_BUILD_TYPE}" />
        </condition>

        <!-- Get the gatk build target.  Default to the STING_BUILD_TYPE.  -->
        <condition property="gatk.target" value="${sting.target}" else="${env.GATK_BUILD_TYPE}">
            <equals arg1="${env.GATK_BUILD_TYPE}" arg2="$${env.GATK_BUILD_TYPE}" />
        </condition>

        <!-- Get the queue build target.  Default to none.  -->
        <condition property="scala.target" value="none" else="${env.QUEUE_BUILD_TYPE}">
            <equals arg1="${env.QUEUE_BUILD_TYPE}" arg2="$${env.QUEUE_BUILD_TYPE}" />
        </condition>

        <!-- If the scala target is set, then include all scala tasks. -->
        <condition property="scala.include">
            <or>
                <not><equals arg1="${scala.target}" arg2="none" /></not>
            </or>
        </condition>

        <!-- Include Grid Engine in the compile if SGE_ROOT is available. -->
        <!-- Based off of http://wikis.sun.com/display/GridEngine/Automating+Grid+Engine+Functions+Through+DRMAA -->
        <condition property="include.gridengine">
            <available file="${drmaa.jar}"/>
        </condition>

        <echo message="GATK build      : ${gatk.target}"/>
        <echo message="Scala build     : ${scala.target}"/>
      <echo message="source revision : ${build.version}"/>
      <echo message="build time      : ${build.timestamp}" />
      
      <condition property="include.oneoffs">
        <equals arg1="${gatk.target}" arg2="oneoffs" casesensitive="false" />
      </condition>
      
      <condition property="include.playground">
        <or>
          <equals arg1="${gatk.target}" arg2="playground" casesensitive="false"/>
          <equals arg1="${gatk.target}" arg2="oneoffs" casesensitive="false" />
        </or>
      </condition>

      <!-- Create the build directory structure used by compile -->
      <mkdir dir="${build.dir}"/>
      <mkdir dir="${java.classes}"/>

      <pathconvert property="external.build.dir">
        <path path="${java.classes}"/>
      </pathconvert>

      <pathconvert property="external.dist.dir">
        <path path="${dist.dir}" />
      </pathconvert>

      <!-- GATK dependencies consist of 3rd party plugins plus compiled GATK classes -->
      <pathconvert property="external.gatk.classpath">
        <path path="${java.classes}"/>
        <path refid="external.dependencies" />
      </pathconvert>
    </target>

    <target name="init.scala.compile" depends="resolve"
            description="Initializes the scala ant tasks from scala-compiler.jar">
        <path id="scala.classpath">
            <fileset dir="lib">
                <include name="scala-compiler-*.jar"/>
                <include name="scala-library-*.jar"/>
            </fileset>
        </path>
        <taskdef resource="scala/tools/ant/antlib.xml">
            <classpath refid="scala.classpath"/>
        </taskdef>
    </target>

    <target name="gatk.compile" depends="tribble,init,resolve"
            description="compile the source">
        <!-- Compile the java code from ${src} into build -->
        <javac fork="true" memoryMaximumSize="512m" srcdir="${java.source.dir}" destdir="${java.classes}" debug="true" debuglevel="lines,vars,source" classpathref="external.dependencies">
            <exclude name="**/examples/**" />
            <exclude name="**/playground/**" unless="include.playground"/>
            <exclude name="**/oneoffprojects/**" unless="include.oneoffs"/>
        </javac>

        <subant target="compile" genericantfile="build.xml">
            <property name="build.dir" value="${external.build.dir}" />
            <property name="dist.dir" value="${external.dist.dir}" />
            <property name="gatk.classpath" value="${external.gatk.classpath}" />
            <fileset dir="${external.dir}" includes="*/build.xml" erroronmissingdir="false" />
        </subant>
    </target>

    <target name="init.queue-extensions.generate" depends="gatk.compile">
        <condition property="uptodate.queue-extensions.generate">
            <or>
                <not>
                    <isset property="scala.include"/>
                </not>
                <uptodate targetfile="${queue-extensions.source.dir}">
                    <srcfiles refid="java.class.files"/>
                    <srcfiles file="${queue-extensions.gatk.jar}"/>
                </uptodate>
            </or>
        </condition>
    </target>

    <!-- NOTE: Extracting help first to avoid "Unable to load help text.  Help output will be sparse." warning message. -->
    <target name="queue-extensions.generate" depends="extracthelp,init.queue-extensions.generate" unless="uptodate.queue-extensions.generate" description="generate GATK modules for Queue">
        <mkdir dir="${queue-extensions.source.dir}"/>
        <echo>Generating Queue GATK extensions...</echo>
        <java fork="true" failonerror="true" classname="org.broadinstitute.sting.queue.extensions.gatk.GATKExtensionsGenerator" >
            <arg value="-outDir" />
            <arg path="${queue-extensions.source.dir}" />
            <arg value="-l" />
            <arg value="WARN" />
            <classpath>
                <file file="${queue-extensions.gatk.jar}"/>
                <path refid="scala.dependencies"/>
            </classpath>
        </java>
        <touch>
            <file file="${queue-extensions.source.dir}"/>
        </touch>
    </target>

    <!-- Scala depends on the java compile -->
    <target name="scala.compile" depends="init,resolve,gatk.compile,queue-extensions.generate,init.scala.compile" if="scala.include" description="compile Scala">
        <mkdir dir="${scala.classes}"/>
        <echo>Building Scala...</echo>
        <scalac fork="true" jvmargs="-Xmx512m" destdir="${scala.classes}" classpathref="scala.dependencies" deprecation="yes" unchecked="yes">
            <src path="${scala.source.dir}" />
            <src path="${queue-extensions.source.dir}" />
            <include name="**/*.scala"/>
            <exclude name="**/gridengine/**" unless="include.gridengine" />
        </scalac>
    </target>

    <target name="init.extracthelp" depends="gatk.compile">
        <loadfile property="properties.version" srcfile="${basedir}/${resource.path}" failonerror="false" quiet="true">
            <filterchain>
                <linecontains>
                    <contains value="org.broadinstitute.sting.gatk.CommandLineGATK.version"/>
                </linecontains>
                <tokenfilter>
                    <replaceregex pattern="^.*\.(.*?)$" replace="\1"/>
                </tokenfilter>
                <striplinebreaks/>
            </filterchain>
        </loadfile>

        <!-- This fileset will contain only source files modified since the resource file was last generated,
             or all source files if the resource file doesn't exist -->
        <fileset dir="${basedir}" id="modified.source.files">
            <include name="${java.source.dir}/**/*.java"/>
            <include name="${external.dir}/**/*.java"/>
            <depend targetdir="${basedir}">
                <mapper type="merge" to="${resource.path}"/>
            </depend>
        </fileset>

        <!-- Set the sources.modified property only if our fileset of modified source files is non-empty -->
        <pathconvert refid="modified.source.files" property="sources.modified" setonempty="false"/>

        <!-- Due to a limitation in the doclet API, we always need to pass package-info files to javadoc -->
        <fileset dir="${basedir}" id="package.info.files">
            <include name="${java.source.dir}/**/package-info.java"/>
            <include name="${external.dir}/**/package-info.java"/>
        </fileset>

        <condition property="uptodate.extracthelp">
            <or>
                <isset property="disable.help"/>
                <and>
                    <not>
                        <isset property="sources.modified"/>
                    </not>
                    <equals arg1="${properties.version}" arg2="${build.version}"/>
                </and>
            </or>
        </condition>
    </target>

    <target name="extracthelp" depends="init.extracthelp" unless="uptodate.extracthelp"
	        description="Extract help key/value pair file from the JavaDoc tags.">
        <path id="doclet.classpath">
            <path refid="external.dependencies" />
            <pathelement location="${java.classes}" />
        </path>

        <javadoc doclet="org.broadinstitute.sting.utils.help.ResourceBundleExtractorDoclet"
                 docletpathref="doclet.classpath"
                 classpathref="external.dependencies"
                 classpath="${java.classes}"
                 additionalparam="-build-timestamp &quot;${build.timestamp}&quot; -version-suffix .${build.version} -out ${basedir}/${resource.path} -quiet">
            <sourcefiles>
                <union>
                    <fileset refid="modified.source.files"/>
                    <fileset refid="package.info.files"/>
                </union>
            </sourcefiles>
        </javadoc>
    </target>

    <target name="sting.compile" depends="gatk.compile, scala.compile" />

    <target name="init.jar" depends="sting.compile,extracthelp">
        <mkdir dir="${dist.dir}"/>
        <copy todir="${dist.dir}">
            <fileset dir="lib" includes="*.jar"/>
        </copy>
    </target>

    <target name="sting-utils.jar" depends="gatk.compile, init.jar">
        <jar jarfile="${dist.dir}/StingUtils.jar">
            <fileset dir="${java.classes}" includes="**/utils/**/*.class"/>
            <fileset dir="${java.classes}" includes="**/commandline/**/*.class"/>
            <fileset dir="${java.classes}" includes="**/sting/datasources/**/*.class"/>
            <fileset dir="${java.classes}" includes="**/sting/jna/**/*.class"/>
            <fileset dir="${java.classes}" includes="net/sf/picard/**/*.class"/>
            <fileset dir="${java.classes}" includes="net/sf/samtools/**/*.class"/>
            <manifest>
                <attribute name="Premain-Class" value="org.broadinstitute.sting.utils.instrumentation.Sizeof" />
            </manifest>
        </jar>
    </target>

    <target name="gatk.jar" depends="gatk.compile, init.jar"
            description="generate the GATK distribution">
        <jar jarfile="${dist.dir}/GenomeAnalysisTK.jar">
            <path refid="gatk.resources"/>
            <fileset dir="${java.classes}">
	          <include name="${resource.file}" />
              <include name="**/gatk/**/*.class" />
              <include name="**/alignment/**/*.class"/>
              <include name="**/oneoffprojects/**/*.class" />
              <include name="**/playground/**/*.class" />
            </fileset>
            <manifest>
                <attribute name="Main-Class" value="org.broadinstitute.sting.gatk.CommandLineGATK" />
            </manifest>
        </jar>

        <jar jarfile="${dist.dir}/Aligner.jar">
            <fileset dir="${java.classes}" includes="**/alignment/**/*.class" />
        </jar>

        <jar jarfile="${dist.dir}/AnalyzeCovariates.jar" whenmanifestonly="skip">
          <fileset dir="${java.classes}">
            <include name="**/analyzecovariates/**/*.class" />
            <include name="**/gatk/walkers/recalibration/*.class" />
          </fileset>
          <manifest>
            <attribute name="Main-Class" value="org.broadinstitute.sting.analyzecovariates.AnalyzeCovariates" />
          </manifest>
        </jar>

        <subant target="dist" genericantfile="build.xml">
            <property name="build.dir" value="${external.build.dir}" />
            <property name="dist.dir" value="${external.dist.dir}" />
            <property name="gatk.classpath" value="${external.gatk.classpath}" />
            <fileset dir="${external.dir}" includes="*/build.xml" erroronmissingdir="false" />
        </subant>
    </target>

    <target name="gatk.oneoffs.jar" depends="gatk.compile, init.jar"
            description="generate the GATK oneoffs distribution" if="include.oneoffs">
        <jar jarfile="${dist.dir}/CompareBAMAlignments.jar" whenmanifestonly="skip">
          <fileset dir="${java.classes}">
            <include name="**/tools/**/*.class" />
          </fileset>
          <manifest>
            <attribute name="Main-Class" value="org.broadinstitute.sting.oneoffprojects.tools.CompareBAMAlignments" />
          </manifest>
        </jar>

        <jar jarfile="${dist.dir}/SliceBams.jar" whenmanifestonly="skip">
          <fileset dir="${java.classes}">
            <include name="**/tools/**/*.class" />
          </fileset>
          <manifest>
            <attribute name="Main-Class" value="org.broadinstitute.sting.playground.tools.SliceBams" />
          </manifest>
        </jar>
    </target>

    <target name="scala.jar" depends="scala.compile, init.jar" if="scala.include">
        <jar jarfile="${dist.dir}/GATKScala.jar">
          <fileset dir="${scala.classes}">
            <include name="org/broadinstitute/sting/scala/**/*.class"/>
          </fileset>
        </jar>
    </target>

    <target name="queue.jar" depends="scala.compile, init.jar" if="scala.include">
        <jar jarfile="${dist.dir}/Queue.jar">
            <fileset dir="${scala.classes}">
                <include name="org/broadinstitute/sting/queue/**/*.class"/>
            </fileset>
            <fileset dir="${java.classes}">
              <include name="org/broadinstitute/sting/queue/**/*.class" />
            </fileset>
            <manifest>
                <attribute name="Main-Class" value="org.broadinstitute.sting.queue.QCommandLine" />
            </manifest>
        </jar>
    </target>

    <target name="sting.jar" depends="sting-utils.jar, gatk.jar, gatk.oneoffs.jar, queue.jar" />

    <target name="init.manifests" depends="sting.jar">
        <pathconvert property="jar.classpath" pathsep=" ">
            <flattenmapper/>
            <fileset dir="${dist.dir}" includes="*.jar"/>
            <filelist files="GATKScala.jar"/>
        </pathconvert>
    </target>

    <target name="sting-utils.manifests" depends="sting-utils.jar, init.manifests">
        <jar jarfile="${dist.dir}/StingUtils.jar" update="true">
            <manifest>
                <attribute name="Class-Path" value="${jar.classpath}"/>
            </manifest>
        </jar>
    </target>

    <target name="gatk.manifests" depends="gatk.jar, init.manifests">

        <jar jarfile="${dist.dir}/GenomeAnalysisTK.jar" update="true">
            <manifest>
                <attribute name="Class-Path" value="${jar.classpath}"/>
            </manifest>
        </jar>

        <jar jarfile="${dist.dir}/AnalyzeCovariates.jar" update="true" whenmanifestonly="skip">
            <manifest>
                <attribute name="Class-Path" value="${jar.classpath}" />
            </manifest>
        </jar>

    </target>

    <target name="gatk.oneoffs.manifests" depends="gatk.oneoffs.jar, init.manifests" if="include.oneoffs">
        <jar jarfile="${dist.dir}/CompareBAMAlignments.jar" update="true" whenmanifestonly="skip">
            <manifest>
                <attribute name="Class-Path" value="${jar.classpath}" />
            </manifest>
        </jar>
        <jar jarfile="${dist.dir}/SliceBams.jar" update="true" whenmanifestonly="skip">
            <manifest>
                <attribute name="Class-Path" value="${jar.classpath}" />
            </manifest>
        </jar>
    </target>

    <target name="queue.manifests" depends="queue.jar, init.manifests" if="scala.include">
        <jar jarfile="${dist.dir}/Queue.jar" update="true" >
            <manifest>
                <attribute name="Class-Path" value="${jar.classpath}" />
            </manifest>
        </jar>
    </target>

    <target name="sting.manifests" depends="sting-utils.manifests, gatk.manifests, gatk.oneoffs.manifests, queue.manifests" />

    <target name="dist" depends="sting.manifests" />

    <target name="core" description="force a build of the Sting core code">
        <antcall target="dist" inheritAll="false">
            <param name="sting.target" value="core" />
        </antcall>
    </target>

    <target name="playground" description="force a build of the Sting experimental code">
      <antcall target="dist" inheritAll="false">
        <param name="sting.target" value="playground" />
	 </antcall>
    </target>

    <target name="oneoffs" description="force a build of the Sting experimental code and one-offs">
      <antcall target="dist" inheritAll="false">
        <param name="sting.target" value="oneoffs" />
      </antcall>
    </target>

    <target name="queue" description="force a build of Queue">
        <!--
        inheritAll is false so that 'ant queue' does not accidentally import
        params if the build was called with 'ant clean oneoffs queue'.
        Instead this task resets the parameters and is just like running
        a fresh 'ant dist -Dscala.target=core'.
        -->
        <antcall target="dist" inheritAll="false">
            <param name="scala.target" value="core" />
        </antcall>
    </target>

    <target name="test.init.compile">
        <mkdir dir="${java.test.classes}"/>
        <mkdir dir="${scala.test.classes}"/>
    </target>

    <target name="test.java.compile" depends="init.buildall,dist,test.init.compile">
        <echo message="Sting: Compiling test cases!"/>
        <javac fork="true" memoryMaximumSize="512m" destdir="${java.test.classes}" debug="true" optimize="on">
            <src path="${java.test.sources}"/>
            <classpath>
                <path refid="external.dependencies" />
                <pathelement location="${java.classes}"/>
                <pathelement location="lib/testng-5.14.1.jar"/>
            </classpath>
        </javac>
    </target>

    <target name="test.scala.compile" depends="test.java.compile,scala.compile" if="scala.include">
        <echo message="Scala: Compiling test cases!"/>
        <scalac fork="true" jvmargs="-Xmx512m" srcdir="${scala.test.sources}" destdir="${scala.test.classes}" deprecation="yes" unchecked="yes">
            <include name="**/*.scala"/>
            <exclude name="**/gridengine/**" unless="include.gridengine" />
            <classpath>
                <path refid="scala.dependencies"/>
                <pathelement location="${scala.test.classes}"/>
                <pathelement location="${java.test.classes}"/>
                <pathelement location="lib/testng-5.14.1.jar"/>
            </classpath>
        </scalac>
    </target>

    <target name="test.compile" depends="test.java.compile,test.scala.compile">
    </target>

    <!-- new scala target -->
    
    <target name="scala" description="build the scala directory">
        <antcall target="scala.jar" inheritAll="false">
            <param name="scala.target" value="core" />
        </antcall>
    </target>
    
    <!-- ***************************************************************************** -->
    <!-- ***********               Tests and associated tasks                ********* -->
    <!-- ***************************************************************************** -->
    <!-- where to put reports and tests-->
    <property name="report" value="${build.dir}/report"/>
    <property name="java.test.classes" value="${build.dir}/java/testclasses"/>
    <property name="test.output" value="${dist.dir}/test"/>
    <property name="java.test.sources" value="java/test"/>
    <property name="scala.test.classes" value="${build.dir}/scala/testclasses"/>
    <property name="scala.test.sources" value="scala/test"/>
    <!-- provide a ceiling on the memory that unit/integration tests can consume. -->
    <property name="test.maxmemory" value="4g"/>

    <!-- TEST -->
    <macrodef name="run-test">
        <attribute name="testtype"/>
        <sequential>
            <!-- Get the pipeline run type.  Default to dry.  -->
            <condition property="pipeline.run" value="dry" else="${pipeline.run}">
                <equals arg1="${pipeline.run}" arg2="$${pipeline.run}" />
            </condition>

            <mkdir dir="${report}/@{testtype}"/>
            <echo message="Sting: Running @{testtype} test cases!"/>
            <taskdef resource="testngtasks" classpath="lib/testng-5.14.1.jar"/>
            <testng outputDir="${report}/@{testtype}"
                    haltOnFailure="false" failureProperty="test.failure"
                    verbose="2"
                    workingDir="${basedir}"
                    useDefaultListeners="false"
                    listeners="org.testng.reporters.FailedReporter,org.testng.reporters.JUnitXMLReporter,org.broadinstitute.sting.StingTextReporter">
                <jvmarg value="-Xmx${test.maxmemory}" />
                <jvmarg value="-Djava.awt.headless=true" />
                <jvmarg value="-Dpipeline.run=${pipeline.run}" />
<!--                 <jvmarg value="-Xdebug"/> -->
<!--                 <jvmarg value="-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"/> -->
                <classpath>
                    <path refid="external.dependencies" />
                    <pathelement location="${java.classes}" />
                    <pathelement location="${scala.classes}" />
                    <pathelement location="${java.test.classes}" />
                    <pathelement location="${scala.test.classes}" />
                </classpath>

                <classfileset dir="${java.test.classes}" includes="**/@{testtype}.class"/>
                <classfileset dir="${scala.test.classes}" includes="**/@{testtype}*.class" />
            </testng>

            <!-- generate a report for Bamboo or Hudson to read in -->
            <junitreport todir="${report}/@{testtype}">
                <fileset dir="${report}/@{testtype}">
                    <include name="*/*.xml"/>
                </fileset>
                <report format="noframes" todir="${report}/@{testtype}"/>
            </junitreport>
            <fail message="test failed" if="test.failure" />
        </sequential>
    </macrodef>


    <!-- our three different test conditions: Test, IntegrationTest, PerformanceTest -->
    <target name="test" depends="test.compile,tribble.test" description="Run unit tests">
        <condition property="ttype" value="*UnitTest" else="${single}">
            <not><isset property="single"/></not>
        </condition>
        <run-test testtype="${ttype}"/>
    </target>
    <target name="integrationtest" depends="test.compile" description="Run integration tests">
        <condition property="itype" value="*IntegrationTest" else="${single}">
            <not><isset property="single"/></not>
        </condition>
        <run-test testtype="${itype}"/>
    </target>
    <target name="performancetest" depends="test.compile" description="Run performance tests">
       <condition property="ptype" value="*PerformanceTest" else="${single}">
            <not><isset property="single"/></not>
        </condition>
        <run-test testtype="${ptype}"/>
    </target>
    <target name="pipelinetest" depends="test.compile" description="Run pipeline tests">
        <condition property="pipetype" value="*PipelineTest" else="${single}">
            <not><isset property="single"/></not>
        </condition>
        <run-test testtype="${pipetype}"/>
    </target>
    <target name="pipelinetestrun" depends="test.compile" description="Run pipeline tests">
        <property name="pipeline.run" value="run"/>
        <condition property="pipetype" value="*PipelineTest" else="${single}">
            <not><isset property="single"/></not>
        </condition>
        <run-test testtype="${pipetype}"/>
    </target>

    <!-- ***************************************************************************** -->
    <!-- ***********                     Tribble                             ********* -->
    <!-- ***************************************************************************** -->
    <!-- compile the library -->
    <target name="tribble.compile" description="compiles the tribble library">
        <echo message="Building the Tribble Library..."/>
        <ant antfile="build.xml" target="all" dir="${tribble.dir}" inheritAll="false"/>
    </target>

    <!-- build the jar -->
    <target name="tribble" description="Builds the tribble jar" depends="tribble.compile">
        <copy todir="lib">
                <fileset dir="${tribble.dir}/dist" includes="*.jar"/>
            </copy>
    </target>

    <!-- test tribble using the unit tests set in tribble -->
    <target name="tribble.test" description="runs the tribble tests" depends="tribble.compile" unless="single">
        <echo message="Testing the Tribble Library..."/>
        <ant antfile="build.xml" target="test" dir="${tribble.dir}" inheritAll="false"/>
    </target>

    <!-- clean tribble -->
    <target name="tribble.clean" description="cleans the tribble library">
        <echo message="Cleaning the Tribble Library..."/>
        <ant antfile="build.xml" target="clean" dir="${tribble.dir}" inheritAll="false"/>
    </target>
    <!-- ***************************************************************************** -->

    <target name="clean.javadoc">
        <delete dir="javadoc"/>
        <delete dir="scaladoc"/>
    </target>

    <target name="javadoc" depends="init.buildall,resolve,queue-extensions.generate,init.scala.compile" description="generates javadoc">
        <mkdir dir="javadoc"/>
        <javadoc destdir="javadoc"
                 classpathref="external.dependencies">
            <sourcepath path="${java.source.dir}"/>
            <sourcepath path="${external.dir}"/>
        </javadoc>
        <mkdir dir="scaladoc"/>
        <scaladoc srcdir="" destdir="scaladoc" classpathref="scala.dependencies" deprecation="yes" unchecked="yes">
            <src path="${scala.source.dir}"/>
            <src path="${queue-extensions.source.dir}"/>
            <include name="**/*.scala"/>
        </scaladoc>
    </target>

    <!-- Unzip all classes from their current locations and assemble them in a staging directory -->
    <target name="stage" description="stage files for distribution">
        <mkdir dir="staging"/>
        <unjar dest="staging" overwrite="false">
          <fileset dir="${dist.dir}">
            <patternset refid="dependency.mask" />
          </fileset>
        </unjar>
    </target>

    <!-- Build a package consisting of all supporting files -->
    <target name="package" depends="dist,stage" description="bundle up an executable for distribution">
      <mkdir dir="dist/packages" />
      <xslt destdir="dist/packages" style="packages/CreatePackager.xsl" useImplicitFileset="false">
          <flattenmapper/>
          <fileset dir="${package.xml.dir}">
              <include name="${executable}.xml" />
          </fileset>

          <fileset dir="${external.dir}" erroronmissingdir="false">
              <include name="*/${executable}.xml" />
          </fileset>

      </xslt>
      <ant antfile="${dist.dir}/packages/${executable}.xml" target="package" />
    </target>

    <target name="release" depends="package" description="release a build, putting each file in a location specified by the package">
      <ant antfile="${dist.dir}/packages/${executable}.xml" target="release" />      
    </target>

    <!-- Build a subset of picard with only those classes we need by completely abusing the packaging system -->
    <!-- TODO: Reuse as much as possible of the 'stage' and 'package' targets -->
    <target name="build-picard-private" depends="resolve">
      <!-- Build out a classpath -->
      <pathconvert property="required.picard.jars" pathsep=":">
        <fileset dir="${basedir}">
	     <include name="staging" />
	     <include name="lib/picard-*.*.*.jar" />
	     <include name="lib/sam-*.jar" />
	   </fileset>
      </pathconvert>
      <echo message="required.picard.jars=${required.picard.jars}" />

      <!-- Stage picard-private -->
      <delete dir="staging" />
      <mkdir dir="staging" />
      <unjar src="${picard.dist.dir}/picard-private.jar" dest="staging" overwrite="true" />

      <!-- Use the packaging system to extract parts of picard-private we need -->
      <mkdir dir="${dist.dir}/packages" />
      <xslt in="packages/PicardPrivate.xml" out="${dist.dir}/packages/BuildPicardPrivate.xml" style="packages/CreatePackager.xsl" />
      <ant antfile="${dist.dir}/packages/BuildPicardPrivate.xml">
	    <property name="additional.jars" value="${required.picard.jars}" />
      </ant>
    </target>

    <!-- ******************************************************************************** -->
    <!-- Find bug tasks                                                                   -->
    <!-- ******************************************************************************** -->
    <path id="findbugs.classpath">
      <fileset dir="lib" erroronmissingdir="true" includes="*.jar"/>
    </path>
    <target         name="findbugs" depends="dist">
        <antcall    target  ="resolve">
            <param  name    ="ivy.conf" value="findbugs"/>
        </antcall>
        <!-- setup the taskdef, telling ant where to find the defined task for ant -->
        <taskdef name="findbugs" classname="edu.umd.cs.findbugs.anttask.FindBugsTask" classpathref="findbugs.classpath"/>
        <!-- what should findbug look at: we want to aim it at the GATK.jar -->
        <findbugs       home="${findbugs.home}"
                        output="xml"
                        outputFile="${build.dir}/findbugs.xml"
                        classpathref="findbugs.classpath"
                        debug="false">
         <auxClasspath>
                <fileset dir="dist" includes="**/*.jar" excludes="**/GenomeAnalysisTK.jar"/>            
         </auxClasspath>
         <sourcePath    path="../java/src" />
         <class         location="dist/GenomeAnalysisTK.jar" />
       </findbugs>
    </target>

    <target name="clean" description="clean up" depends="tribble.clean,clean.javadoc">
        <delete dir="out"/>
        <delete dir="${build.dir}"/>
        <delete dir="lib"/>
        <delete dir="staging"/>
        <delete dir="${dist.dir}"/>
        <delete dir="pipelinetests"/>
        <!-- When we clean, make sure to clean out tribble as well -->
        <ant antfile="tribble/build.xml" target="clean"/>
    </target>

    <!-- Build gsalib R module -->
    <target name="gsalib">
      <exec executable="R" failonerror="true">
        <arg line="R CMD INSTALL -l R/ R/src/gsalib/" />
      </exec>
    </target>
</project>
