<?xml version="1.0" encoding="UTF-8"?>

<!-- build.xml is autogenerated.  buildExamplesTemplate.xml is used to produce a
     customized build.xml for each autogenerated X3D example archive build.xml -->

<!--
  Copyright (c) 1995-2023 held by the author(s).  All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer
      in the documentation and/or other materials provided with the
      distribution.
    * The names of the Web3D Consortium (https://www.web3D.org),
      Naval Postgraduate School (NPS) (https://www.nps.edu),
      Modeling Virtual Environments and Simulation (MOVES) Institute
      (https://MovesInstitute.nps.edu) and
      the names of its contributors may not be used to endorse or
      promote products derived from this software without specific
      prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-->

<project name="X3D examples: Savage" default="all" basedir=".">
    <description>Builds and tests the X3D Examples Savage archive using Ant</description>

    <!-- properties common to all build files, customized for this archive ============================== -->

    <property name="archive.name"                    value="Savage"/>
    <property name="archive.site"                    value="https://savage.nps.edu/"/>
    <property name="archive.path"                 location="."/>

    <!-- ConformanceNist and Savage* archives have 2-level catalog structure, others have single-directory catalog structure -->
    <property name="numberOfSections"             location="2"/>
    <property name="subdir"                       location="*/*"/>

    <fileset id="x3dScenes" dir="." includes="*/*/*.x3d" excludes="_archive/*.*,**/_archive/*.*,_schematron/*.*,**/_schematron/*.*,**/hide/*,**/**/hide/*,**/InstallingCortonaBrowserAsPowerpointControl_files/*.*,**/build.xml,**/nbproject/**/*.xml,**/configuration/**/*.*,**/*Canonical.xml,**/*.nrrd,**/XvlShell.*"/>
    <fileset id="xmlFiles"  dir="." includes="*/*/*.xml"  excludes="_archive/*.*,**/_archive/*.*,_schematron/*.*,**/_schematron/*.*,**/hide/*,**/**/hide/*,**/InstallingCortonaBrowserAsPowerpointControl_files/*.*,**/build.xml,**/nbproject/**/*.xml,**/configuration/**/*.*,**/*Canonical.xml,**/*.nrrd,**/XvlShell.*"/>
    <fileset id="jsFiles"   dir="." includes="*/*/*.js"   excludes="_archive/*.*,**/_archive/*.*,_schematron/*.*,**/_schematron/*.*,**/hide/*,**/**/hide/*,**/InstallingCortonaBrowserAsPowerpointControl_files/*.*,**/build.xml,**/nbproject/**/*.xml,**/configuration/**/*.*,**/*Canonical.xml,**/*.nrrd,**/XvlShell.*"/>

    <!-- properties common to all build files and archives ======================================== -->

    <property environment="env"/>

    <!-- java jvmarg parameters ignored on server unless forked -->
    <!-- Xj3D converter tends to lock up Netbeans unless forked -->
    <property name="fork"                      value="true"/>
    
    <!-- https://ant.apache.org/manual/Tasks/exec.html -->
    <property name="timeout"                   value="600000" description="600000 msec = 10 min"/>

    <!-- ignoreSetupDownloadErrors can be overridden by Jenkins configuration, ensure initialized by previous invocations -->
    <property name="ignoreSetupDownloadErrors" value="true"/>

    <!-- Developers note: Netbeans default path for Ant is built, if override needed go to    -->
    <!-- Netbeans > Tools > Options > Java > Ant                                              -->
    <!-- and then pointing to C:\apache-ant-1.10.1 (or somesuch locally installed directory)  -->
    <!-- Further details are available at https://savage.nps.edu/Savage/developers.html#Ant   -->

    <!-- ANT Contrib archive is online at https://sourceforge.net/projects/ant-contrib/files   -->
    <!-- Must have ant-contrib-1.0b3.jar in ANT_HOME/lib (or else specify path, as below)     -->
    <taskdef resource="net/sf/antcontrib/antlib.xml" classpath="lib/ant-contrib-1.0b3.jar"/>

    <!-- jslint4java: a Java wrapper around Douglas Crockford's jslint tool. -->
    <!-- https://code.google.com/p/jslint4java -->
    <!-- https://code.google.com/archive/p/jslint4java -->
    <!-- http://kaatz-media.com/2011/10/06/uberprufen-von-javascript-dateien-ant-und-jslint-jenkins-using-ant-on-jenkins-for-jslint -->
    <!-- TODO bug report: https://code.google.com/p/jslint4java/issues/detail?id=101 -->
    <property name="jslint.jar"     value="lib/jslint4java-2.0.5.jar"/>
    <taskdef name="jslint"
        classname="com.googlecode.jslint4java.ant.JSLintTask"
        classpath="${jslint.jar}" />
    <property name="jslint.options" value="white"/>
    <!-- unused options: ass,bitwise,browser,closure,continue,debug,devel,eqeq,es5,evil,forin,indent,maxerr,maxlen,newcap,node,nomen,passfail,plusplus,predef,properties,regexp,rhino,sloppy,stupid,sub,todo,unparam,vars,warnings, -->

	<!-- https://github.com/fge/json-schema-validator -->
	<!-- https://www.jsonschemavalidator.net -->
	<!-- https://stackoverflow.com/questions/22867521/how-to-run-json-schema-validator-from-the-command-line -->
	<!-- fix double-hyphen switch when running on command line: -->
	<!-- java -jar lib/json-schema-validator-2.2.6-lib.jar - -help -->
	<!-- java -jar lib/json-schema-validator-2.2.6-lib.jar - -syntax ../../specifications/x3d-3.3-JSONSchema.json -->
	<!-- java -jar lib/json-schema-validator-2.2.6-lib.jar ../../specifications/x3d-3.3-JSONSchema.json test/HelloWorld.json -->
    <!-- https://github.com/java-json-tools/json-schema-validator/issues/287#issuecomment-543603403 -->
    <!-- https://github.com/java-json-tools/json-schema-validator/blob/master/README.md -->
    <!-- https://mvnrepository.com/artifact/com.github.java-json-tools/json-schema-validator -->
    <!-- only supports JSON Schema v4, not draft 2019 09 -->
    <!-- trouble report json-schema-validator-2.2.11.jar at https://github.com/java-json-tools/json-schema-validator/issues/287#issuecomment-544100447 -->
    <property name="json-schema-validator.jar"     value="lib/json-schema-validator-2.2.6-lib.jar"/>

    <!-- https://stackoverflow.com/questions/919692/how-to-execute-xslt-2-0-with-ant -->
    <!-- https://sourceforge.net/projects/saxon/files/Saxon-HE jar download handled in X3DJSAIL build -->
    <!-- https://sourceforge.net/projects/saxon/files/Saxon-HE/11/Java/ -->
    <!-- https://www.saxonica.com/documentation10/#!about/gettingstarted/gettingstartedjava -->
    <!-- SaxonHE 11 (java.lang.NoClassDefFoundError: org/xmlresolver/Resolver) https://saxonica.plan.io/boards/3/topics/8478?r=8480 -->
    <property name="saxon.dir"        location="lib" description="relative path from archive directory"/>
    <property name="saxon.jar"           value="saxon-he-11.4.jar"/><!-- previously saxon-he-11.3.jar saxon-he-11.2.jar saxon-he-10.6.jar saxon9he.jar -->
    <property name="xmlresolver.jar"     value="xmlresolver-4.4.3.jar"/><!-- required with saxon-he-11+.jar -->
    <property name="saxon.classpath" value="${saxon.dir}/${saxon.jar};.${saxon.dir}/${xmlresolver.jar};."/>

    <!-- compiled stylesheets are no longer supported as of saxon 9.4 -->
<!--<property name="saxononicaSA.dir" location="C:/java/saxonsa9-1-0-6j"/> not actively used -->

    <property name="c14n.dir"            value="../../../tools/canonical/dist/lib"/>
    <property name="c14n.jar"            value="X3dC14n.jar"/>
    <!-- https://logging.apache.org/log4j/2.x/manual/api.html -->
    <property name="log4j.dir"        location="../../../tools/canonical/lib"/>
    <property name="log4j-api.jar"       value="log4j-api-2.17.1.jar"/>
    <property name="log4j-core.jar"      value="log4j-core-2.17.1.jar"/>

    <property name="stylesheet.dir"   location="../../../stylesheets"/>
    <property name="local.dir"        location="."/>
	
    <!-- ensure backwards compatibility to specified version of Java -->
    <property name="java.source"                    value="17"/><!-- 1.8 is strictest, 15 or higher allows use of """text blocks""" for Script CDATA -->
    <property name="java.target"                    value="17"/>
    
    <property name="javac.verbose"                  value="false"/>
    <property name="java.classes.dir"               value="classes"/>
    <property name="x3djsail.dir"                   value="../../../stylesheets/java"/>
    <property name="x3djsail.stylesheets.dir"       value="${x3djsail.dir}/jars"/>
    <property name="jsai.classes.archive.jar.name"  value="X3DJSAIL.4.0.classes.jar"/>
    <property name="jsai.full.archive.jar.name"     value="X3DJSAIL.4.0.full.jar"/>

    <property name="javadoc.additionalparam" value=""/>
    <property name="javadoc.author"          value="Don Brutzman brutzman@nps.edu"/>
    <property name="javadoc.dir"             value="javadoc"/>
    <property name="javadoc.encoding"        value="ISO-8859-1"/>
	<!-- TODO insert archive name in mailto subject line or body -->
    <property name="javadoc.copyright"       value="Copyright &#169;2005-2021 &lt;a href='https://www.web3d.org'&gt;Web3D Consortium&lt;/a&gt; under an &lt;a href='../../../../license.html'&gt;open-source license&lt;/a&gt;, free for any use. &lt;a href='mailto:x3d-public@web3D.org,brutzman@nps.edu?subject=X3D%20Examples%20Archive%20X3DJSAIL%20feedback'&gt;Feedback&lt;/a&gt; is welcome."/>
    <property name="javadoc.noindex"         value="false"/>
    <property name="javadoc.nonavbar"        value="false"/>
    <property name="javadoc.notree"          value="false"/>
    <property name="javadoc.private"         value="false"/>
    <property name="javadoc.splitindex"      value="true"/>
    <property name="javadoc.breakiterator"   value="true"/>
    <property name="javadoc.use"             value="true"/><!-- Create class and package usage pages -->
    <property name="javadoc.version"         value="true"/>
	
    <property name="pyjnius.X3DautoclassPath" location="${x3djsail.dir}/src/python/pyjnius"/>
    
    <!-- https://stackoverflow.com/questions/20970732/jnius-1-1-import-error -->
    <!-- https://pyjnius.readthedocs.io/en/stable/installation.html -->
    <!-- TODO other OS variants needed? -->
    <property name="pyjnius.configurationPath" location="${env.JAVA_HOME}/jre/bin/server;${env.Path}"/><!-- help pyjnius find jvm.dll -->
    
    <property name="arq" location="${env.JENA_HOME}/bat/arq.bat" description="executable invocation, bat/arq.bat or bin/arq"/>
    <property name="semantics.dir" location="../../../../semantics"/>
    
    <!--            xml.catalog.dir is found in ${X3dDtdsSchemas.dir} -->
    <property name="xml.catalog.file" value="OasisXmlCatalogX3D.xml"/>
    
    <property name=   "python" value="python" description="local executable"/>
    
    <property name=   "node.exe" value="node.exe"/>
    
    <!-- ======================================== -->
    <!-- Xj3D internal paths for finding OS-specific /natives files, adapted from from NPS-branch build_nps.xml and build.properties -->

    <target name="platformInitialize" depends="platformType,initializeWindows,initializeUnix,initializeMac"/>
    <target name="platformType">
        <condition property="isWindows">
            <os family="windows"/>
        </condition>
        <condition property="isMac">
            <os family="mac"/>
        </condition>
        <!-- Based on Apache Ant user-manual example -->
        <condition property="isUnixNotMac">
            <and>
                <os family="unix"/>

                <not>
                    <equals arg1="${os.name}" arg2="Mac OS X"/>
                </not>

            </and>
        </condition>
    </target>

    <!-- relative paths, use value="" vice location -->
    <property name="natives.dir"         value="natives"/>
    <property name="native.library.path" value="${natives.dir}/${os.name}/${os.arch}"/>

    <target name="initializeCommon">
        <echo message="=============================="/>
        <echo message="build.xml property $native.library.path=${native.library.path}"/>
        <echo message="=============================="/>
        <echo message="java -XshowSettings:properties"/>
        <java classname="ignoreClassNotFoundExceptionJustShowProperties">
            <jvmarg value="-XshowSettings:properties"/>
        </java>
        <echo message="=============================="/>
        <echo message="check Xj3D jars list, if installed:"/>
        <if>
            <not>
                <equals arg1="${xj3d.jars.all}" arg2=""/>
            </not>
            <then>
                <pathconvert property="xj3d.jars.list" refid="xj3d.jars.all" pathsep="${line.separator}" setonempty="true">
                    <!-- https://stackoverflow.com/questions/1456852/how-can-i-print-a-fileset-to-a-file-one-file-name-per-line -->
                    <!-- Add this if you want the path stripped -->
                    <mapper>
                        <flattenmapper />
                    </mapper>
                </pathconvert>
                <echo message="build.xml property $xj3d.jars.list:"/>
                <echo message="${xj3d.jars.list}"/>
            </then>
            <else>
                <echo message=" ... not available at ${xj3d.jars.all}"/>
            </else>
        </if>
        <echo message="=============================="/>
    </target>
    <target name="initializeMac" if="isMac" depends="platformType,initializeCommon">
        <!-- operating system-specific commands here -->
    </target>
    <target name="initializeWindows" if="isWindows" depends="platformType,initializeCommon">
        <!-- operating system-specific commands here -->
    </target>
    <target name="initializeUnix" if="isUnixNotMac" depends="platformType,initializeCommon">
        <!-- operating system-specific commands here -->
    </target>

    <!-- ======================================== -->

<!--
# ******************************************************************************
# NOTE: The convention here for determining OS architecture assumes Intel (x86)
# CPUs only.  For non-traditional: amd64, sparc, i386, etc., this convention
# will not work requiring a manual rename for the path to the native binaries.

# https://www.oracle.com/technetwork/java/hotspotfaq-138619.html#64bit_detection
-->
<!--
    <property name="os.architecture.bitness"  value="x86_${sun.arch.data.model}"/>
    <property name="natives.dir"              value="natives"/>
    <property name="mac.library.path"         value="${natives.dir}"/>
    <property name="win.library.path"         value="${natives.dir}/${os.architecture.bitness}/win"/>
    <property name="linux.library.path"       value="${natives.dir}/${os.architecture.bitness}/linux"/>

    <target name="initializeMac" if="isMac" depends="platformType">
        <property name="native.library.path" value="${mac.library.path}"/>
    </target>
    <target name="initializeWindows" if="isWindows" depends="platformType">
        <property name="native.library.path" value="${win.library.path}"/>
    </target>
    <target name="initializeUnix" if="isUnixNotMac" depends="platformType">
        <property name="native.library.path" value="${linux.library.path}"/>
    </target>
-->
    <!-- ======================================== -->

    <!-- Savage Developers Guide, Xj3D viewer: NPS source documentation https://savage.nps.edu/Savage/developers.html#Xj3D -->
    <!-- Xj3D v2.3 git        version-control source at https://gitlab.nps.edu/Savage/xj3d  -->
    <!-- Xj3D v2.1 subversion version-control source at https://svn.code.sf.net/p/xj3d/code -->

    <!-- all Xj3D.nps jars need to be in same directory for fileset to work properly. -->
    <!-- Prerequisite:  run build.xml 'dist' or 'all' target to get the .jars built and in the right place -->
    <!-- TODO in order for server-side jenkins to also work, they are retrieved to same directory -->
    <property name="xj3d.dir"            location="C:/x-nps-gitlab/xj3d"/>        <!-- formerly C:/xj3d-code/branches/NPS, C:/j3d-code/xj3d, C:/xj3d-code/xj3d -->
    <property name="xj3d.dir.jars"       location="${xj3d.dir}/jars"/>            <!-- C:/j3d-code/xj3d/jars -->
    <property name="xj3d.3rdparty.jar"   value="xj3d-2.3-3rdparty-nps.jar"/>      <!-- C:/j3d-code/xj3d/jars -->
    <property name="xj3d.jar"            value="xj3d-2.3-nps.jar"/>               <!-- C:/j3d-code/xj3d/jars -->
    <property name="xj3d.browser.jar"    value="xj3d.browser_2.3.0-nps.jar"/>     <!-- C:/j3d-code/xj3d/jars -->
    <property name="xj3d.cadfilter.jar"  value="xj3d.cadfilter_2.3.0-nps.jar"/>   <!-- C:/j3d-code/xj3d/jars -->
    <property name="xj3d.replica.jar"    value="xj3d.replica_2.3.0-nps.jar"/>     <!-- C:/j3d-code/xj3d/jars -->
    <!-- see HelloWorld task for path diagnostic messages -->
    <fileset dir="${xj3d.dir.jars}" id="xj3d.jars.all">
        <include name="${xj3d.jar}"/>
        <include name="${xj3d.browser.jar}"/>
        <include name="${xj3d.cadfilter.jar}"/>
        <include name="${xj3d.replica.jar}"/>
        <include name="${xj3d.3rdparty.jar}"/>
        <include name="jhall.jar"/><!-- javahelp -->
        <include name="jogamp-fat.jar"/><!-- includes all native OS dlls, etc. -->
    </fileset>

    <!-- site to download latest xj3d jars -->
    <property name="xj3d.jar.site"        value="https://savage.nps.edu/Xj3D.nps/jars"/>
    <!-- prior download location:                https://sourceforge.net/p/xmsf/code/HEAD/tree/trunk/AuvWorkbench/lib/xj3d -->

    <!-- subversion checkout address to download latest x3d configuration files -->
    <property name="x3d.sourceforge.site" value="https://svn.code.sf.net/p/x3d/code/www.web3d.org"/>
    <property name="use.sourceforge.site" value="true"/>

    <property name="X3dSchematronValidityChecks.dir" location="../../../tools/schematron"/>
    <property name="X3dSchematronValidityChecks"        value="X3dSchematronValidityChecks"/>
    <property name="SvrlReportText"                     value="SvrlReportText"/>

    <property name="CreateContentCatalog.dir" location="../../../tools/CreateContentCatalog"/>
    <property name="X3dDtdsSchemas.dir"       location="../../../../specifications"/>
    <!-- n.b. resolver.jar maintained independently of saxon xmlresolver.jar dependency -->
    <property name="resolver.dir"             location="${env.ANT_HOME}/lib"/>
    <property name="resolver.jar"             value="xml-resolver-1.2.jar"/>
    <length property="resolver.jar.length" file="${resolver.dir}/${resolver.jar}"/>
    <!-- original alternative to ant: https:///xerces.apache.org/mirrors.cgi XML Commons Resolver Version 1.2 - zip -->

<!--
OASIS XML Catalog standard references
         https:///www.oasis-open.org/specs/index.php#xmlcatalogs
         https:///www.oasis-open.org/committees/download.php/14810/xml-catalogs.pdf
Apache Ant validation and resolver references
         https:///ant.apache.org/manual/Types/xmlcatalog.html
         https:///ant.apache.org/manual/Tasks/xmlvalidate.html
         https:///ant.apache.org/manual/Tasks/schemavalidate.html
         https:///ant.apache.org/manual/install.html#librarydependencies
         http://www.saxproject.org/apidoc/org/xml/sax/package-summary.html#package_description
         https:///xerces.apache.org/xerces-j/features.html
         https:///xerces.apache.org/xerces-j/properties.html
Key references:
         https:///xml.apache.org/commons/components/resolver (then see ${resolver.jar})
         https:///xerces.apache.org/xml-commons
         https:///www.apache.org/dist/xerces/xml-commons
-->
    <xmlcatalog id="X3dCatalog">
        <dtd    publicId="ISO//Web3D//DTD X3D 3.0//EN"                                  location="${X3dDtdsSchemas.dir}/x3d-3.0.dtd"/>
        <dtd    publicId="ISO//Web3D//DTD X3D 3.1//EN"                                  location="${X3dDtdsSchemas.dir}/x3d-3.1.dtd"/>
        <dtd    publicId="ISO//Web3D//DTD X3D 3.2//EN"                                  location="${X3dDtdsSchemas.dir}/x3d-3.2.dtd"/>
        <dtd    publicId="ISO//Web3D//DTD X3D 3.3//EN"                                  location="${X3dDtdsSchemas.dir}/x3d-3.3.dtd"/>
        <dtd    publicId="http://www.web3d.org/specifications/x3d-3.0.dtd"              location="${X3dDtdsSchemas.dir}/x3d-3.0.dtd"/>
        <dtd    publicId="http://www.web3d.org/specifications/x3d-3.1.dtd"              location="${X3dDtdsSchemas.dir}/x3d-3.1.dtd"/>
        <dtd    publicId="http://www.web3d.org/specifications/x3d-3.2.dtd"              location="${X3dDtdsSchemas.dir}/x3d-3.2.dtd"/>
        <dtd    publicId="http://www.web3d.org/specifications/x3d-3.3.dtd"              location="${X3dDtdsSchemas.dir}/x3d-3.3.dtd"/>
        <dtd    publicId="http://www.web3d.org/specifications/x3d-4.0.dtd"              location="${X3dDtdsSchemas.dir}/x3d-4.0.dtd"/>
        <entity publicId="http://www.web3d.org/specifications/x3d-3.0.xsd"              location="${X3dDtdsSchemas.dir}/x3d-3.0.xsd"/>
        <entity publicId="http://www.web3d.org/specifications/x3d-3.1.xsd"              location="${X3dDtdsSchemas.dir}/x3d-3.1.xsd"/>
        <entity publicId="http://www.web3d.org/specifications/x3d-3.2.xsd"              location="${X3dDtdsSchemas.dir}/x3d-3.2.xsd"/>
        <entity publicId="http://www.web3d.org/specifications/x3d-3.3.xsd"              location="${X3dDtdsSchemas.dir}/x3d-3.3.xsd"/>
        <entity publicId="http://www.web3d.org/specifications/x3d-4.0.xsd"              location="${X3dDtdsSchemas.dir}/x3d-4.0.xsd"/>
        <!-- Transitional DTD, versions 3.0 and 3.1 only -->
        <dtd    publicId="file:///www.web3d.org/TaskGroups/x3d/translation/x3d-3.0.dtd" location="${X3dDtdsSchemas.dir}/x3d-3.0.dtd"/>
        <dtd    publicId="file:///www.web3d.org/TaskGroups/x3d/translation/x3d-3.1.dtd" location="${X3dDtdsSchemas.dir}/x3d-3.1.dtd"/>
        <!-- fallback solution, depends on ${resolver.jar} availability -->
        <xmlcatalog>
            <catalogpath location="${X3dDtdsSchemas.dir}/${xml.catalog.file}" description="external path to same definitions"/>
        </xmlcatalog>
    </xmlcatalog>

    <!-- Ant macro definitions common to all build files, customized for this archive ============================== -->

    <!-- excerpted/adapted from "SAXON XSLT Processing with Ant" by James Fuller, http://ablog.apress.com/?p=753 -->
    <!-- https:///www.saxonica.com/documentation9.0/using-xsl/commandline.html                                     -->
    <macrodef name="Saxon11" description="Invoke XSLT transformation on passed scene using passed stylesheet">
        <attribute name="scene"/>
        <attribute name="stylesheet"/>
        <attribute name="suffix" default=""/>
        <attribute name="extension"/>
		<!-- https:///www.saxonica.com/html/documentation/configuration/config-features.html -->
        <attribute name="expand" default="off"/> <!-- https://www.saxonica.com/html/documentation/configuration/config-features.html -->
        <!-- parameterPair1 must have a legal value or saxon fails mysteriously while running under jenkins! java.lang.StringIndexOutOfBoundsException: String index out of range: 0 -->
        <!-- parameterPair1,2,3 must have some kind of string under Java 17 and saxon11 java.lang.StringIndexOutOfBoundsException: String index out of range: 0 -->
        <attribute name="parameterPair1" default="dummy1=0"/>
        <attribute name="parameterPair2" default="dummy2=0"/>
        <attribute name="parameterPair3" default="dummy3=0"/>
        <sequential>
            <!--
			<echo message="Saxon11 processing @{scene}@{suffix}.@{extension} using @{stylesheet}.xslt, -catalog:${X3dDtdsSchemas.dir}/${xml.catalog.file}"/>
			<echo message="... -expand:'@{expand}' parameterPair1='@{parameterPair1}' parameterPair2='@{parameterPair2}' parameterPair3='@{parameterPair3}'"/>
            -->
                    <!--<echo message="$saxon.classpath=${saxon.classpath}"/>-->
			<java classname="net.sf.saxon.Transform"
				  classpath="${saxon.classpath}"
				  fork="${fork}"
				  failonerror="false">
				<!-- TODO
                https://stackoverflow.com/questions/14165765/how-to-use-saxon-built-in-catalog-feature
                
				<jvmarg value="-Dxml.catalog.files=C:/www.web3d.org/specifications/OasisXmlCatalogX3D.xml"/>
				<jvmarg value="-Dxml.catalog.verbosity=4"/>
				use the Apache commons resolver for XML Catalog resolution of online DTD, schema addresses
                                https://sourceforge.net/projects/saxon
				https://www.saxonica.com/html/documentation/sourcedocs/xml-catalogs.html
				"How to use a catalog file:  Using catalogs with Saxon"
				https://www.sagehill.net/docbookxsl/UseCatalog.html
				download ${resolver.jar} from https://www.apache.org/dist/xerces/xml-commons (formerly https://xml.apache.org/commons/dist)
				unzip package and install ${resolver.jar} into classpath above,
				must also have CatalogManager.properties in CLASSPATH
				<arg value="-r:org.apache.xml.resolver.tools.CatalogResolver"/>
				<arg value="-x:org.apache.xml.resolver.tools.ResolvingXMLReader"/>
				<arg value="-y:org.apache.xml.resolver.tools.ResolvingXMLReader"/> -->
				<!-- <arg value="-t"/> saxon version and timing information -->
				<!-- <arg value="-T"/> trace (voluminous) -->
				<arg value="-warnings:recover"/> <!-- recover after writing a warning message -->
				<arg value="-s:@{scene}.x3d"/>                  <!--  input file -->
				<arg value="-o:@{scene}@{suffix}.@{extension}"/><!-- output file -->
				<arg value="-xsl:@{stylesheet}.xslt"/>  <!-- regular stylesheet -->
				<arg value="-dtd:off"/>                 <!-- DTD validation (on|off|recover); suppress creation of default DTD values, only use values in document -->
				<arg value="-expand:@{expand}"/>        <!-- whether to expand (i.e. add) DTD default values (on|off) -->
                                <arg value="-catalog:${X3dDtdsSchemas.dir}/${xml.catalog.file}"/> 
				<arg value="@{parameterPair1}"/>        <!-- parameter=value passed to stylesheet -->
				<arg value="@{parameterPair2}"/>
				<arg value="@{parameterPair3}"/>
			</java>
        </sequential>
    </macrodef>

    <macrodef name="canonicalX3D" description="convert scene.x3d to sceneCanonical.xml">
        <attribute name="scene"/>
        <!-- depends on "build all" in project X3D Tools: Canonicalization (C14N) -->
        <sequential>
            <java classname="org.web3d.x3d.tools.x3db.X3dCanonicalizer"
                  classpath="${c14n.dir}/${c14n.jar}"
                       fork="${fork}"
                failonerror="true">
                <arg value="@{scene}.x3d"/>
                <arg value="@{scene}Canonical.xml"/>
            </java>
            <echo message="check well-formedness of canonical form"/>
            <xmlvalidate file="@{scene}Canonical.xml" failonerror="false" warn="true" lenient="true"/>
            <echo message="check DTD validation  of canonical form"/>
            <xmlvalidate file="@{scene}Canonical.xml" failonerror="false" warn="true" lenient="false">
                <xmlcatalog refid="X3dCatalog"/>
                <!-- TODO get xmlcatalog working under jenkins
                <attribute name="http://xml.org/sax/features/validation" value="true"/>
                <attribute name="http://xml.org/sax/features/namespaces" value="true"/>
                -->
            </xmlvalidate>
            <!-- save prior version to _archive/ subdirectory, then copy canonicalized version as current version -->
            <copy file="@{scene}.x3d"           todir="_archive/"    overwrite="true" failonerror="true" verbose="true" preservelastmodified="true"/>
            <copy file="@{scene}Canonical.xml" tofile="@{scene}.x3d" overwrite="true" failonerror="true" verbose="true" preservelastmodified="true"/>
        </sequential>
    </macrodef>

    <macrodef name="X3dTidy" description="Perform X3dTidy modifications">
        <attribute name="scene"/>
        <attribute name="title"/>
        <sequential>
            <java classname="net.sf.saxon.Transform" classpath="${saxon.classpath}" fork="${fork}">
                <!-- https://www.saxonica.com/documentation9.5/using-xsl/commandline.html -->
                    <arg value="-warnings:recover"/> <!-- recover after writing a warning message -->
                    <!-- <arg value="-t"/> saxon version and timing information -->
                    <arg value="-s:@{scene}.x3d"/>
                    <arg value="-o:@{scene}Tidy.x3d"/>
                    <arg value="-xsl:${stylesheet.dir}/X3dTidy.xslt"/> <!--  regular stylesheet -->
                    <arg value="-dtd:recover"/> <!-- recover from failures -->
                    <arg value="-expand:on"/>   <!-- whether to expand (i.e. add) DTD default values (on|off) -->
                    <arg value="title=@{title}"/>
                    <arg value="conversionRequired=true"/>
                    <arg value="reviseCurrentDate=false"/><!-- best to let author decide, sometimes helpful for block updates -->
                    <arg value="fixMFStringQuotes=true"/>
                    <arg value="fixUrlAdditionHttpAddresses=true"/>
                    <arg value="appendMissingMetaLicense=true"/>
                    <arg value="licenseLink=../license.html"/>
                    <!-- numerous other parameters are available in X3dTidy.xslt -->
                    <!-- expand:on since DTD defaults needed -->
            </java>
            <echo message="now canonicalize X3dTidy output:"/>
            <java classname="org.web3d.x3d.tools.x3db.X3dCanonicalizer"
                  classpath="${c14n.dir}/${c14n.jar}"
                       fork="true"
                failonerror="false"><!-- must have fork=true for failonerror to proceed -->
                <arg value="@{scene}Tidy.x3d"/>
                <arg value="@{scene}TidyCanonical.xml"/>
            </java>
            <echo message="check well-formedness of X3dTidy canonicalized form"/>
            <xmlvalidate file="@{scene}TidyCanonical.xml" failonerror="false" warn="true" lenient="true"/>
            <echo message="check DTD validation  of X3dTidy canonicalized form"/>
            <xmlvalidate file="@{scene}TidyCanonical.xml" failonerror="false" warn="true">
                <xmlcatalog refid="X3dCatalog"/>
                <!-- TODO get xmlcatalog working under jenkins
                <attribute name="http://xml.org/sax/features/validation" value="true"/>
                <attribute name="http://xml.org/sax/features/namespaces" value="true"/>
                -->
            </xmlvalidate>
            <echo message="check schema validation of X3dTidy canonicalized form"/>
            <schemavalidate file="@{scene}TidyCanonical.xml" failonerror="false" fullchecking="false" lenient="false" warn="true">
                <xmlcatalog refid="X3dCatalog"/>
            </schemavalidate>
            <length property="@{scene}.length"          file="@{scene}.x3d"/>
            <length property="@{scene}Tidy.length" file="@{scene}TidyCanonical.xml"/>
            <!-- copy scenes even if length is unchanged since some modifications may have occurred, identical files are recognized as such by subversion -->
            <echo message="@{scene}.length=${@{scene}.length} bytes, @{scene}Tidy.length=${@{scene}Tidy.length} bytes"/>
            <!-- save prior version to _archive/ subdirectory, then copy canonicalized version as current version -->
            <copy file="@{scene}.x3d"                    todir="_archive/"    overwrite="true" failonerror="true"  verbose="true" preservelastmodified="true"/>
            <move file="@{scene}Tidy.x3d"           todir="_archive/"    overwrite="true" failonerror="true"  verbose="true" preservelastmodified="true"/>
            <!-- the following file might not exist if no canonicalization changes occurred, thus move is optional -->
            <move file="@{scene}TidyCanonical.xml" tofile="@{scene}.x3d" overwrite="true" failonerror="false" verbose="true" preservelastmodified="true"/>
            <echo message="=================================================="/>
        </sequential>
    </macrodef>

    <!-- target tasks common to all build files ===================================================================== -->
    <target name="all" depends="echo.timestamp,check.ant.java.versions,versions,clean.backups,clean.duplicates,clean.RoundTrip,clean.X3dTidy,commonSetup,validate.full,build,upload" description="clean backups, build, zip and upload this X3D archive">
        <echo message="Copying latest build.log.txt to subdirectory ${archive.name}/_archive/"/>
        <copy file="build.log.txt" todir="_archive/" overwrite="true" failonerror="false"/>
    </target>

    <target name="help" description="display build directions">
        <loadfile property="readmeFileContents" srcFile="README.txt" />
        <echo    message="${readmeFileContents}" />
        <echo />
    </target>

    <target name="echo.timestamp" description="output current date and time">
        <tstamp>
            <format property="time" pattern="HH:mm:ss"/>
        </tstamp>
        <tstamp>
            <format property="date" pattern="d MMMM yyyy"/>
        </tstamp>
        <echo message="timestamp ${time} on ${date}" />
    </target>

    <target name="saxon.help" description="display command-line settings">
        <echo message="$saxon.classpath=${saxon.classpath}"/>
        <java classname="net.sf.saxon.Transform"
              classpath="${saxon.classpath}"
              fork="${fork}"
              failonerror="false">
            <arg value="-?"/>
        </java>
    </target>

    <target name="all.record" description="build all for this X3D archive, record output to file">
        <tstamp>
            <format property="dateStamp" pattern="yyyyMMMMdd"/>
        </tstamp>
        <property name="build.out.filename" value="build.out.${archive.name}.${timestamp.DSTAMP}.txt"/>
        <delete file="${build.out.filename}"/>
        <echo message="logfile ${build.out.filename}"/>
        <echo message="logfile ${build.out.filename}" file="${build.out.filename}"/>
        <echo message=""       append="true"          file="${build.out.filename}"/>
        <record action="start" append="true"          name="${build.out.filename}"/>
        <antcall target="all"/>
        <record name="build.out.${archive.name}.${timestamp.DSTAMP}.txt" action="stop"/>
    </target>

    <target name="build.record" description="build this X3D archive, record output to file">
        <tstamp>
            <format property="dateStamp" pattern="yyyyMMMMdd"/>
        </tstamp>
        <property name="build.out.filename" value="build.out.${archive.name}.${timestamp.DSTAMP}.txt"/>
        <delete file="${build.out.filename}"/>
        <echo message="logfile ${build.out.filename}"/>
        <echo message="logfile ${build.out.filename}" file="${build.out.filename}"/>
        <echo message=""       append="true"          file="${build.out.filename}"/>
        <record action="start" append="true"          name="${build.out.filename}"/>
        <antcall target="build"/>
        <record name="build.out.${archive.name}.${timestamp.DSTAMP}.txt" action="stop"/>
        <antcall target="echo.timestamp"/>
    </target>

    <target name="build" depends="echo.timestamp,check.ant.java.versions,clean.duplicates,get.slideshowTools,commonSetup,processScenes,catalog,zip" description="build this X3D archive">
        <!-- note no validation occurs -->
        <antcall target="echo.timestamp"/>
        <echo message="build complete."/>
    </target>

    <target name="check.ant.java.versions" description="Check Apache Ant and Java versions">
       <echo message="ant.version=${ant.version}"/>
       <echo message="  java.home=${java.home}"/>
       <echo message=" saxon path=${saxon.dir}/${saxon.jar}"/>
       <echoproperties/>
       <fail message="Build requires Apache Ant version 1.7, 1.8, 1.9 or 1.10">
           <condition>
               <and>
                   <not>
                       <contains string="${ant.version}" substring="1.7"/>
                   </not>
                   <not>
                       <contains string="${ant.version}" substring="1.8"/>
                   </not>
                   <not>
                       <contains string="${ant.version}" substring="1.9"/>
                   </not>
                   <not>
                       <contains string="${ant.version}" substring="1.10"/>
                   </not>
               </and>
           </condition>
       </fail>
    </target>

    <target name="clean.all" depends="clean.backups,clean.duplicates,clean.RoundTrip,clean.X3dTidy,clean.Canonical.xml,clean.htmlPrettyPrintPages,clean.java,clean.schematron,clean.SVG,clean.wrl,clean.json,clean.x3dv,clean.x3db,clean.X3domXhtml,clean.X_ITE.html,clean.slideshowTools,clean.catalog.pages,clean.X3dTidy,clean.python,clean.turtle" description="clean out autogenerated files (only)">
        <echo message="clean/delete autogenerated ${archive.name} catalog pages and files matching *.x3d scenes: *.html *.wrl *.x3db *.x3dv *Canonical.xml (but do not clean autogenerated images under version control)"/>
        <!-- delete autogenerated directories, but not _archive directory -->
        <delete dir="_svg"        quiet="true" includeemptydirs="true" failonerror="false"/>
        <delete dir="_schematron" quiet="true" includeemptydirs="true" failonerror="false"/>
        <delete failonerror="false" includeemptydirs="true" verbose="true">
            <!-- <fileset dir="." includes="build.out*.txt"/> -->
            <fileset dir="." includes="ContentCatalog*.*"/>
            <fileset dir="." includes="newScene.*"/>
            <fileset dir="." includes="newHtmlPageWithX3dObject.html"/>
            <fileset dir="." includes="newECMAscript.js"/>
            <fileset dir="." includes="newX3dScript.java"/>
            <fileset dir="." includes="HelloWorld.*"/>
            <fileset dir="." includes="earth-topo*.*"/>
            <fileset dir="." includes="*.html" excludes="license.html"/>
            <fileset dir="." includes="*.wrl"/>
            <fileset dir="." includes="*.x3db"/>
            <fileset dir="." includes="*.x3dv"/>
            <fileset dir="." includes="*Canonical.xml"/>
            <fileset dir="." includes="Thumbs.db"/>
            <fileset dir="." includes="*.bak"/>
            <fileset dir="." includes="**/*.$$$$$$"/> <!-- escape $ as $$ -->
        </delete>
        <!-- clean jenkins subdirectories
        <delete dir="lib"         quiet="false" includeemptydirs="true" failonerror="false"/> -->
        <delete dir="stylesheets" quiet="false" includeemptydirs="true" failonerror="false"/>
    </target>

    <target name="clean.archiveSubdirectories" description="clean out duplicates in archive/ and _archive/ subdirectories">
        <echo message="clean/delete archive (backup) files for project ${archive.name}"/>
        <delete failonerror="false" includeemptydirs="true" verbose="true">
            <fileset dir="." includes="**/archive/**"/>
            <fileset dir="." includes="**/_archive/**"/>
        </delete>
    </target>

    <target name="clean.catalog.pages" description="clean out catalog-produced files  and schematron outputs">
        <echo message="clean/delete autogenerated catalog files and schematron outputs"/>
        <delete failonerror="false" includeemptydirs="true" verbose="true">
            <fileset dir=".">
                <include name="**/*Index.html"/>
                <include name="**/index.html"/>
                <include name="**/viewpointSlideshow.html"/>
                <include name="**/_schematron/*"/>
                <include name="**/_pages/*.html"/><!-- older versions -->
                <exclude name="**/*javadoc/**/*"/>
                <exclude name="SoundEffects/**/*"/>
                <exclude name="services/**/*"/>
                <exclude name="Installing*"/>
            </fileset>
        </delete>
        <delete failonerror="false" includeemptydirs="true"><!-- older versions -->
                <fileset dir="**/_pages"/>
                <fileset dir="**/_svg"/>
        </delete>
    </target>

    <target name="clean.media" description="clean out large files (warning, this included necessary files for scene operation)">
        <echo message="clean/delete sound, image and movie files"/>
        <delete failonerror="false" includeemptydirs="true" verbose="true">
                <fileset dir="." includes="**/*.wav"/>
                <fileset dir="." includes="**/*.gif"/>
                <fileset dir="." includes="**/*.jpg"/>
                <fileset dir="." includes="**/*.mpg"/>
                <fileset dir="." includes="**/*.mov"/>
                <fileset dir="." includes="**/*.ppt"/>
        </delete>
    </target>

    <target name="clean.backups" description="clean out unnecessary backup files (only)">
        <echo message="clean/delete backup files for project ${archive.name}"/>
        <delete failonerror="false" includeemptydirs="true" verbose="true">
            <fileset dir="." includes="**/_new_pretty_print.html"/>
            <fileset dir="." includes="**/_new_result.wrl"/>
            <fileset dir="." includes="**/_new_result.x3db"/>
            <fileset dir="." includes="**/_new_result.x3dv"/>
            <fileset dir="." includes="**/Thumbs.db"/>
            <fileset dir="." includes="**/*.bak"/>
            <fileset dir="." includes="**/hs_err_pid*.log"/>
            <fileset dir="." includes="**/manifest.mf"/>
            <fileset dir="." includes="**/*.$$$$$$"/> <!-- escape $ as $$ -->
            <fileset dir="." includes="**/*Canonical.x3d"/>
            <fileset dir="." includes="**/*Canonical.x3db"/>
            <fileset dir="." includes="**/*Canonical.x3dv"/>
            <fileset dir="." includes="**/*Canonical.wrl"/>
            <fileset dir="." includes="**/*Canonical.html"/>
            <!-- Xj3D Replica image-creation issue -->
            <fileset dir="." includes="**/*0001.png"/>
            <fileset dir="." includes="**/*0002.png"/>
            <fileset dir="." includes="**/*0003.png"/>
            <fileset dir="." includes="**/*0004.png"/>
            <fileset dir="." includes="**/*0005.png"/>
            <fileset dir="." includes="**/*0006.png"/>
            <fileset dir="." includes="**/*0007.png"/>
            <fileset dir="." includes="**/*0008.png"/>
            <fileset dir="." includes="**/*0009.png"/>
            <fileset dir="." includes="**/*_VP_Unnamed_1.png"/>
        </delete>
    </target>

    <!-- warning!  do not create .x3d file names that end in five or more numeric digits since X3D-Edit uses that as a temporary backup filename -->
    <target name="clean.duplicates" description="clean out duplicate files autogenerated by X3D-Edit, ending with 6 or more numeric values" depends="clean.RoundTrip">
        <echo message="clean/delete duplicate files autogenerated by X3D-Edit ending with 6 or more numeric values (*######.x3d)"/>
        <echo message="  including files matching *######.x3d scenes: *.html *.wrl *.x3db *.x3dv *Canonical.xml"/>
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="filename.prefix.duplicate"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*[0-9][0-9][0-9][0-9][0-9][0-9])(\.x3d|\.x3dv|\.x3db|\.wrl|\.html|Canonical\.xml)"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
                <if>
                    <equals arg1="${filename.prefix.duplicate}" arg2="" />
                    <then>
                        <!-- not a duplicate, ignore-->
                    </then>
                    <else>
                    <!--<echo>delete ${relative.path1}/${relative.path2}/${name.short}.html</echo> -->
                        <delete file="${relative.path1}/${relative.path2}/${filename.prefix.duplicate}.x3d"/>
                        <delete file="${relative.path1}/${relative.path2}/${filename.prefix.duplicate}.html"/>
                        <delete file="${relative.path1}/${relative.path2}/${filename.prefix.duplicate}.java"/>
                        <delete file="${relative.path1}/${relative.path2}/${filename.prefix.duplicate}.json"/>
                        <delete file="${relative.path1}/${relative.path2}/${filename.prefix.duplicate}.wrl"/>
                        <delete file="${relative.path1}/${relative.path2}/${filename.prefix.duplicate}.x3db"/>
                        <delete file="${relative.path1}/${relative.path2}/${filename.prefix.duplicate}.x3dv"/>
                        <delete file="${relative.path1}/${relative.path2}/${filename.prefix.duplicate}.xhtml"/>
                        <delete file="${relative.path1}/${relative.path2}/${filename.prefix.duplicate}Canonical.xml"/>
                        <delete file="${relative.path1}/${relative.path2}/${filename.prefix.duplicate}Cobweb.html"/>
                        <delete file="${relative.path1}/${relative.path2}/${filename.prefix.duplicate}X_ITE.html"/>
                    </else>
                </if>
            </sequential>
        </for>
    </target>

    <target name="clean.htmlPrettyPrintPages" description="clean out autogenerated pretty-print *.html files (only)">
        <echo message="clean/delete autogenerated pretty-print files matching *.x3d scenes: *.html "/>
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="name.short"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
            <!-- <echo>delete ${relative.path1}/${relative.path2}/${name.short}.html</echo> -->
                <delete file="${relative.path1}/${relative.path2}/${name.short}.html"/>
                <delete file="${relative.path1}/${relative.path2}/${name.short}.svg"/><!-- Extrusion crossSection diagram -->
            </sequential>
        </for>
        <echo message="consider clean.SVG if crossSection figures also need removal"/>
    </target>

    <target name="clean.X3domXhtml" description="clean out autogenerated *.xhtml files (only)">
        <echo message="clean/delete autogenerated pretty-print files matching *.x3d scenes: *.xhtml "/>
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="name.short"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
            <!-- <echo>delete ${relative.path1}/${relative.path2}/${name.short}X3dom.xhtml</echo> -->
                <delete file="${relative.path1}/${relative.path2}/${name.short}X3dom.xhtml"/>
            </sequential>
        </for>
    </target>

    <target name="clean.X_ITE.html" description="clean out autogenerated *X_ITE.html and *Cobweb.html files (only)">
        <echo message="clean/delete autogenerated pretty-print files matching *.x3d scenes: *X_ITE.html "/>
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="name.short"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
            <!-- <echo>delete ${relative.path1}/${relative.path2}/${name.short}X_ITE.html</echo> -->
                <delete file="${relative.path1}/${relative.path2}/${name.short}Cobweb.html"/>
                <delete file="${relative.path1}/${relative.path2}/${name.short}X_ITE.html"/>
            </sequential>
        </for>
    </target>

    <target name="clean.wrl" description="clean out autogenerated *.wrl files (only)">
        <echo message="clean/delete autogenerated files matching *.x3d scenes: *.wrl"/>
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="name.short"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
            <!-- <echo>delete ${relative.path1}/${relative.path2}/${name.short}.wrl</echo> -->
                <delete file="${relative.path1}/${relative.path2}/${name.short}.wrl"/>
            </sequential>
        </for>
    </target>

    <target name="clean.json" description="clean out autogenerated *.json files (only)">
        <echo message="clean/delete autogenerated files matching *.x3d scenes: *.json"/>
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="name.short"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
            <!-- <echo>delete ${relative.path1}/${relative.path2}/${name.short}.json</echo> -->
                <delete file="${relative.path1}/${relative.path2}/${name.short}.json"/>
            </sequential>
        </for>
    </target>

    <target name="clean.x3db" description="clean out autogenerated *.x3db files">
        <echo message="clean/delete autogenerated files matching *.x3d scenes: *.x3db"/>
        <delete failonerror="false" includeemptydirs="true" verbose="true">
            <fileset dir="." includes="**/*.x3db"/>
        </delete>
    </target>

    <target name="clean.x3dv" description="clean out autogenerated *.x3dv files (only)">
        <echo message="clean/delete autogenerated files matching *.x3d scenes: *.x3dv"/>
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="name.short"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
            <!-- <echo>delete ${relative.path1}/${relative.path2}/${name.short}.x3dv</echo> -->
                <delete file="${relative.path1}/${relative.path2}/${name.short}.x3dv"/>
            </sequential>
        </for>
    </target>

    <target name="clean.Canonical.xml" description="clean out autogenerated *Canonical.xml files (only)">
        <echo message="clean/delete autogenerated *Canonical.xml files"/>
        <delete failonerror="false" includeemptydirs="true" verbose="true">
            <fileset dir="." includes="**/*Canonical.xml"/>
        </delete>
    </target>

    <target name="clean.SVG" description="clean out autogenerated *.svg files (only)">
        <!-- SVG crossSection images are generated along with html pretty-print pages for each scene -->
        <echo message="clean/delete autogenerated files matching *.x3d scenes: _svg/*.svg"/>
        <delete failonerror="false" includeemptydirs="true" verbose="true">
            <fileset dir="." includes="**/_svg/*.svg"/>
        </delete>
    </target>

    <target name="clean.schematron" description="clean out autogenerated schematron validation files (only)">
        <echo message="clean/delete autogenerated files matching *.x3d scenes: _schematron/*"/>
        <delete failonerror="false" includeemptydirs="true" verbose="true">
            <fileset dir=".">
                <include name="_schematron/*"/>
                <include name="*/_schematron/*"/>
                <include name="*/*/_schematron/*"/>
            </fileset>
        </delete>
    </target>

    <target name="clean.slideshowTools" description="clean out downloaded slideshow tools">
        <echo message="clean out downloaded slideshow tools"/>
        <delete verbose="true" dir="slideshow" includeemptydirs="true" failonerror="false"/>
    </target>

    <target name="clean.viewpointImages" description="clean out autogenerated viewpoint image files (only)">
        <echo message="clean/delete autogenerated viewpoint image files"/>
        <delete failonerror="false" includeemptydirs="true" verbose="true">
            <fileset dir=".">
                <include name="**/_viewpoints/*.png"/>
            </fileset>
        </delete>
        <echo message="Note: you must also clean HTML versions of scenes to trigger re-shooting of replica screenshot images"/>
     </target>

     <target name="clean.thumbnailImages" description="clean out autogenerated thumbnail image files (only)">
        <echo message="clean/delete autogenerated thumbnail image files"/>
        <delete failonerror="false" includeemptydirs="true" verbose="true">
            <fileset dir=".">
                <include name="**/_thumbnails/*.png"/>
            </fileset>
        </delete>
     </target>

    <target name="jenkins" depends="jenkins.prepare,build" description="jenkins tasks">
        <!-- optional dependency:  clean.jenkins -->
        <!-- TODO build,HelloWorld,newScene - fix XML catalog, needs server-side configuration -->
        <delete dir="_archive" failonerror="false" verbose="false"/>
        <antcall target="jenkins.deploy.nightly"/>
        <antcall target="echo.timestamp"/>
        <echo message="jenkins ${archive.name} examples build complete"/>

<!-- Jenkins description (adjusted for each build):
<p>
Create a local version of <a href="ws/Basic/index.html">X3D Basic Examples archive</a>
by performing version-control source update, build, validate and test tasks.
Also produced:
<a href="ws/Basic/ContentCatalogBasic.xml">content catalog</a>
and
<a href="ws/X3dExamplesBasic.zip">.zip archive</a>.
</p>
<p>
Officially released models and .zip distribution are maintained at
<a href="https://www.web3d.org/x3d/content/examples/Basic" target="_blank">https://www.web3d.org/x3d/content/examples/Basic</a>.
</p>

<p>
Nightly builds are published at
<a href="https://savagedefense.nps.navy.mil/SavageDefense/nightly" target="_blank">https://savagedefense.nps.navy.mil/SavageDefense/nightly</a>.
</p>

<p>
Additional example build projects nearby include
<ul>
<li><a href="../X3dExamplesBasic">X3dExamplesBasic</a></li>
<li><a href="../X3dExamplesConformanceNist">X3dExamplesConformanceNist</a></li>
<li><a href="../X3dExamplesVrml2Sourcebook">X3dExamplesVrml2Sourcebook</a></li>
<li><a href="../X3dExamplesX3dForWebAuthors">X3dExamplesX3dForWebAuthors</a></li>
<li><a href="../X3dExamplesSavage">X3dExamplesSavage</a></li>
<li><a href="https://savagedefense.nps.navy.mil/jenkins/job/X3dExamplesSavageDefense">X3dExamplesSavageDefense</a></li>
</ul>
</p>

<p>Additional information is available at
<a href="https://savage.nps.edu/Savage/developers.html#Jenkins" target="_blank">Savage Developers Guide</a>,
<a href="https://SavageDefense.nps.navy.mil/SavageDefense/developers.html#Jenkins">SavageDefense Developers Guide</a>,
<a href="https://www.web3d.org/x3d/content/examples/X3dResources.html" target="_blank">X3D Resources</a>
and
<a href="https://www.web3d.org/x3d/content/examples/X3dSceneAuthoringHints.html" target="_blank">X3D Scene Authoring Hints</a>.
</p>
        -->
    </target>

    <target name="clean.jenkins" description="clean files downloaded by jenkins.prepare">
        <echo message="clean/delete directory and files downloaded by jenkins.prepare"/>
        <delete dir="jenkins" failonerror="false" includeemptydirs="true" verbose="true"/>
        <!-- make library directories for supporting jar files -->
        <mkdir  dir="jenkins/lib"/>
    </target>

    <target name="jenkins.permissions" description="ensure archive files have correct permissions">
        <!-- utility task, not normally needed -->
        <!-- For some archives, if some permissions were not modified properly: cd /var/www/html/ArchiveName; ./permissions.sh -->
        <echo message="ensure archive files have correct permissions:"/>
        <property name="verbose" value="true"/>
        <chmod verbose='${verbose}' perm='664' type="file">
            <fileset id="imageFiles" dir=".">
                <include name="**/*.png"/>
                <exclude name="**/.svn/*"/>
            </fileset>
        </chmod>
        <chown verbose='${verbose}' owner='jenkins:jenkins' type="file">
            <fileset refid="imageFiles"/>
        </chown>
    </target>

    <target name="jenkins.deploy.release" description="release jenkins build to website directory" depends="">
        <!-- this task is run in a separate project from the jenkins build nightly project, and so must adapt paths -->
        <!-- local: /var/lib/jenkins/jobs/X3dExamplesSavageDeployRelease/workspace/ -->
        <!-- build: /var/lib/jenkins/jobs/X3dExamplesSavage/workspace/X3dExamplesSavage.zip -->
        <tstamp>
            <format property="dateStamp" pattern="yyyyMMMMdd"/>
        </tstamp>
        <property name="zipFileName" value="X3dExamples${archive.name}.zip"/>
        <!-- mkdir and owner/permission settings for destination directories typically require root or sudo permissions -->
        <if>
            <equals arg1="${archive.name}" arg2="Savage" />
            <then>
            <!--
                <property name="zipFilePath" value="../../../X3dExamplesSavage/ws"/>
                <length property="archive.zip.length" file="${zipFilePath}/${zipFileName}"/>
                <echo message="Backing up prior ${zipFilePath}/${zipFileName} release to public build subdirectory as X3dExamples${archive.name}.${dateStamp}.zip"/>
                <copy file="${zipFilePath}/${zipFileName}" tofile="/var/www/html/X3dExamples${archive.name}.${dateStamp}.zip"        preservelastmodified="true" overwrite="true" force="true" verbose="true"/>
                <echo message="Copying ${zipFilePath}/${zipFileName} (${archive.zip.length} bytes) and X3dExamplesSavageAuvWorkbenchExcerpt.zip to public website"/>
                <copy todir="/var/www/html/"        preservelastmodified="true" overwrite="true" force="true" verbose="true">
                    <fileset dir="${zipFilePath}">
                        <include name="X3dExamplesSavageAuvWorkbenchExcerpt.zip"/>
                        <include name="${zipFileName}"/>
                    </fileset>
                </copy>
                <echo message="================================================================================"/>
                <echo message="Copying all build output files to deploy this jenkins workspace to public website"/>
                <copy todir="/var/www/html/Savage/"        preservelastmodified="true" overwrite="true" force="true" verbose="true">
                    <fileset dir="${zipFilePath}/Savage">
                        <include name="**/*"/>
                        <exclude name="**/.svn/*"/>
                    </fileset>
                </copy>
                -->
                        <!-- no need to filter further since this build only contains the original subversion content and direct products -->
            </then>

<!--
echo Post-build jenkins shell script X3dExamplesSavageDeployRelease
echo Copy build products to release deployment directory, preserve timestamps
pwd

echo Copy .zip archives
cp -fv ../../X3dExamplesSavage/workspace/X3dExamplesSavage*.zip /var/www/html/
echo Changing public permissions to readable and executable:
chmod g+rw+X /var/www/html/X3dExamplesSavage*.zip
chmod o+r+X  /var/www/html/X3dExamplesSavage*.zip

echo Copy file assets, Savage
cp -fr ../../X3dExamplesSavage/workspace/Savage /var/www/html/
echo Changing public permissions to readable and executable:
chmod g+rw+X -R /var/www/html/Savage
chmod o+r+X  -R /var/www/html/Savage

echo Cleanup subversion .svn subdirectories
rm -rf /var/www/html/SavageDefense/*/*/.svn
rm -rf /var/www/html/SavageDefense/*/.svn
rm -rf /var/www/html/SavageDefense/.svn

echo If some permissions were not modified properly: cd /var/www/html/SavageDefense/; ./permissions.sh
-->

<!--
echo Post-build jenkins shell script X3dExamplesSavageDefenseDeployRelease
echo Copy build products to release deployment directory
pwd
echo Copy .zip archive
cp -fv ../../X3dExamplesSavageDefense/workspace/X3dExamplesSavageDefense.zip /var/www/html/
echo Changing public permissions to readable and executable:
chmod g+rw /var/www/html/X3dExamplesSavage*.zip
chmod o+r  /var/www/html/X3dExamplesSavage*.zip

echo Copy file assets, SavageDefense
cp -fr ../../X3dExamplesSavageDefense/workspace/SavageDefense /var/www/html/
echo Changing public permissions to readable and executable:
chmod g+rw+X -R /var/www/html/SavageDefense
chmod o+r+X  -R /var/www/html/SavageDefense

echo Cleanup subversion .svn subdirectories
rm -rf /var/www/html/SavageDefense/*/*/.svn
rm -rf /var/www/html/SavageDefense/*/.svn
rm -rf /var/www/html/SavageDefense/.svn
-->

<!--
<p>
Deploy release version of locally built Jenkins project
When initiated by an administrator, deploy the release version of Savage using the local nightly-build Jenkins project
<a href="../X3dExamplesSavage">X3dExamplesSavage</a>.
</p>
<p>
Officially released models and .zip distribution are maintained at
<a href="https://savage.nps.edu/Savage" target="_blank">https://savage.nps.edu/Savage</a>.
</p>

<p>
Nightly builds are published at
<a href="https://savage.nps.edu/Savage/nightly" target="_blank">https://savage.nps.edu/Savage/nightly</a>.
</p>

<p>
Nearby: additional X3D Example build projects include
<ul>
<li><a href="../X3dExamplesBasic">X3dExamplesBasic</a></li>
<li><a href="../X3dExamplesConformanceNist">X3dExamplesConformanceNist</a></li>
<li><a href="../X3dExamplesVrml2Sourcebook">X3dExamplesVrml2Sourcebook</a></li>
<li><a href="../X3dExamplesX3dForWebAuthors">X3dExamplesX3dForWebAuthors</a></li>
<li><a href="../X3dExamplesSavage">X3dExamplesSavage</a></li>
<li><a href="https://savagedefense.nps.navy.mil/jenkins/job/X3dExamplesSavageDefense">X3dExamplesSavageDefense</a></li>
</ul>
</p>

<p>Additional information is available at <a href="https://savage.nps.edu/developers.html" target="_blank">Savage Developers Guide</a>,
<a href="https://www.web3d.org/x3d/content/examples/X3dResources.html" target="_blank">X3D Resources</a>
and
<a href="https://www.web3d.org/x3d/content/examples/X3dSceneAuthoringHints.html" target="_blank">X3D Scene Authoring Hints</a>.
</p>
-->
        <elseif>
            <equals arg1="${archive.name}" arg2="SavageDefense" />
            <then>
            <!--
                <property name="zipFilePath" value="../../../X3dExamplesSavageDefense/ws"/>
                <length property="archive.zip.length" file="${zipFilePath}/${zipFileName}"/>
                <echo message="Copying current ${zipFilePath}/${zipFileName} (${archive.zip.length} bytes) to public website"/>
                <copy file="${zipFilePath}/${zipFileName}" tofile="/var/www/html/X3dExamples${archive.name}.${dateStamp}.zip" preservelastmodified="true" overwrite="true" force="true" verbose="true"/>
                <copy todir="/var/www/html/"        preservelastmodified="true" overwrite="true" force="true" verbose="true">
                    <fileset dir="${zipFilePath}">
                        <include name="${zipFileName}"/>
                    </fileset>
                </copy>
                <echo message="========================================================================="/>
                <echo message="Copying all build output files to deploy this jenkins workspace to public website"/>
                <copy todir="/var/www/html/SavageDefense" preservelastmodified="true" overwrite="true" force="true" verbose="true">
                    <fileset dir="${zipFilePath}/SavageDefense">
                        <include name="**/*"/>
                        <exclude name="**/.svn/*"/>
                    </fileset>
                </copy>
                -->
                        <!-- no need to filter further since this build only contains the original subversion content and direct products -->
            </then>
<!--
<p>
Deploy release version of locally built Jenkins project <a href="../X3dExamplesSavageDefense">X3dExamplesSavageDefense</a>.
</p>
<p>
This project is controlled-access For Official Use Only (FOUO).
</p>
<p>
Officially released models and .zip distribution are maintained at
<a href="https://savagedefense.nps.navy.mil/SavageDefense" target="_blank">https://savagedefense.nps.navy.mil/SavageDefense</a>.
</p>

<p>
Nightly builds are published at
<a href="https://savagedefense.nps.navy.mil/SavageDefense/nightly" target="_blank">https://savagedefense.nps.navy.mil/SavageDefense/nightly</a>.
</p>

<p>
Nearby: additional X3D Example build projects include
<ul>
<li><a href="https://savage.nps.edu/jenkins/job/X3dExamplesBasic">X3dExamplesBasic</a></li>
<li><a href="https://savage.nps.edu/jenkins/job/X3dExamplesConformanceNist">X3dExamplesConformanceNist</a></li>
<li><a href="https://savage.nps.edu/jenkins/job/X3dExamplesVrml2Sourcebook">X3dExamplesVrml2Sourcebook</a></li>
<li><a href="https://savage.nps.edu/jenkins/job/X3dExamplesX3dForWebAuthors">X3dExamplesX3dForWebAuthors</a></li>
<li><a href="https://savage.nps.edu/jenkins/job/X3dExamplesSavage">X3dExamplesSavage</a></li>
<li><a href="https://savagedefense.nps.navy.mil/jenkins/job/X3dExamplesSavageDefense">X3dExamplesSavageDefense</a></li>
</ul>
</p>

<p>Additional information is available at
<a href="https://savage.nps.edu/developers.html" target="_blank">Savage Developers Guide</a>,
<a href="https://SavageDefense.nps.navy.mil/developers.html" target="_blank">SavageDefense Developers Guide</a>,
<a href="https://www.web3d.org/x3d/content/examples/X3dResources.html" target="_blank">X3D Resources</a>
and
<a href="https://www.web3d.org/x3d/content/examples/X3dSceneAuthoringHints.html" target="_blank">X3D Scene Authoring Hints</a>.
</p>
-->
        </elseif>
        <else>
            <!-- TODO, not yet implemented:
            <scp remotetodir="${username.web3d}@${sftpServer.web3d}:${sftpDirectory.web3d.examples}" password="${password.web3d}" verbose="true">
                <fileset dir=".">
                    <include name="${zipFilePath}/${zipFileName}"/>
                </fileset>
            </scp>
            -->
        </else>
        </if>
    </target>

    <target name="jenkins.deploy.nightly" description="copy jenkins build .zip to website nightly-build directory" depends="">
        <!-- properties already set by zip task; match them to enable separate invocation -->
        <property name="zipFileName" value="../X3dExamples${archive.name}.zip"/>
        <length property="archive.zip.length" file="${zipFileName}"/>
        <echo message="Completed ${zipFileName} (${archive.zip.length} bytes)"/>
        <!-- server-side mkdir and owner/permission settings for destination directories typically require root or sudo permissions -->
        <!-- prerequisite permissions for destination .zip files:  -rw-rw-r- tomcat tomcat -->
        <if>
            <equals arg1="${archive.name}" arg2="Savage" />
            <then>
                <ant antfile="buildSavageAuvWorkbenchModelDistribution.xml" target="zip.AuvWorkbenchExcerpt"/>
                <property name="excerptZipFileName" value="../X3dExamplesSavageAuvWorkbenchExcerpt.zip"/>
                <length property="excerpt.zip.length" file="${excerptZipFileName}"/>
                <echo message="Completed ${excerptZipFileName} (${excerpt.zip.length} bytes)"/>
                <!--
                <echo message="Copying ${zipFileName} (${archive.zip.length} bytes) to nightly build subdirectory"/>
                <copy todir="/var/www/html/Savage/nightly"        preservelastmodified="true" overwrite="true" force="true" verbose="true">
                    <fileset dir=".">
                        <include name="${zipFileName}"/>
                    </fileset>
                </copy>
                <echo message="Copying ${excerptZipFileName} (${excerpt.zip.length} bytes) to nightly build subdirectory"/>
                <copy todir="/var/www/html/Savage/nightly"        preservelastmodified="true" overwrite="true" force="true" verbose="true">
                    <fileset dir=".">
                        <include name="${excerptZipFileName}"/>
                    </fileset>
                </copy>
                -->
                <!-- TODO SavageStudio excerpt -->
            </then>
        <elseif>
            <equals arg1="${archive.name}" arg2="SavageDefense" />
            <then>
                <!-- location: /var/lib/jenkins/jobs/X3dExamplesSavageDefense/workspace/X3dExamplesSavageDefense.zip -->
                <!--
                <echo message="Copying ${zipFileName} (${archive.zip.length} bytes) to nightly build subdirectory"/>
                <copy todir="/var/www/html/SavageDefense/nightly" preservelastmodified="true" overwrite="true" force="true" verbose="true">
                    <fileset dir=".">
                        <include name="${zipFileName}"/>
                    </fileset>
                </copy>
                -->
            </then>
        </elseif>
        <else>
            <!-- TODO, not yet implemented:
            <scp remotetodir="${username.web3d}@${sftpServer.web3d}:${sftpDirectory.web3d.examples}" password="${password.web3d}" verbose="true">
                <fileset dir=".">
                    <include name="${zipFileName}"/>
                </fileset>
            </scp>
            -->
        </else>
        </if>
    </target>

<!-- Jenkins build server top-level description templates

<h2>Savage Jenkins Build Server</h2>
<p>This online continuous-integration server is used to test open-source code and content distributions.
Projects of interest include the AUV Workbench, X3D Examples, X3D Tools, and NPS source branch of the Xj3D player for X3D.</p>

<h2>SavageDefense Jenkins Build Server</h2>
<p>This online continuous-integration server is used to test open-source code and content distributions.  Projects of interest include TrackDataConversionSuiteDefense and X3dExamplesSavageDefense.</p>


<p>
For Official Use Only (FOUO) data access is restricted to U.S. government employees and contractors.
No classified information is contained in this system.
</p>

<p>
The
<a href="https://savage.nps.edu/developers.html#Jenkins">Savage Developers Guide</a>
contains further information about the various technologies involved and their configuration details.
</p>

<p>
We also maintain the FOUO restricted-access
<a href="https://savage.nps.edu/jenkins">Savage Jenkins Server</a>
and NPS-internal
<a href="https://mmog.ern.nps.edu/jenkins">Savage MMOG Jenkins Server</a>.
</p>
-->

<!-- Post-build execute shell commands for jenkins projects X3dExamplesSavage/X3dExamplesSavageDefense:

echo Post-build jenkins shell script
echo Copy build products to nightly deployment directory, preserve timestamps
pwd
cp -fvp X3dExamplesSavage*.zip /var/www/html/nightly/

echo Changing public permissions to readable and executable:
chmod g+rw+X -R /var/www/html/nightly/X3dExamplesSavage*.zip
chmod o+r+X  -R /var/www/html/nightly/X3dExamplesSavage*.zip

ls -al X3dExamplesSavage*.zip /var/www/html/nightly/X3dExamplesSavage*.zip
-->
<!-- TODO
echo move current copies to avoid later recopying/retimestamping if failed build occurs
mkdir -vp prior
mv    -vf X3dExamplesSavage*.zip prior/
-->
    <target name="jenkins.prepare" description="setup jenkins server-side build"> <!-- depends="clean.jenkins" depends="clean.X3domXhtml" -->
        <!-- clean.X3domXhtml for full X3DOM updates since this capability is evolving -->
        <!-- jenkins tasks:  jenkins.prepare, build -->
        <!-- jenkins configuration needs to reset Ant property values to match subdirectories below:
c14n.dir=jenkins/lib
log4j.dir=jenkins/lib
saxon.dir=jenkins/lib
stylesheet.dir=jenkins/stylesheets
xj3d.dir=jenkins/lib
CreateContentCatalog.dir=jenkins/CreateContentCatalog
X3dSchematronValidityChecks.dir=jenkins/schematron
X3dDtdsSchemas.dir=jenkins/specifications
ignoreSetupDownloadErrors=true
        -->
        <!-- jenkins configuration for Ant java options:
-Dxml.catalog.files=jenkins/specifications/OasisXmlCatalogX3D.xml
-Dxml.catalog.verbosity=4
-Xbootclasspath/p:lib/bin
-Dsun.java2d.noddraw=true
-Djava.library.path=lib/bin
        -->
        <property name="jenkins.prepared" value="true"/>
        <property name="catalog.local.dtd" value="" description="use online X3D DTD and schema for catalog autogeneration"/>
        <echo message="Build settings:"/>
        <echo message="                             fork=${fork}"/>
        <echo message="                         c14n.dir=${c14n.dir}"/>
        <echo message="                        log4j.dir=${log4j.dir}"/>
        <echo message="                        saxon.dir=${saxon.dir}"/>
        <echo message="                   stylesheet.dir=${stylesheet.dir}"/>
        <echo message="                         xj3d.dir=${xj3d.dir.jars}"/>
        <echo message="         CreateContentCatalog.dir=${CreateContentCatalog.dir}"/>
        <echo message="  X3dSchematronValidityChecks.dir=${X3dSchematronValidityChecks.dir}"/>
        <echo message="               X3dDtdsSchemas.dir=${X3dDtdsSchemas.dir}"/>
        <echo message="        ignoreSetupDownloadErrors=${ignoreSetupDownloadErrors}"/>
        <echo message="   saxon path: ${saxon.dir}/${saxon.jar}"/>
   <!-- TODO <echo message="resolver path: ${saxon.dir}/${xmlresolver.jar}; (${resolver.jar.length} bytes)"/> -->

        <!-- make library directories for supporting jar files -->
        <mkdir  dir="jenkins/lib"/>

        <echo message="get local copies of dependency files in order to independently prepare jenkins server-side build"/>

        <mkdir dir="${X3dDtdsSchemas.dir}"/>
        <get src="${x3d.sourceforge.site}/specifications/OasisXmlCatalogX3D.xml?format=raw"
                             dest="${X3dDtdsSchemas.dir}/OasisXmlCatalogX3D.xml"    verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/specifications/CatalogManager.properties?format=raw"
                             dest="${X3dDtdsSchemas.dir}/CatalogManager.properties" verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/specifications/x3d-3.0.dtd"
                             dest="${X3dDtdsSchemas.dir}/x3d-3.0.dtd"               verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/specifications/x3d-3.1.dtd"
                             dest="${X3dDtdsSchemas.dir}/x3d-3.1.dtd"               verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/specifications/x3d-3.2.dtd"
                             dest="${X3dDtdsSchemas.dir}/x3d-3.2.dtd"               verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/specifications/x3d-3.3.dtd"
                             dest="${X3dDtdsSchemas.dir}/x3d-3.3.dtd"               verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/specifications/x3d-3.0.xsd"
                             dest="${X3dDtdsSchemas.dir}/x3d-3.0.xsd"               verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/specifications/x3d-3.1.xsd"
                             dest="${X3dDtdsSchemas.dir}/x3d-3.1.xsd"               verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/specifications/x3d-3.2.xsd"
                             dest="${X3dDtdsSchemas.dir}/x3d-3.2.xsd"               verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/specifications/x3d-3.3.xsd"
                             dest="${X3dDtdsSchemas.dir}/x3d-3.3.xsd"               verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>

        <mkdir dir="${stylesheet.dir}"/>
        <get src="${x3d.sourceforge.site}/x3d/stylesheets/X3dToXhtml.xslt"
                                  dest="${stylesheet.dir}/X3dToXhtml.xslt"          verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/x3d/stylesheets/X3dToVrml97.xslt"
                                  dest="${stylesheet.dir}/X3dToVrml97.xslt"         verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/x3d/stylesheets/X3dToX3dvClassicVrmlEncoding.xslt"
                                  dest="${stylesheet.dir}/X3dToX3dvClassicVrmlEncoding.xslt" verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/x3d/stylesheets/X3dExtrusionCrossSectionToSvg.xslt"
                                  dest="${stylesheet.dir}/X3dExtrusionCrossSectionToSvg.xslt"  verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/x3d/stylesheets/X3dToX3domX_ITE.xslt"
                                  dest="${stylesheet.dir}/X3dToX3domX_ITE.xslt"          verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        
        <mkdir dir="${c14n.dir}"/>
        <get src="${x3d.sourceforge.site}/x3d/tools/canonical/dist/lib/${c14n.jar}"
                                                     dest="${c14n.dir}/${c14n.jar}"  verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>

        <mkdir dir="${log4j.dir}"/>
        <get src="${x3d.sourceforge.site}/x3d/tools/canonical/dist/lib/${log4j.jar}"
                                                    dest="${log4j.dir}/${log4j.jar}" verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>

        <mkdir dir="${saxon.dir}"/>
        <get src="${x3d.sourceforge.site}/x3d/tools/schematron/bin/${saxon.jar}"
                                                dest="${saxon.dir}/${saxon.jar}"     verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>

        <mkdir dir="${xj3d.dir.jars}"/>
        <!-- TODO configure get https certificate handling; use local copy instead
        <get src="${xj3d.jar.site}/${xj3d.jar}"
                 dest="${xj3d.dir.jars}/${xj3d.jar}"           verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${xj3d.jar.site}/${xj3d.cadfilter.jar}"
                 dest="${xj3d.dir.jars}/${xj3d.cadfilter.jar}" verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${xj3d.jar.site}/${xj3d.3rdparty.jar}"
                 dest="${xj3d.dir.jars}/${xj3d.3rdparty.jar}"  verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${xj3d.jar.site}/${xj3d.browser.jar}"
                 dest="${xj3d.dir.jars}/${xj3d.browser.jar}"   verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        -->

        <if>
            <equals arg1="${archive.name}" arg2="SavageDefense" />
            <then>
                <get src="https://sourceforge.net/p/xmsf/code/HEAD/tree/trunk/AuvWorkbench//lib/xj3d/${xj3d.jar}"
                                                                                dest="${xj3d.dir.jars}/${xj3d.jar}"           verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
                <get src="https://sourceforge.net/p/xmsf/code/HEAD/tree/trunk/AuvWorkbench//lib/xj3d/${xj3d.cadfilter.jar}"
                                                                                dest="${xj3d.dir.jars}/${xj3d.cadfilter.jar}" verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
                <get src="https://sourceforge.net/p/xmsf/code/HEAD/tree/trunk/AuvWorkbench//lib/xj3d/${xj3d.3rdparty.jar}"
                                                                                dest="${xj3d.dir.jars}/${xj3d.3rdparty.jar}"  verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
                <get src="https://sourceforge.net/p/xmsf/code/HEAD/tree/trunk/AuvWorkbench//lib/xj3d/${xj3d.browser.jar}"
                                                                                dest="${xj3d.dir.jars}/${xj3d.browser.jar}"   verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
            </then>
            <else>
                <!-- Xj3D.nps build is on local server savage.nps.edu -->
                <copy file="/var/www/html/Xj3D.nps/jars/${xj3d.jar}"           todir="${xj3d.dir.jars}/" verbose="true"/>
                <copy file="/var/www/html/Xj3D.nps/jars/${xj3d.cadfilter.jar}" todir="${xj3d.dir.jars}/" verbose="true"/>
                <copy file="/var/www/html/Xj3D.nps/jars/${xj3d.3rdparty.jar}"  todir="${xj3d.dir.jars}/" verbose="true"/>
                <copy file="/var/www/html/Xj3D.nps/jars/${xj3d.browser.jar}"   todir="${xj3d.dir.jars}/" verbose="true"/>
            </else>
        </if>

        <mkdir dir="${X3dSchematronValidityChecks.dir}"/>
        <get src="${x3d.sourceforge.site}/x3d/tools/schematron/${X3dSchematronValidityChecks}.xslt?format=raw"
                      dest="${X3dSchematronValidityChecks.dir}/${X3dSchematronValidityChecks}.xslt"             verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/x3d/tools/schematron/${SvrlReportText}.xslt?format=raw"
                      dest="${X3dSchematronValidityChecks.dir}/${SvrlReportText}.xslt"                          verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        
        <mkdir dir="${CreateContentCatalog.dir}"/>
        <get src="${x3d.sourceforge.site}/x3d/tools/CreateContentCatalog/CreateContentCatalog.jar"
                                                               dest="lib/CreateContentCatalog.jar" verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/x3d/tools/CreateContentCatalog/CreateContentCatalogPages.xslt?format=raw"
                                       dest="${CreateContentCatalog.dir}/CreateContentCatalogPages.xslt"        verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <!-- DTD to validate content catalog used for creation of example archive html pages -->
        <get src="${x3d.sourceforge.site}/x3d/tools/CreateContentCatalog/ContentCatalog.dtd?format=raw"
                                       dest="${CreateContentCatalog.dir}/ContentCatalog.dtd"                    verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/x3d/tools/CreateContentCatalog/ContentCatalogToXmlSpyProject.xslt?format=raw"
                                       dest="${CreateContentCatalog.dir}/ContentCatalogToXmlSpyProject.xslt"    verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/x3d/tools/CreateContentCatalog/SavageModelingAnalysisLanguage1.0.dtd?format=raw"
                                       dest="${CreateContentCatalog.dir}/SavageModelingAnalysisLanguage1.0.dtd" verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>

        <!-- Copy viewpoint screen snapshot images to support catalog generation -->
        <if>
            <equals arg1="${archive.name}" arg2="Savage" />
            <then>
                <echo message="Copy viewpoint screen snapshot images to support catalog generation"/>
                <copy todir="." preservelastmodified="true" overwrite="true" verbose="true">
                    <fileset dir="/var/www/html/${archive.name}">
                        <include name="*/*/_viewpoints/*.png"/>
                        <exclude name="**/.svn/*"/>
                    </fileset>
                </copy>
            </then>
        <elseif>
            <equals arg1="${archive.name}" arg2="SavageDefense" />
            <then>
                <echo message="Copy viewpoint screen snapshot images to support catalog generation"/>
                <copy todir="." preservelastmodified="true" overwrite="true" verbose="true">
                    <fileset dir="/var/www/html/${archive.name}">
                        <include name="*/*/_viewpoints/*.png"/>
                        <exclude name="**/.svn/*"/>
                    </fileset>
                </copy>
            </then>
        </elseif>
        </if>
    </target>

    <target name="commonSetup" depends="HelloWorld,newScene" description="Copy setup files from common example archives">
        <echo message="Verifying Apache Ant XML Catalog resolver classpath: ${resolver.dir}/${resolver.jar} (${resolver.jar.length} bytes)"/>
        <!-- each specific example archive redirects to X3dResources.html (formerly help.html) in parent examples directory due to other relative links there -->
        <get src="${x3d.sourceforge.site}/x3d/content/examples/_help.redirect.html?format=raw"
                                                          dest="help.html"                    verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <!-- here is local copy of X3dResources.html as well -->
        <get src="${x3d.sourceforge.site}/x3d/content/examples/X3dResources.html?format=raw"
                                                         dest="X3dResources.html"             verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/x3d/content/examples/X3dSceneAuthoringHints.html?format=raw"
                                                         dest="X3dSceneAuthoringHints.html"   verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
       <get src="${x3d.sourceforge.site}/x3d/content/examples/newHtmlPageWithX3dObject.html?format=raw"
                                                         dest="newHtmlPageWithX3dObject.html" verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/x3d/content/examples/newECMAscript.js?format=raw"
                                                         dest="newECMAscript.js"              verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/x3d/content/examples/newX3dScript.java?format=raw"
                                                         dest="newX3dScript.java"             verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/x3d/content/examples/newStylesheet.xslt?format=raw"
                                                         dest="newStylesheet.xslt"            verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
		<!-- Savage and SavageDefense have different licenses than Web3D archives; all are checked into version control -->
        <if>
            <and>
                <not>
                    <equals arg1="${archive.name}" arg2="Savage" />
                </not>
                <not>
                    <equals arg1="${archive.name}" arg2="SavageDefense" />
                </not>
            </and>
            <then>
                <get src="${x3d.sourceforge.site}/x3d/content/examples/license.html?format=raw"
                    dest="license.html" verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
                <get src="${x3d.sourceforge.site}/x3d/content/examples/license.txt?format=raw"
                    dest="license.txt"  verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>	
            </then>
        </if>
        <antcall target="get.slideshowTools"/>
    </target>

    <target name="get.web3d.saxon" description="get saxon.jar if not checked out" depends="get.web3d.saxon.check" unless="saxon.found">
        <echo message="get saxon.jar if not checked out"/>
        <mkdir dir="${saxon.dir}"/>
        <get src="https://svn.code.sf.net/p/x3d/code/www.web3d.org/x3d/tools/jar/${saxon.jar}"
            dest="${saxon.dir}/${saxon.jar}" verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
    </target>
    <target name="get.web3d.saxon.check">
        <condition property="saxon.found" else="false">
            <available file="${saxon.dir}/${saxon.jar}"/>
        </condition>
        <echo message="found ${saxon.dir}/${saxon.jar}: ${saxon.found}"/>
    </target>

    <target name="get.X3DJSAIL.update.online" description="get latest X3DJSAIL update" >
        <echo message="get latest X3DJSAIL update from https://www.web3d.org/specifications/java/X3DJSAIL.html"/>
        <get src="https://www.web3d.org/specifications/java/jars/${jsai.full.archive.jar.name}"
            dest="lib/" verbose="true" ignoreerrors="false"/>
        <length property="jsai.full.archive.jar.length" file="lib/${jsai.full.archive.jar.name}"/>
        <echo>Download complete, lib/${jsai.full.archive.jar.name} size ${jsai.full.archive.jar.length} bytes</echo>
    </target>

    <target name="copy.X3DJSAIL.update.local" description="get latest X3DJSAIL update" >
        <echo message="get latest X3DJSAIL update from ${x3djsail.stylesheets.dir}"/>
        <copy file="${x3djsail.stylesheets.dir}/${jsai.full.archive.jar.name}"
             todir="lib/" verbose="true"/>
        <length property="jsai.full.archive.jar.length" file="lib/${jsai.full.archive.jar.name}"/>
        <echo>File copy complete, lib/${jsai.full.archive.jar.name} size ${jsai.full.archive.jar.length} bytes</echo>
    </target>

    <target name="get.slideshowTools" description="retrieve slideshow package"> <!-- unless="${ignoreSetupDownloadErrors}" -->
        <echo message="Retrieve open-source google slideshow package https://code.google.com/archive/p/slideshow"/>
        <property name="mootools.zip" value="Slideshow-1.3.2.110508.zip"/>
        <property name="mootools.dir" value="https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/slideshow"/>
		<get src="${mootools.dir}/${mootools.zip}"
                            dest="${mootools.zip}" verbose="true" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <mkdir  dir="slideshow"/>
        <unzip dest="slideshow" src="${mootools.zip}"/>
        <move todir="slideshow" verbose="true">
            <fileset dir="slideshow/Slideshow">
              <include name=    "css/**/*"/>
              <include name=    "js/**/*"/>
              <include name="README"/>
              <!--
              <include name="images/**/*"/>
              <include name="index.html"/>
              -->
            </fileset>
        </move>
        <delete  dir="slideshow/Slideshow" verbose="true"/>
        <delete  dir="slideshow/__MACOSX"  verbose="true"/>
        <delete file="${mootools.zip}"     verbose="true" failonerror="false"/>
    </target>

    <target name="diagnostics" description="Ant diagnostics, shows jars and classpaths">
        <diagnostics/>
    </target>

    <target name="HelloWorld" description="Copy HelloWorld.x3d example from common example archives and convert to other encodings" depends="get.web3d.saxon">
        <delete failonerror="false">
            <fileset dir="." includes="HelloWorld.*"/>
            <fileset dir="." includes="HelloWorldX_ITE.html"/>
            <fileset dir="." includes="HelloWorldX_ITE.html"/>
            <fileset dir="." includes="HelloWorldX3dom.xhtml"/>
            <fileset dir="." includes="HelloWorldCanonical.*"/>
        </delete>
        <if>
            <equals arg1="${use.sourceforge.site}" arg2="true" />
            <then>
        <get src="${x3d.sourceforge.site}/x3d/content/examples/X3dForAdvancedModeling/HelloWorldScenes/HelloWorld.x3d?format=raw"
                                                         dest="HelloWorld.x3d"       ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/x3d/content/examples/X3dForAdvancedModeling/HelloWorldScenes/earth-topo.jpg"
                                                         dest="earth-topo.jpg"       ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/x3d/content/examples/X3dForAdvancedModeling/HelloWorldScenes/earth-topo.png"
                                                         dest="earth-topo.png"       ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/x3d/content/examples/X3dForAdvancedModeling/HelloWorldScenes/earth-topo.gif"
                                                         dest="earth-topo.gif"       ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/x3d/content/examples/X3dForAdvancedModeling/HelloWorldScenes/earth-topo-small.gif"
                                                         dest="earth-topo-small.gif" ignoreerrors="${ignoreSetupDownloadErrors}"/>
        <get src="${x3d.sourceforge.site}/x3d/content/examples/X3dForAdvancedModeling/HelloWorldScenes/HelloWorld.tall.png"
                                                         dest="HelloWorld.tall.png"  ignoreerrors="${ignoreSetupDownloadErrors}"/>
            </then>
            <else>
                <copy file="../X3dForAdvancedModeling/HelloWorldScenes/HelloWorld.x3d"       todir="."
                                                                 overwrite="true" failonerror="true" verbose="true" preservelastmodified="true"/>
                <copy file="../X3dForAdvancedModeling/HelloWorldScenes/earth-topo.jpg"       todir="."
                                                                 overwrite="true" failonerror="true" verbose="true" preservelastmodified="true"/>
                <copy file="../X3dForAdvancedModeling/HelloWorldScenes/earth-topo.png"       todir="."
                                                                 overwrite="true" failonerror="true" verbose="true" preservelastmodified="true"/>
                <copy file="../X3dForAdvancedModeling/HelloWorldScenes/earth-topo.gif"       todir="."
                                                                 overwrite="true" failonerror="true" verbose="true" preservelastmodified="true"/>
                <copy file="../X3dForAdvancedModeling/HelloWorldScenes/earth-topo-small.gif" todir="."
                                                                 overwrite="true" failonerror="true" verbose="true" preservelastmodified="true"/>
                <copy file="../X3dForAdvancedModeling/HelloWorldScenes/HelloWorld.tall.png"  todir="."
                                                                 overwrite="true" failonerror="true" verbose="true" preservelastmodified="true"/>
            </else>
        </if>
        <echo message="X3dCatalog X3dDtdsSchemas.dir=${X3dDtdsSchemas.dir}"/>
        <echo message="check well-formedness"/>
        <xmlvalidate file="HelloWorld.x3d" failonerror="false" warn="true" lenient="true"/>
        <echo message="check DTD validation"/>
        <xmlvalidate file="HelloWorld.x3d" failonerror="false" warn="true">
            <xmlcatalog refid="X3dCatalog"/>
            <!-- TODO get xmlcatalog working under jenkins
            <attribute name="http://xml.org/sax/features/validation" value="true"/>
            <attribute name="http://xml.org/sax/features/namespaces" value="true"/>
            -->
        </xmlvalidate>
        <echo message="Convert HelloWorld.x3d to HelloWorld.html using X3dToXhtml.xslt stylesheet"/>
        <!-- https://www.saxonica.com/documentation/#!using-xsl/commandline                           -->
        <!-- java net.sf.saxon.Transform -s:source -o:output  -xsl:stylesheet -->
        <!-- $(SAXON) -t -s:HelloWorld.x3d -o:HelloWorld.html -xsl:../X3dToXhtml.xslt -->
        <!-- note reordering of parameters for source, output contrary to Saxon documentation! -->
        <java classname="net.sf.saxon.Transform" classpath="${saxon.classpath}" fork="${fork}">
            <arg value="-warnings:recover"/> <!-- recover after writing a warning message -->
            <!-- <arg value="-t"/> saxon version and timing information -->
            <arg value="-s:HelloWorld.x3d"/>
            <arg value="-o:HelloWorld.html"/>
            <arg value="-xsl:${stylesheet.dir}/X3dToXhtml.xslt"/>
        </java>
        <echo message="Convert HelloWorld.x3d to HelloWorldX_ITE.html using X3dToX3domX_ITE.xslt stylesheet"/>
        <java classname="net.sf.saxon.Transform" classpath="${saxon.classpath}" fork="${fork}">
            <arg value="-warnings:recover"/> <!-- recover after writing a warning message -->
            <!-- <arg value="-t"/> saxon version and timing information -->
            <arg value="-s:HelloWorld.x3d"/>
            <arg value="-o:HelloWorldX_ITE.html"/>
            <arg value="-xsl:${stylesheet.dir}/X3dToX3domX_ITE.xslt"/>
            <arg value="player=X_ITE"/>
            <arg value="suffix=X_ITE"/>
            <arg value="urlScene=HelloWorld.x3d"/>
            <arg value="extension=html"/>
        </java>
        <echo message="Convert HelloWorld.x3d to HelloWorldX3dom.xhtml using X3dToX3domX_ITE.xslt stylesheet"/>
        <java classname="net.sf.saxon.Transform" classpath="${saxon.classpath}" fork="${fork}">
            <arg value="-warnings:recover"/> <!-- recover after writing a warning message -->
            <!-- <arg value="-t"/> saxon version and timing information -->
            <arg value="-s:HelloWorld.x3d"/>
            <arg value="-o:HelloWorldX3dom.xhtml"/>
            <arg value="-xsl:${stylesheet.dir}/X3dToX3domX_ITE.xslt"/>
        </java>
        <echo message="Convert HelloWorld.x3d to HelloWorld.wrl using X3dToVrml97.xslt stylesheet"/>
        <java classname="net.sf.saxon.Transform" classpath="${saxon.classpath}" fork="${fork}">
            <arg value="-warnings:recover"/>
            <!-- <arg value="-t"/> saxon version and timing information -->
            <arg value="-s:HelloWorld.x3d"/>
            <arg value="-o:HelloWorld.wrl"/>
            <arg value="-xsl:${stylesheet.dir}/X3dToVrml97.xslt"/>
        </java>
        <echo message="Convert HelloWorld.x3d to HelloWorld.x3dv using X3dToX3dvClassicVrmlEncoding.xslt stylesheet"/>
        <java classname="net.sf.saxon.Transform" classpath="${saxon.classpath}" fork="${fork}">
            <arg value="-warnings:recover"/>
            <!-- <arg value="-t"/> saxon version and timing information -->
            <arg value="-s:HelloWorld.x3d"/>
            <arg value="-o:HelloWorld.x3dv"/>
            <arg value="-xsl:${stylesheet.dir}/X3dToX3dvClassicVrmlEncoding.xslt"/>
        </java>
        <echo message="Convert HelloWorld.x3d to HelloWorldCanonical.xml using canonicalX3D"/>
        <!-- canonicalX3D is locally defined macro -->
        <!-- X3dC14n requires full paths to the scene in order to resolve where to put the *Canonical.xml version -->
        <canonicalX3D scene="${basedir}/HelloWorld"/>
        <!-- now compressed binary encoding -->
        <echo message="Convert HelloWorld.x3d to HelloWorld.x3db using Xj3D cadfilter"/>
        <!-- path diagnostics
        <echo message="{xj3d.dir} {xj3d.jar}=${xj3d.dir.jars}/${xj3d.jar}"/>
        <echo message="{xj3d.dir} {xj3d.browser.jar}=${xj3d.dir.jars}/${xj3d.browser.jar}"/>
        <echo message="{xj3d.dir} {xj3d.cadfilter.jar}=${xj3d.dir.jars}/${xj3d.cadfilter.jar}"/>
        <echo message="{xj3d.dir} {xj3d.3rdparty.jar}=${xj3d.dir.jars}/${xj3d.3rdparty.jar}"/>
        -->
        <!-- prerequisite: local Xj3D.NPS, 'build all' to compile, 'build dist' to create jars.  TODO add depends check. -->
        <java classname="xj3d.filter.CDFFilter" fork="${fork}" dir=".">
            <classpath>
                <pathelement path="${saxon.classpath}"/>
                <fileset refid="xj3d.jars.all"/>
            </classpath>
       <!-- <jvmarg value="-verbose"/> -->
            <arg value="Identity"/>
            <arg value="HelloWorld.x3d"/>
            <arg value="HelloWorld.x3db"/>
        </java>
        <echo>HelloWorld.json creation with X3dToJson.xslt</echo>
        <!-- JavaScript Object Notation (JSON) -->
        <Saxon11  scene="HelloWorld"
            stylesheet="${stylesheet.dir}/X3dToJson"
             extension="json"
				expand="on"/>
		<!-- expand:on since DTD defaults needed -->
        <!-- Default options:
        parameterPair1="traceEnabled=false"
        parameterPair2="sceneGraphOnly=false"
        parameterPair3="stripComments=false"
        -->
        <echo>HelloWorld.json validation checking with jslint using ${jslint.jar}</echo>
        <java classname="com.googlecode.jslint4java.cli.Main" classpath="${jslint.jar}" fork="${fork}">
            <arg value="HelloWorld.json"/>
        </java>
        <!-- native Ant target jslint is buggy, see TODO bug report
        <jslint options="${jslint.options}">
            <formatter type="plain" destfile="jslint.out"/>
            <fileset   file="HelloWorld.json"/>
        </jslint>
        -->
        <echo>HelloWorld.json validation checking with ${json-schema-validator.jar}</echo>
        <java jar="${json-schema-validator.jar}" fork="${fork}">
            <arg value="../../../../specifications/x3d-3.3-JSONSchema.json"/>
            <arg value="HelloWorld.json"/>
        </java>
        <echo>HelloWorld.java creation with X3dToJava.xslt</echo>
        <!-- JavaScript Object Notation (JSON) -->
        <Saxon11  scene="HelloWorld"
            stylesheet="${stylesheet.dir}/X3dToJava"
             extension="java"
                expand="on"
        parameterPair1="className=HelloWorld"
        parameterPair2="strictJava8=false"/>
	<!-- expand:on since DTD defaults needed -->
        <echo>HelloWorld.py creation with X3dToPython.xslt</echo>
        <!-- JavaScript Object Notation (JSON) -->
        <Saxon11  scene="HelloWorld"
            stylesheet="${stylesheet.dir}/X3dToPython"
             extension="py"
				expand="on"
        parameterPair1="insertPackagePrefix=false"/>
		<!-- expand:on since DTD defaults needed -->
        <echo>HelloWorld.ttl creation with X3dToTurtle.xslt</echo>
        <!-- Turtle .ttl -->
        <Saxon11  scene="HelloWorld"
            stylesheet="${stylesheet.dir}/X3dToTurtle"
             extension="ttl"
				expand="on"
        parameterPair1="defaultModelPrefix="/>
		<!-- expand:on since DTD defaults needed -->
        <echo message="${arq} --data ${semantics.dir}/ontologies/X3dOntology4.0.ttl --query ${semantics.dir}/queries/X3dHelloWorldQuery_03.rq --graph HelloWorld.ttl"/>
        <exec executable="${arq}"  dir="." vmlauncher="false" timeout="${timeout}">
            <arg value="--graph"/>
            <arg value="HelloWorld.ttl"/>
            <arg value="--data"/>
            <arg value="${semantics.dir}/ontologies/X3dOntology4.0.ttl"/>
            <arg value="--query"/>
            <arg value="${semantics.dir}/queries/X3dHelloWorldQuery_03.rq"/>
            <redirector output="HelloWorld.rq.txt" alwayslog="true" append="true"/>
        </exec>

        <if>
            <not>
                <equals arg1="${jenkins.prepared}" arg2="true" />
            </not>
            <then>
                <echo message="all conversions complete, save results in parent directory next to master copy of HelloWorld.x3d"/>
                <copy todir=".." overwrite="true" verbose="true">
                    <fileset dir="." includes="HelloWorld.x3dv"/>
                    <fileset dir="." includes="HelloWorld.x3db"/>
                    <fileset dir="." includes="HelloWorld.wrl"/>
                    <fileset dir="." includes="HelloWorld.json"/>
                    <fileset dir="." includes="HelloWorld.java"/>
                    <fileset dir="." includes="HelloWorld.py"/>
                    <fileset dir="." includes="HelloWorld.ttl"/>
                    <fileset dir="." includes="HelloWorld.rq.txt"/>
                    <fileset dir="." includes="HelloWorld.html"/>
                    <fileset dir="." includes="HelloWorldX_ITE.html"/>
                    <fileset dir="." includes="HelloWorldX3dom.xhtml"/>
                    <fileset dir="." includes="HelloWorldCanonical.xml"/>
                </copy>
            </then>
        </if>
    </target>

    <target name="newScene" description="Copy newScene.x3d example from common example archives and convert to other encodings" depends="get.web3d.saxon">
        <delete failonerror="false">
            <fileset dir="." includes="newScene*"/>
            <fileset dir="." includes="newSceneX_ITE.html"/>
            <fileset dir="." includes="newSceneX3dom.xhtml"/>
        </delete>
        <if>
            <equals arg1="${use.sourceforge.site}" arg2="true" />
            <then>
                <get src="${x3d.sourceforge.site}/x3d/content/examples/X3dForWebAuthors/Chapter01TechnicalOverview/newScene.x3d?format=raw"
                    dest="newScene.x3d" ignoreerrors="${ignoreSetupDownloadErrors}"/>
            </then>
            <else>
                <copy file="../newScene.x3d"             todir="." overwrite="true" failonerror="true" verbose="true" preservelastmodified="true"/>
            </else>
        </if>
        <echo message="X3dCatalog X3dDtdsSchemas.dir=${X3dDtdsSchemas.dir}"/>
        <echo message="check well-formedness"/>
        <xmlvalidate file="newScene.x3d" failonerror="false" warn="true" lenient="true"/>
        <echo message="check DTD validation"/>
        <xmlvalidate file="newScene.x3d" failonerror="false" warn="true">
            <xmlcatalog refid="X3dCatalog"/>
            <!-- TODO get xmlcatalog working under jenkins
            <attribute name="http://xml.org/sax/features/validation" value="true"/>
            <attribute name="http://xml.org/sax/features/namespaces" value="true"/>
            -->
        </xmlvalidate>
        <echo message="Convert newScene.x3d to newScene.html using X3dToXhtml.xslt regular stylesheet"/>
        <!-- https://www.saxonica.com/documentation/#!using-xsl/commandline                           -->
        <!-- java net.sf.saxon.Transform -s:source -o:output -xsl:stylesheet -->
        <!-- $(SAXON) -t -s:newScene.x3d -o:newScene.html -xsl:../X3dToXhtml.xslt -->
        <!-- note reordering of parameters for source, output contrary to Saxon documentation! -->
        <java classname="net.sf.saxon.Transform" classpath="${saxon.classpath}" fork="${fork}">
            <arg value="-warnings:recover"/> <!-- recover after writing a warning message -->
            <!-- <arg value="-t"/> saxon version and timing information -->
            <arg value="-s:newScene.x3d"/>
            <arg value="-o:newScene.html"/>
            <arg value="-xsl:${stylesheet.dir}/X3dToXhtml.xslt"/>
        </java>
        <echo message="Convert newScene.x3d to newSceneX_ITE.html using X3dToX3domX_ITE.xslt stylesheet in X_ITE mode"/>
        <java classname="net.sf.saxon.Transform" classpath="${saxon.classpath}" fork="${fork}">
            <arg value="-warnings:recover"/> <!-- recover after writing a warning message -->
            <!-- <arg value="-t"/> saxon version and timing information -->
            <arg value="-s:newScene.x3d"/>
            <arg value="-o:newSceneX_ITE.html"/>
            <arg value="-xsl:${stylesheet.dir}/X3dToX3domX_ITE.xslt"/>
            <arg value="player=X_ITE"/>
            <arg value="suffix=X_ITE"/>
            <arg value="urlScene=newScene.x3d"/>
            <arg value="extension=html"/>
        </java>
        <echo message="Convert newScene.x3d to newSceneX3dom.xhtml using X3dToX3domX_ITE.xslt stylesheet in default mode"/>
        <java classname="net.sf.saxon.Transform" classpath="${saxon.classpath}" fork="${fork}">
            <arg value="-warnings:recover"/> <!-- recover after writing a warning message -->
            <!-- <arg value="-t"/> saxon version and timing information -->
            <arg value="-s:newScene.x3d"/>
            <arg value="-o:newSceneX3dom.xhtml"/>
            <arg value="-xsl:${stylesheet.dir}/X3dToX3domX_ITE.xslt"/>
        </java>
        <echo message="Convert newScene.x3d to newScene.wrl using X3dToVrml97.xslt regular stylesheet"/>
        <java classname="net.sf.saxon.Transform" classpath="${saxon.classpath}" fork="${fork}">
            <arg value="-warnings:recover"/>
            <!-- <arg value="-t"/> saxon version and timing information -->
            <arg value="-s:newScene.x3d"/>
            <arg value="-o:newScene.wrl"/>
            <arg value="-xsl:${stylesheet.dir}/X3dToVrml97.xslt"/>
        </java>
        <echo message="Convert newScene.x3d to newScene.x3dv using X3dToX3dvClassicVrmlEncoding.xslt regular stylesheet"/>
        <java classname="net.sf.saxon.Transform" classpath="${saxon.classpath}" fork="${fork}">
            <arg value="-warnings:recover"/> 
            <arg value="-s:newScene.x3d"/>
            <arg value="-o:newScene.x3dv"/>
            <arg value="-xsl:${stylesheet.dir}/X3dToX3dvClassicVrmlEncoding.xslt"/>
        </java>
        <echo message="Convert newScene.x3d to newSceneCanonical.xml using canonicalX3D"/>
        <!-- canonicalX3D is locally defined macro -->
        <canonicalX3D scene="${basedir}/newScene"/>
        <!-- now compressed binary encoding -->
        <echo message="Convert newScene.x3d to newSceneCanonical.x3db using Xj3D cadfilter"/>
        <echo message=".x3db binary conversion depends on local Xj3D installation, current directory xj3d.dir=${xj3d.dir}"/>
		<java classname="xj3d.filter.CDFFilter" fork="${fork}" dir=".">
            <classpath>
                <pathelement path="${saxon.classpath}"/>
                <fileset refid="xj3d.jars.all"/>
            </classpath>
            <arg value="Identity"/>
            <arg value="newScene.x3d"/>
            <arg value="newScene.x3db"/>
        </java>
        <!-- JavaScript Object Notation (JSON) -->
        <echo>newScene.json creation with X3dToJson.xslt</echo>
        <Saxon11  scene="newScene"
            stylesheet="${stylesheet.dir}/X3dToJson"
             extension="json"
				expand="on"/>
		<!-- expand:on since DTD defaults needed -->
        <!-- Default options:
        parameterPair1="traceEnabled=false"
        parameterPair2="sceneGraphOnly=false"
        parameterPair3="stripComments=false"
        -->
        <echo>newScene.json validation checking with jslint using ${jslint.jar}</echo>
        <java classname="com.googlecode.jslint4java.cli.Main" classpath="${jslint.jar}" fork="${fork}">
            <arg value="newScene.json"/>
        </java>
        <!-- native Ant target jslint is buggy, see TODO bug report
        <echo>newScene.json validation checking with jslint</echo>
        <jslint options="${jslint.options}">
            <formatter type="plain" destfile="jslint.out"/>
            <fileset   file="newScene.json"/>
        </jslint>
        -->
        <echo>newScene.json validation checking with ${json-schema-validator.jar}</echo>
        <java jar="${json-schema-validator.jar}" fork="${fork}">
            <arg value="../../../../specifications/x3d-3.3-JSONSchema.json"/>
            <arg value="newScene.json"/>
        </java>
        <echo>newScene.java creation with X3dToJava.xslt</echo>
        <!-- JavaScript Object Notation (JSON) -->
        <Saxon11  scene="newScene"
            stylesheet="${stylesheet.dir}/X3dToJava"
             extension="java"
		expand="on"
        parameterPair1="className=newScene"
        parameterPair2="strictJava8=false"/>
        <!-- expand:on since DTD defaults needed -->
        <echo>newScene.py creation with X3dToPython.xslt</echo>
        <!-- JavaScript Object Notation (JSON) -->
        <Saxon11  scene="newScene"
            stylesheet="${stylesheet.dir}/X3dToPython"
             extension="py"
				expand="on"
        parameterPair1="insertPackagePrefix=false"/>
		<!-- expand:on since DTD defaults needed -->
        <echo>HelloWorld.ttl creation with X3dToTurtle.xslt</echo>
        <!-- Turtle .ttl -->
        <Saxon11  scene="newScene"
            stylesheet="${stylesheet.dir}/X3dToTurtle"
             extension="ttl"
				expand="on"
        parameterPair1="defaultModelPrefix="/>
		<!-- expand:on since DTD defaults needed -->
        <echo message="${arq} --data ${semantics.dir}/ontologies/X3dOntology4.0.ttl --query ${semantics.dir}/queries/X3dHelloWorldQuery_03.rq --graph newScene.ttl"/>
        <exec executable="${arq}"  dir="." vmlauncher="false" timeout="${timeout}">
            <arg value="--graph"/>
            <arg value="newScene.ttl"/>
            <arg value="--data"/>
            <arg value="${semantics.dir}/ontologies/X3dOntology4.0.ttl"/>
            <arg value="--query"/>
            <arg value="${semantics.dir}/queries/X3dHelloWorldQuery_03.rq"/>
            <redirector output="newScene.rq.txt" alwayslog="true" append="true"/>
        </exec>
		
        <if>
            <not>
                <equals arg1="${jenkins.prepared}" arg2="true" />
            </not>
            <then>
                <echo message="all conversions complete, save results in parent directory next to master copy"/>
                <copy todir=".." overwrite="true" verbose="true">
                    <fileset dir="." includes="newScene.x3dv"/>
                    <fileset dir="." includes="newScene.x3db"/>
                    <fileset dir="." includes="newScene.wrl"/>
                    <fileset dir="." includes="newScene.html"/>
                    <fileset dir="." includes="newScene.json"/>
                    <fileset dir="." includes="newScene.java"/>
                    <fileset dir="." includes="newScene.py"/>
                    <fileset dir="." includes="newScene.ttl"/>
                    <fileset dir="." includes="newScene.rq.txt"/>
                    <fileset dir="." includes="newSceneX_ITE.html"/>
                    <fileset dir="." includes="newSceneX3dom.xhtml"/>
                    <fileset dir="." includes="newSceneCanonical.xml"/>
                </copy>
            </then>
        </if>
    </target>
		
    <target name="validate.full" description="XML well formed, DTD and schematron validation for all .x3d examples"
        depends="validate.DTD,validate.schema.all,validate.schema.wildcard.x3dv4,validate.schematron">
        <antcall target="echo.timestamp"/>
        <echo message="validate.full using all methods: ${archive.name} archive complete"/>
        <!-- TODO
        <echo message="warning: schema validation of all files is a bit slow and is prone to java.lang.StackOverflowError within Ant"/>
        <antcall target="validate.schema.wildcard"/><!- - possible problem: xmlcatalog not working, x3d schema is getting downloaded each time - ->
        <antcall target="validate.xmllint"/>
        -->
		<!-- TODO validate.schema.saxonicaSA, -->
    </target>

    <target name="validate.DTD" description="XML well formed checks and X3D DTD validation for all .x3d examples"
        depends="clean.duplicates">
        <!-- XML well-formed checks -->
        <echo message="XML well-formed check: ${archive.name} build.xml and scenes"/>
        <echo message="Verifying Apache Ant XML Catalog resolver classpath: ${resolver.dir}/${resolver.jar} (${resolver.jar.length} bytes)"/>
        <xmlvalidate failonerror="false" warn="true" lenient="true" file="build.xml"/>
        <echo message="X3D DTDs and schemas available at https://www.web3d.org/specifications"/>
        <echo message="check well-formedness of X3D scenes"/>
        <xmlvalidate failonerror="false" warn="true" lenient="true">
            <!-- only check *.x3d files of interest (and *Canonical.xml versions as a double-check) not grandchild directories holding errors or work in progress -->
            <fileset refid="x3dScenes"/>
            <fileset refid="xmlFiles"/>
            <xmlcatalog refid="X3dCatalog"/>
            <!-- TODO get xmlcatalog working under jenkins
            <attribute name="http://xml.org/sax/features/validation" value="true"/>
            <attribute name="http://xml.org/sax/features/namespaces" value="true"/>
            -->
        </xmlvalidate>
        <!-- X3D DTD validation -->
        <echo message="Validate using X3D DTD: ${archive.name} archive"/>
        <xmlvalidate failonerror="false" warn="true" lenient="false">
            <xmlcatalog refid="X3dCatalog"/>
            <!-- only check *.x3d files of interest (and *Canonical.xml versions as a double-check) not grandchild directories holding errors or work in progress -->
            <fileset refid="x3dScenes"/>
            <fileset refid="xmlFiles"/>
            <!-- TODO get xmlcatalog working under jenkins
            <attribute name="http://xml.org/sax/features/validation" value="true"/>
            <attribute name="http://xml.org/sax/features/namespaces" value="true"/>
            -->
        </xmlvalidate>
        <echo>validate.DTD complete.</echo>
    </target>

    <target name="validate.schema.wildcard" description="XML validation for all .x3d examples using X3D schema as declared in scenes (caution, time consuming unless xmlcatalog points to local copy)"
        depends="clean.duplicates">
        <!-- X3D schema validation -->
        <echo message="Validate using X3D schema as declared in scenes: ${archive.name} archive"/>
        <echo message="X3D DTDs and schemas available at https://www.web3d.org/specifications"/>
        <!-- TODO need to try increasing stack space to 16m, fullchecking true results in java.lang.StackOverflowError
        at com.sun.org.apache.xerces.internal.impl.xpath.regex.RegularExpression.matchString(RegularExpression.java:1903) -->
        <schemavalidate failonerror="false" fullchecking="false" lenient="false" warn="true">
            <xmlcatalog refid="X3dCatalog"/>
            <!-- only check *.x3d files of interest, not grandchild directories holding errors or work in progress -->
            <fileset refid="x3dScenes"/>
            <!-- TODO get xmlcatalog working under jenkins
            <attribute name="http://xml.org/sax/features/validation" value="true"/>
            <attribute name="http://xml.org/sax/features/namespaces" value="true"/>
            -->
        </schemavalidate>
    </target>

    <target name="validate.schema.wildcard.x3dv4" description="XML validation for all .x3d examples using X3Dv4 schema (caution, time consuming unless xmlcatalog points to local copy)"
        depends="clean.duplicates">
        <!-- X3D schema validation -->
        <echo message="Validate using X3D schema version 4.0: ${archive.name} archive"/>
        <echo message="X3D DTDs and schemas available at https://www.web3d.org/specifications"/>
        <!-- TODO need to try increasing stack space to 16m, fullchecking true results in java.lang.StackOverflowError
        at com.sun.org.apache.xerces.internal.impl.xpath.regex.RegularExpression.matchString(RegularExpression.java:1903) -->
        <schemavalidate failonerror="false" fullchecking="true" lenient="false" warn="true"
						noNamespaceFile="${X3dDtdsSchemas.dir}/x3d-4.0.xsd">
            <xmlcatalog refid="X3dCatalog"/>
            <!-- only check *.x3d files of interest, not grandchild directories holding errors or work in progress -->
            <fileset refid="x3dScenes"/>
            <!-- TODO get xmlcatalog working under jenkins
            <attribute name="http://xml.org/sax/features/validation" value="true"/>
            <attribute name="http://xml.org/sax/features/namespaces" value="true"/>
            -->
        </schemavalidate>
    </target>

    <target name="validate.schema.all" description="XML validation for new or modified .x3d examples using X3D schema as declared in scenes"
        depends="clean.duplicates">
        <echo message="Validate using X3D schema as declared in scenes: ${archive.name} archive, new scenes"/>
        <echo message="X3D DTDs and schemas available at https://www.web3d.org/specifications"/>
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="name.short"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
                <outofdate>
                    <sourcefiles>
                        <filelist>
                            <file name="@{file.path.name}"/>
                        </filelist>
                    </sourcefiles>
                    <mapper dir="." type="glob" from="*.x3d" to="*Canonical.xml"/>
                    <sequential>
                        <!-- process individual files here.  show full path to facilitate user loading, editing of reported files -->
                        <echo message="@{file.path.name} validation using X3D schema..."/>
                        <schemavalidate file="@{file.path.name}" lenient="false" failonerror="false" fullchecking="true">
                            <xmlcatalog refid="X3dCatalog"/>
            <!-- TODO get xmlcatalog working under jenkins
            <attribute name="http://xml.org/sax/features/validation" value="true"/>
            <attribute name="http://xml.org/sax/features/namespaces" value="true"/>
            -->
                        </schemavalidate>
                    </sequential>
                </outofdate>
            </sequential>
        </for>
        <echo>validation complete.  run processScenes.canonicalX3D to change status of "new" scenes to confirmed..</echo>
        <echo>validate.schema.all complete.</echo>
    </target>

    <target name="validate.schema.saxonicaSA" description="XML validation for all .x3d examples using X3D schema as declared in scenes (caution, time consuming unless xmlcatalog points to local copy)"
        depends="clean.duplicates">
        <!-- X3D schema validation -->
        <echo message="Validate using X3D schema as declared in scenes,saxonicaSA: ${archive.name} archive"/>
        <echo message="https://www.web3d.org/specifications https://www.saxonica.com"/>
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <echo message="@{file.path.name} validation using X3D schema, saxononicaSA..."/>
                <java classname="com.saxonica.Validate" classpath="${saxononicaSA.dir}/saxon9sa.jar;${saxononicaSA.dir};${saxononicaSA.dir}/saxon-license.lic;." fork="false">
                    <arg value="@{file.path.name}"/>
                </java>
            </sequential>
        </for>
    </target>

    <target name="validate.schematron.singleFile" description="validate one .x3d scene">
        <!-- TODO customize singleFilePath, singleFileName as desired -->
        <property name="singleFilePath" location="AudioSpatialSound"/>
        <property name="singleFileName"    value="AllAudioGraphNodesTest"/><!-- no file extension -->
        
        <echo>${singleFilePath}/${singleFileName}.x3d validation using X3D Schematron rules</echo>
        <java classname="net.sf.saxon.Transform" classpath="${saxon.classpath}" fork="false">
            <arg value="-warnings:recover"/>
            <arg value="-s:${singleFilePath}"/>
            <arg value="-o:${singleFilePath}/_schematron/${singleFileName}.svrl"/> <!-- ${archive.path}/ -->
            <arg value="-xsl:${X3dSchematronValidityChecks.dir}/${X3dSchematronValidityChecks}.xslt"/>
        </java>
        <java classname="net.sf.saxon.Transform" classpath="${saxon.classpath}" fork="false">
            <arg value="-warnings:recover"/>
            <arg value="-s:${singleFilePath}/_schematron/${singleFileName}.svrl"/>
            <arg value="-o:${singleFilePath}/_schematron/${singleFileName}.svrl.txt"/> <!-- ${archive.path}/ -->
            <arg value="-xsl:${X3dSchematronValidityChecks.dir}/${SvrlReportText}.xslt"/>
        </java>
        <concat>
            <filelist dir="." files="${singleFilePath}/_schematron/${singleFileName}.svrl.txt"/>
        </concat>
    </target>

    <target name="validate.schematron" description="validate each .x3d scene using X3D Schematron rules (caution: time consuming unless xmlcatalog points to local copy)"
        depends="get.web3d.saxon,clean.duplicates">
        <echo message="Validate using X3D Schematron: ${archive.name} archive"/>
        <echo message="   using ${X3dSchematronValidityChecks.dir}/${X3dSchematronValidityChecks}.xslt"/>
        <echo message="https://www.web3d.org/x3d/tools/schematron/X3dSchematron.html"/>
        <echo>====================================================================================================================</echo>
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="name.short"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
                <!-- trace
                <echo></echo>
                <echo>@file.path.name       = @{file.path.name}</echo>
                <echo>$archive.path         = ${archive.path}</echo>
                <echo>$relative.path1       = ${relative.path1}</echo>
                <echo>$relative.path2       = ${relative.path2}</echo>
                <echo>$name.short           = ${name.short}</echo>
                -->
                <outofdate>
                    <sourcefiles>
                        <filelist>
                            <file name="@{file.path.name}"/>
                        </filelist>
                    </sourcefiles>
                    <mapper dir="." type="glob" from="*.x3d" to="_schematron/*.svrl"/>
                    <sequential>
                        <!-- process individual files here.  show full path to facilitate user loading, editing of reported files -->
                        <mkdir dir="${archive.path}/${relative.path1}/${relative.path2}/_schematron"/>
                        <!-- regular .xslt stylesheet using Ant task:
                        <echo>@{file.path.name} validation using source X3D Schematron rules</echo>
                        <xslt basedir="." destdir="." extension=""
                              style="${X3dSchematronValidityChecks.dir}/${X3dSchematronValidityChecks}.xslt"
                                 in="@{file.path.name}"
                                out="${archive.path}/${relative.path1}/${relative.path2}/_schematron/${name.short}.svrl">
                            <xmlcatalog refid="X3dCatalog"/>
                        </xslt>
                        <xslt basedir="." destdir="." extension=""
                              style="${X3dSchematronValidityChecks.dir}/${SvrlReportText}.xslt"
                                 in="${archive.path}/${relative.path1}/${relative.path2}/_schematron/${name.short}.svrl"
                                out="${archive.path}/${relative.path1}/${relative.path2}/_schematron/${name.short}.svrl.txt">
                            <xmlcatalog refid="X3dCatalog"/>
                        </xslt>
                        -->
                        <echo>@{file.path.name} validation using X3D Schematron rules</echo>
                        <java classname="net.sf.saxon.Transform" classpath="${saxon.classpath}" fork="false">
                            <arg value="-warnings:recover"/>
                            <arg value="-s:@{file.path.name}"/>
                            <arg value="-o:${relative.path1}/${relative.path2}/_schematron/${name.short}.svrl"/> <!-- ${archive.path}/ -->
                            <arg value="-xsl:${X3dSchematronValidityChecks.dir}/${X3dSchematronValidityChecks}.xslt"/>
                        </java>
                        <java classname="net.sf.saxon.Transform" classpath="${saxon.classpath}" fork="false">
                            <arg value="-warnings:recover"/>
                            <arg value="-s:${relative.path1}/${relative.path2}/_schematron/${name.short}.svrl"/>
                            <arg value="-o:${relative.path1}/${relative.path2}/_schematron/${name.short}.svrl.txt"/> <!-- ${archive.path}/ -->
                            <arg value="-xsl:${X3dSchematronValidityChecks.dir}/${SvrlReportText}.xslt"/>
                        </java>
                        <concat>
                            <filelist dir="." files="${relative.path1}/${relative.path2}/_schematron/${name.short}.svrl.txt"/>
                        </concat>
                        <echo>====================================================================================================================</echo>
                    </sequential>
                </outofdate>
            </sequential>
        </for>
        <echo>validate.schematron complete.</echo>
    </target>

    <!-- prerequisite:  xmllint installed on system path.
         provided as part of libxml library, https://xmlsoft.org
         suggested installation for Windows is cygwin, https://cygwin.com -->
    <!-- TODO:  not working
    -->
    <target name="validate.xmllint">
        <echo>Warning: xmllint appears to be unable to handle complexity of X3D content model, incorrectly reporting nondeterminism errors</echo>
        <for param="filenames">
            <path>
                <fileset dir="." includes="**/*.x3d"/>
            </path>
            <sequential>
                <propertyregex
                    property="path.scene"
                    override="true"
                    input="@{filenames}"
                    regexp="([^\n]*)[\\|/][^\\]*\.x3d"
                    select="\1"/>
                <propertyregex
                    property="filename.prefix"
                    override="true"
                    input="@{filenames}"
                    regexp="([^\\]*\\)*([^\n]*)\.x3d"
                    select="\2"/>
                <echo>Processing ${path.scene}/${filename.prefix}.x3d with xmllint</echo>
                <exec executable="xmllint" vmlauncher="false" timeout="${timeout}"><!-- timeout in case process hangs --><!-- vmlauncher switch needed for netbeans invocation -->
                    <arg value="--version"/><!-- display the version of the XML library used -->
                    <arg value="--valid"/>	<!-- validate the document in addition to std well-formed check -->
                    <arg value="--noout"/>	<!-- don't output the result tree -->
                    <!-- <arg value="- -dtdvalid  https://www.web3d.org/specifications/x3d-4.0.dtd"/>
											do a posteriori validation against a given DTD -->
					<arg value="${path.scene}/${filename.prefix}.x3d"/>
                </exec>
            </sequential>
        </for>
    </target>

    <target name="refresh.local" depends="echo.timestamp,versions,clean.backups,clean.duplicates,clean.RoundTrip,clean.X3dTidy,commonSetup,processScenes,catalog" description="quick master refresh of all .x3d examples:  processScenes, catalog, zip">
        <!-- unreliable when network delays occur: validate.DTD -->
        <antcall target="echo.timestamp"/>
        <echo message="${archive.name} refresh.local complete."/>
    </target>

    <target name="refresh.upload" depends="refresh.local,zip,upload" description="quick master refresh of all .x3d examples, then upload">
        <antcall target="echo.timestamp"/>
        <echo message="${archive.name} refresh.upload complete."/>
    </target>

    <target name="refresh.upload.scenes" depends="refresh.local,upload.scenes" description="quick master refresh of all .x3d examples, then upload scenes only (not .zip)">
        <antcall target="echo.timestamp"/>
        <echo message="${archive.name} refresh.upload.scenes complete."/>
    </target>

    <!-- TODO:  subversion update, potentially will need to deconflict naming of tasks -->
    <target name="update.subversion.draft" depends="clean.backups,commonSetup,processScenes" description="update online versions for all .x3d examples">
        <!-- TODO subversion task here -->
        <echo message="${archive.name} update complete."/>
    </target>

    <target name="upload" description="upload all x3d examples and archive files, including .zip">
        <ant dir=".." target="scp.uploadExampleUpdates.${archive.name}"/>
        <antcall target="echo.timestamp"/>
        <echo message="${archive.name} upload complete."/>
    </target>

    <target name="upload.pages" description="upload catalog pages in examples archive (overwrite previous versions), do not upload .zip">
        <ant dir=".." target="scp.uploadExampleUpdates.${archive.name}.pages"/>
        <antcall target="echo.timestamp"/>
        <echo message="${archive.name} upload.pages complete."/>
    </target>

    <target name="upload.scenes" depends="clean.backups,clean.duplicates,clean.RoundTrip,clean.X3dTidy" description="upload scenes in examples archive (overwrite previous versions), do not upload .zip">
        <ant dir=".." target="scp.uploadExampleUpdates.${archive.name}.scenes"/>
        <antcall target="echo.timestamp"/>
        <echo message="${archive.name} upload.scenes complete."/>
    </target>

    <target name="upload.zip" description="upload current .zip examples archive (overwrite previous version)">
        <ant dir=".." target="scp.uploadExampleUpdates.${archive.name}.zip"/>
        <antcall target="echo.timestamp"/>
        <echo message="${archive.name}.zip upload complete."/>
    </target>

    <target name="processScenes" description="process all scenes with all conversion tasks" depends="get.web3d.saxon">
        <echo>TODO: note that if Viewpoint descriptions changed, or the visible rendered scene changed,</echo>
        <echo>      then you must delete the pretty-print .html version in order to trigger target task</echo>
        <echo>      processScenes.captureImages that regenerates the viewpoint snapshot images.</echo>
        <!-- processScenes.regularExpressionChecks occurs first because provides diagnostic scene correctness checks -->
        <!-- processScenes.canonicalX3D            occurs second because it replaces original .x3d scene -->
        <!-- processScenes.X3DtoVRML97             occurs third because provides diagnostic scene  correctness checks -->
        <!-- processScripts.jslint, X3dToJson      occur  fourth,fifth & provide diagnostic script correctness checks -->
        <!-- processScenes.captureImages           occurs sixth because it must be performed before processScenes.htmlPrettyPrintPages -->
        <!-- this task depends on other tasks to look through the directories, only updating as needed -->
        <antcall target="processScenes.regularExpressionChecks"/>
        <antcall target="processScenes.canonicalX3D"/>
        <antcall target="processScenes.X3DtoVRML97"/>
        <antcall target="processScenes.java"/>
        <antcall target="processScenes.javadoc"/>
        <antcall target="processScripts.jslint"/>
        <antcall target="processScenes.json"/>
        <antcall target="processScenes.python"/>
        <antcall target="processScenes.turtle"/>
        <antcall target="processScenes.X3dToX_ITE.html"/>
        <antcall target="processScenes.X3dToX3domXhtml"/>
        <antcall target="processScenes.X3dToX3dvClassicVrmlEncoding"/>
        <antcall target="processScenes.X3dToX3dbCompressedBinaryEncoding"/>
        <!-- processScenes.captureImages need to precede processScenes.htmlPrettyPrintPages
        <antcall target="processScenes.captureImages"/> -->
        <antcall target="processScenes.htmlPrettyPrintPages"/>
        <echo message="${archive.name} processScenes complete."/>
    </target>

    <target name="processScenes.htmlPrettyPrintPages" description="convert each .x3d scene into pretty-print .html version, also generate SVG diagrams of 2D plots such as Extrusion crossSection" depends="get.web3d.saxon">
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="name.short"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
                <!-- trace
                <echo></echo>
                <echo>@file.path.name       = @{file.path.name}</echo>
                <echo>$archive.path         = ${archive.path}</echo>
                <echo>$relative.path1       = ${relative.path1}</echo>
                <echo>$relative.path2       = ${relative.path2}</echo>
                <echo>$name.short           = ${name.short}</echo>
                -->
                <outofdate>
                    <sourcefiles>
                        <filelist>
                            <file name="@{file.path.name}"/>
                        </filelist>
                    </sourcefiles>
                    <mapper dir="." type="glob" from="*.x3d" to="*.html"/>
                    <sequential>
                        <!-- process individual files here. show full path to facilitate user loading, editing of reported files -->
                        <echo>${archive.path}/${relative.path1}/${relative.path2}/${name.short}.x3d processing with X3dToXhtml stylesheet for pretty-print .html</echo>
                        <!-- Saxon11 is locally defined macro -->
                        <Saxon11  scene="${relative.path1}/${relative.path2}/${name.short}"
                            stylesheet="${stylesheet.dir}/X3dToXhtml"
                             extension="html"
                        parameterPair1="linkImages=true"
				expand="on"/>
			<!-- expand:on since DTD defaults needed -->
                        <echo>${archive.path}/${relative.path1}/${relative.path2}/${name.short}.x3d processing with X3dExtrusionCrossSectionToSvg stylesheet for SVG diagrams (if Extrusion found)</echo>
                        <!-- Saxon11 is locally defined macro -->
                        <Saxon11  scene="${relative.path1}/${relative.path2}/${name.short}"
                            stylesheet="${stylesheet.dir}/X3dExtrusionCrossSectionToSvg"
                             extension="svg"
                                expand="on"/>
                        <!-- expand:on since DTD defaults needed -->
                    </sequential>
                </outofdate>
            </sequential>
        </for>
        <!-- clean up erroneously created namespace artifacts -->
        <replace dir="." token=' xmlns=""' value="">
            <include name="**/*.svg"/>
        </replace>
        <antcall target="echo.timestamp"/>
        <echo>processScenes.htmlPrettyPrintPages complete.</echo>
    </target>

    <target name="processScenes.X3dToX3domXhtml" description="convert each .x3d scene into *X3dom.xhtml version for X3DOM" depends="get.web3d.saxon,clean.RoundTrip">
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="name.short"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
                <!-- trace
                <echo></echo>
                <echo>@file.path.name       = @{file.path.name}</echo>
                <echo>$archive.path         = ${archive.path}</echo>
                <echo>$relative.path1       = ${relative.path1}</echo>
                <echo>$relative.path2       = ${relative.path2}</echo>
                <echo>$name.short           = ${name.short}</echo>
                -->
                <outofdate>
                    <sourcefiles>
                        <filelist>
                            <file name="@{file.path.name}"/>
                        </filelist>
                    </sourcefiles>
                    <mapper dir="." type="glob" from="*.x3d" to="*X3dom.xhtml"/>
                    <sequential>
                        <!-- process individual files here. show full path to facilitate user loading, editing of reported files -->
                        <echo>${archive.path}/${relative.path1}/${relative.path2}/${name.short}.x3d processing with X3dToX3domX_ITE stylesheet:</echo>
                        <echo>${archive.path}/${relative.path1}/${relative.path2}/${name.short}X3dom.xhtml</echo>
                        <!-- Saxon11 is locally defined macro -->
                        <Saxon11  scene="${relative.path1}/${relative.path2}/${name.short}"
                            stylesheet="${stylesheet.dir}/X3dToX3domX_ITE"
                        parameterPair1="player=X3DOM"
                                suffix="X3dom"
                             extension="xhtml"
				expand="on"/>
			<!-- expand:on since DTD defaults needed -->
                    </sequential>
                </outofdate>
            </sequential>
        </for>
        <!-- clean up erroneously created namespace artifacts -->
        <replace dir="." token=' xmlns=""' value="">
            <include name="**/*X3dom.xhtml"/>
        </replace>
        <antcall target="echo.timestamp"/>
        <echo>processScenes.X3dToX3domXhtml complete.</echo>
    </target>

    <target name="processScenes.X3dToX_ITE.html" description="convert each .x3d scene into *X_ITE.html version for X3DOM" depends="get.web3d.saxon,clean.RoundTrip">
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="name.short"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
                <!-- trace
                <echo></echo>
                <echo>@file.path.name       = @{file.path.name}</echo>
                <echo>$archive.path         = ${archive.path}</echo>
                <echo>$relative.path1       = ${relative.path1}</echo>
                <echo>$relative.path2       = ${relative.path2}</echo>
                <echo>$name.short           = ${name.short}</echo>
                -->
                <outofdate>
                    <sourcefiles>
                        <filelist>
                            <file name="@{file.path.name}"/>
                        </filelist>
                    </sourcefiles>
                    <mapper dir="." type="glob" from="*.x3d" to="*X_ITE.html"/>
                    <sequential>
                        <!-- process individual files here. show full path to facilitate user loading, editing of reported files -->
                        <echo>${archive.path}/${relative.path1}/${relative.path2}/${name.short}.x3d processing with X3dToX3domX_ITE stylesheet: ${name.short}X_ITE.html</echo>
                        <!-- Saxon11 is locally defined macro -->
                        <Saxon11  scene="${relative.path1}/${relative.path2}/${name.short}"
                            stylesheet="${stylesheet.dir}/X3dToX3domX_ITE"
                        parameterPair1="player=X_ITE"
                        parameterPair2="urlScene=${name.short}.x3d"
                                suffix="X_ITE"
                             extension="html"
				expand="on"/>
			<!-- expand:on since DTD defaults needed -->
                    </sequential>
                </outofdate>
            </sequential>
        </for>
        <!-- clean up erroneously created namespace artifacts -->
        <replace dir="." token=' xmlns=""' value="">
            <include name="**/*X_ITE.html"/>
        </replace>
        <antcall target="echo.timestamp"/>
        <echo>processScenes.X3dToX_ITE.html complete.</echo>
    </target>

    <target name="processScenes.X3DtoVRML97" description="convert each .x3d scene to .wrl VRML97 encoding" depends="get.web3d.saxon">
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="name.short"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
                <!-- trace
                <echo></echo>
                <echo>@file.path.name       = @{file.path.name}</echo>
                <echo>$archive.path         = ${archive.path}</echo>
                <echo>$relative.path1       = ${relative.path1}</echo>
                <echo>$relative.path2       = ${relative.path2}</echo>
                <echo>$name.short           = ${name.short}</echo>
                -->
                <outofdate>
                    <sourcefiles>
                        <filelist>
                            <file name="@{file.path.name}"/>
                        </filelist>
                    </sourcefiles>
                    <mapper dir="." type="glob" from="*.x3d" to="*.wrl"/>
                    <sequential>
                        <!-- process individual files here.  show full path to facilitate user loading, editing of reported files -->
                        <echo>${archive.path}/${relative.path1}/${relative.path2}/${name.short}.x3d processing with X3dToVrml97 stylesheet</echo>
                        <!-- Saxon11 is locally defined macro -->
                        <Saxon11  scene="${relative.path1}/${relative.path2}/${name.short}"
                            stylesheet="${stylesheet.dir}/X3dToVrml97"
                             extension="wrl"/>
                    </sequential>
                </outofdate>
            </sequential>
        </for>
        <antcall target="echo.timestamp"/>
        <echo>processScenes.X3DtoVRML97 complete.</echo>
    </target>

    <target name="processScripts.jslint" description="run jslint on .js script source files">
        <!-- https://code.google.com/p/jslint4java -->
        <!-- http://docs.jslint4java.googlecode.com/git/2.0.5 -->
        <echo>*.js script validation checking with jslint using jslint4java, https://code.google.com/p/jslint4java</echo>

        <java classname="com.googlecode.jslint4java.cli.Main" classpath="${jslint.jar}" fork="${fork}">
            <arg value="--version"/>
            <arg value="--help"/>
        </java>

        <for param="file.path.name">
            <path>
                <fileset refid="jsFiles"/>
            </path>
            <sequential>
                <echo></echo>
                <!-- regexes are complex!  after special cases, usually either first or second regex pattern works, so the correct one must be chosen -->
                <propertyregex
                        property="path.name.noExtension1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="^([\S]*(?=[\\])[\\])([\w-][\w-]*(?=Script))[Script]?[\w-]*\.js"
                        defaultValue=""
                        select="\1\2"/>
                <propertyregex
                        property="path.name.noExtension2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="^([\S]*(?=[\\])[\\])([\w]*)([\w]*)\.js"
                        defaultValue=""
                        select="\1\2\3"/>
                <!-- regex explanation of groups: (all characters up to last backslash)(single character, allowing files starting with 'Script')(characters prior to Script literal)(.js literal) -->
                <!-- now the correct one must be chosen -->
                <var name="parentX3dSceneName" unset="true"/>
                <if>
                    <contains string="@{file.path.name}" substring="Figure30.1ScriptSlidingBall.js" casesensitive="false"/>
                    <then>
                        <var name="parentX3dSceneName" value="C:\x3d-code\www.web3d.org\x3d\content\examples\Vrml2Sourcebook\Chapter30-Scripts\Figure30.1ScriptSlidingBall.x3d"/>
                    </then>
                    <elseif>
                        <contains string="@{file.path.name}" substring="donutmaker.js" casesensitive="false"/>
                        <then>
                            <var name="parentX3dSceneName" value="C:\x3d-code\www.web3d.org\x3d\content\examples\Vrml2Sourcebook\Chapter30-Scripts\Figure30.5ScriptTorusBuilder.x3d"/>
                        </then>
                    </elseif>
                    <elseif>
                        <contains string="@{file.path.name}" substring="ECMAScriptSaiAddDynamicRoutes.js" casesensitive="false"/>
                        <then>
                            <var name="parentX3dSceneName" value="C:\x3d-code\www.web3d.org\x3d\content\examples\Basic\X3dSpecifications\ECMAScriptSaiAddDynamicRoutes.x3d"/>
                        </then>
                    </elseif>
                    <elseif>
                        <length string="${path.name.noExtension1}" when="greater" length="0"/>
                        <then>
                            <var name="parentX3dSceneName" value="${path.name.noExtension1}.x3d"/>
                            <!-- <echo>... pattern 1, parent1 found</echo> -->
                        </then>
                    </elseif>
                    <elseif>
                        <length string="${path.name.noExtension2}" when="greater" length="0"/>
                        <then>
                            <var name="parentX3dSceneName" value="${path.name.noExtension2}.x3d"/>
                            <!-- <echo>... pattern 2, parent1 not found</echo> -->
                        </then>
                    </elseif>
                    <elseif>
                        <and>
                            <not>
                                <contains string="@{file.path.name}" substring="javadoc" />
                            </not>
                            <not>
                                <contains string="@{file.path.name}" substring="mootool" />
                            </not>
                            <not>
                                <contains string="@{file.path.name}" substring="slideshow." />
                            </not>
                            <equals arg1="@{file.path.name}" arg2=""/>
                        </and>
                        <then>
                            <echo>Warning: no parent scene determined for script, additional false-positive errors may be flagged</echo>
                        </then>
                    </elseif>
                </if>
                <if>
                    <and>
                            <not>
                                <contains string="@{file.path.name}" substring="javadoc" />
                            </not>
                            <not>
                                <contains string="@{file.path.name}" substring="mootool" />
                            </not>
                            <not>
                                <contains string="@{file.path.name}" substring="slideshow." />
                            </not>
                            <not>
                                <equals arg1="@{file.path.name}" arg2=""/>
                            </not>
                    </and>
                    <then>
                        <echo>jslint  @{file.path.name}</echo>

                        <!-- diagnostic
                        <echo>parent1 ${path.name.noExtension1}.x3d</echo>
                        <echo>parent2 ${path.name.noExtension2}.x3d</echo> -->
                        <!-- Expected  X3D scene -->
                        <echo>parent  ${parentX3dSceneName} </echo>
                        <!-- the following filename-match heuristic may well fail, so ensure that default property=values are there.  also ensures that var task doesn't fail on an empty file -->
                        <concat destfile="sceneScriptFieldGlobals.properties">sceneScriptFieldGlobals=Browser,SFBool,MFBool,SFColor,MFColor,SFColorRGBA,MFColorRGBA,SFDouble,MFDouble,SFFloat,MFFloat,SFImage,MFImage,SFInt32,MFInt32,SFMatrix3d,MFMatrix3d,SFMatrix3f,MFMatrix3f,SFMatrix4d,MFMatrix4d,SFMatrix4f,MFMatrix4f,SFNode,MFNode,SFRotation,MFRotation,SFString,MFString,SFTime,MFTime,SFVec2d,MFVec2d,SFVec2f,MFVec2f,SFVec3d,MFVec3d,SFVec3f,MFVec3f,SFVec4d,MFVec4d,SFVec4f,MFVec4f
                        </concat>
                        <echo message="Create list of field names (if any/if found) as script global variables using stylesheet X3dSceneScriptFieldNames.xslt"/>
                        <!-- https://www.saxonica.com/documentation/#!using-xsl/commandline                           -->
                        <!-- java net.sf.saxon.Transform -s:source -o:output -xsl:stylesheet -->
                        <!-- $(SAXON) -t -s:HelloWorld.x3d -o:HelloWorld.html -xsl:../X3dToXhtml.xslt -->
                        <!-- note reordering of parameters for source, output contrary to Saxon documentation! -->
                        <java classname="net.sf.saxon.Transform" classpath="${saxon.classpath}" fork="${fork}">
                            <arg value="-warnings:recover"/> <!-- recover after writing a warning message -->
                            <arg value="-s:${parentX3dSceneName}"/>
                            <arg value="-o:sceneScriptFieldGlobals.properties"/>
                            <arg value="-xsl:${stylesheet.dir}/X3dSceneScriptFieldNames.xslt"/>
                        </java>
                        <var        file="sceneScriptFieldGlobals.properties"/>
                        <!-- debug
                        <echo>file:</echo>
                        <concat>
                            <filelist dir="." files="sceneScriptFieldGlobals.properties"/>
                        </concat>
                        <echo>variable:</echo>
                        -->
                        <!-- debug
                        <echo>sceneScriptFieldGlobals=${sceneScriptFieldGlobals}</echo>
                        -->
                        <java classname="com.googlecode.jslint4java.cli.Main" classpath="${jslint.jar}" fork="${fork}">
                            <!-- command line interface: http://docs.jslint4java.googlecode.com/git/2.0.5/cli.html -->
                            <arg value="--eqeq"/>
                            <arg value="--maxerr"/><arg value="1000"/>
                            <arg value="--plusplus"/>
                            <arg value="--sloppy"/> <!-- the 'use strict'; pragma is optional -->
                            <arg value="--todo"/>
                       <!-- <arg value="- -undef"/> not yet supported by jslint4java -->
                            <arg value="--vars"/>
                            <arg value="--white"/>
                            <!-- build and pass a list of predefined global variables from .x3d Script field definitions, if found -->
                            <arg value="--predef"/>
                            <arg value="${sceneScriptFieldGlobals}"/> <!-- defined in sceneScriptFieldGlobals.properties -->
                            <arg value="@{file.path.name}"/>
                            <!-- TODO figure out how to exclude javadoc/**/*.js -->
                        </java>
                        <!-- clean up -->
                        <var    name="sceneScriptFieldGlobals" unset="true"/>
                        <!-- TODO how to silence this deletion? -->
                        <delete file="sceneScriptFieldGlobals.properties" verbose="false" quiet="true"/>
                    </then>
                </if>
            </sequential>
        </for>
        <!-- native Ant target jslint is buggy, see TODO bug report
        <jslint options="${jslint.options}">
            <formatter type="plain" destfile="jslint.out"/>
            <fileset refid="jsFiles"/>
        </jslint>
        -->
        <antcall target="echo.timestamp"/>
        <echo>processScripts.jslint complete.</echo>
    </target>

    <!-- X3dForAdvancedModeling test scenes for JSON encoding development:
    <target name="test.X3dToJson" description="test task">
        <property name="traceEnabled"  value="false"/>
        <property name="stripComments" value="false"/>
        <delete verbose="true" file="Animation/CubeWithLabeledSidesViewpointSequencer.json"/>
        <delete verbose="true" file="GeometricShapes/Dodecahedron.json"/>
        <delete verbose="true" file="GeometricShapes/StairStepPrototype.json"/>
        <delete verbose="true" file="Inspiration/ObliqueStrategies.json"/>
        <antcall target="processScenes.json"/>
    </target> -->

    <target name="processScenes.json" description="convert each .x3d scene to Javascript Object Notation .json version" depends="get.web3d.saxon,clean.RoundTrip">
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="name.short"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
                <!-- trace
                <echo></echo>
                <echo>@file.path.name       = @{file.path.name}</echo>
                <echo>$archive.path         = ${archive.path}</echo>
                <echo>$relative.path1       = ${relative.path1}</echo>
                <echo>$relative.path2       = ${relative.path2}</echo>
                <echo>$name.short           = ${name.short}</echo>
                -->
                <outofdate>
                    <sourcefiles>
                        <filelist>
                            <file name="@{file.path.name}"/>
                        </filelist>
                    </sourcefiles>
                    <mapper dir="." type="glob" from="*.x3d" to="*.json"/>
                    <sequential>
                        <!-- process individual files here.  show full path to facilitate user loading, editing of reported files -->
                        <echo>${archive.path}/${relative.path1}/${relative.path2}/${name.short}.x3d processing with X3dToJson stylesheet</echo>
                        <!-- Saxon11 is locally defined macro -->
                        <Saxon11  scene="${relative.path1}/${relative.path2}/${name.short}"
                            stylesheet="${stylesheet.dir}/X3dToJson"
                             extension="json"
                        parameterPair1="traceEnabled=${traceEnabled}"
                        parameterPair3="stripComments=${stripComments}"
                                expand="on"/>
                        <!-- expand:on since DTD defaults needed -->
                        <!-- Default options:
                        parameterPair1="traceEnabled=false"
                        parameterPair2="sceneGraphOnly=false"
                        parameterPair3="stripComments=false"
                        -->
                        <echo>${archive.path}/${relative.path1}/${relative.path2}/${name.short}.json validation checking with jslint</echo>
                        <java classname="com.googlecode.jslint4java.cli.Main" classpath="${jslint.jar}" fork="${fork}">
                            <arg value="${archive.path}/${relative.path1}/${relative.path2}/${name.short}.json"/>
                        </java>
                        <!-- native Ant target jslint is buggy, see TODO bug report
                        <jslint options="${jslint.options}">
                            <formatter type="plain" destfile="jslint.out"/>
                            <fileset   file="${archive.path}/${relative.path1}/${relative.path2}/${name.short}.json"/>
                        </jslint>
                        -->
						<echo>${archive.path}/${relative.path1}/${relative.path2}/${name.short}.json validation checking with json-schema-validator</echo>
						<echo message="... does not support latest JSON Schema, this test is not yet usable"/>
                        <!--
                        <java jar="${json-schema-validator.jar}" fork="${fork}">
							<arg value="../../../../specifications/x3d-3.3-JSONSchema.json"/>
							<arg value="${archive.path}/${relative.path1}/${relative.path2}/${name.short}.json"/>
						</java>
                        -->
						<!-- TODO also validate using JSON schema https://github.com/everit-org/json-schema -->
					</sequential>
                </outofdate>
            </sequential>
        </for>
        <antcall target="echo.timestamp"/>
        <echo>processScenes.json complete.</echo>
    </target>

    <target name="processScenes.X3dToX3dvClassicVrmlEncoding" description="convert each .x3d scene to .x3dv ClassicVrml encoding" depends="get.web3d.saxon,clean.RoundTrip">
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="name.short"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
                <!-- trace
                <echo></echo>
                <echo>@file.path.name       = @{file.path.name}</echo>
                <echo>$archive.path         = ${archive.path}</echo>
                <echo>$relative.path1       = ${relative.path1}</echo>
                <echo>$relative.path2       = ${relative.path2}</echo>
                <echo>$name.short           = ${name.short}</echo>
                -->
                <outofdate>
                    <sourcefiles>
                        <filelist>
                            <file name="@{file.path.name}"/>
                        </filelist>
                    </sourcefiles>
                    <mapper dir="." type="glob" from="*.x3d" to="*.x3dv"/>
                    <sequential>
                        <!-- process individual files here.  show full path to facilitate user loading, editing of reported files -->
                        <echo>${archive.path}/${relative.path1}/${relative.path2}/${name.short}.x3d processing with X3dToX3dvClassicVrmlEncoding stylesheet</echo>
                        <!-- Saxon11 is locally defined macro -->
                        <Saxon11  scene="${relative.path1}/${relative.path2}/${name.short}"
                            stylesheet="${stylesheet.dir}/X3dToX3dvClassicVrmlEncoding"
                             extension="x3dv"/>
                    </sequential>
                </outofdate>
            </sequential>
        </for>
        <antcall target="echo.timestamp"/>
        <echo>processScenes.X3dToX3dvClassicVrmlEncoding complete.</echo>
    </target>

    <target name="processScenes.X3dToX3dbCompressedBinaryEncoding" description="convert each .x3d scene to .x3db Compressed Binary Encoding version" depends="clean.RoundTrip">
        <!-- dependency:  see xj3d.dir etc. definitions, perform local Xj3D "build all" -->
        <echo message="processScenes.X3dToX3dbCompressedBinaryEncoding conversion depends on local Xj3D installation, current directory xj3d.dir=${xj3d.dir}"/>
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="name.short"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
                <!-- trace
                <echo></echo>
                <echo>@file.path.name       = @{file.path.name}</echo>
                <echo>$archive.path         = ${archive.path}</echo>
                <echo>$relative.path1       = ${relative.path1}</echo>
                <echo>$relative.path2       = ${relative.path2}</echo>
                <echo>$name.short           = ${name.short}</echo>
                -->
                <outofdate>
                    <sourcefiles>
                        <filelist>
                            <file name="@{file.path.name}"/>
                        </filelist>
                    </sourcefiles>
                    <mapper dir="." type="glob" from="*.x3d" to="*.x3db"/>
                    <sequential>
                        <!-- process individual files here.  show full path to facilitate user loading, editing of reported files -->
                        <echo>${archive.path}/${relative.path1}/${relative.path2}/${name.short}.x3d processing with Xj3D for .x3db binary compression</echo>
                        <java classname="xj3d.filter.CDFFilter" fork="${fork}" dir=".">
                            <classpath>
                                <pathelement path="${saxon.classpath}"/>
                                <fileset refid="xj3d.jars.all"/>
                            </classpath>
                            <arg value="Identity"/>
                            <arg value="${relative.path1}/${relative.path2}/${name.short}.x3d"/>
                            <arg value="${relative.path1}/${relative.path2}/${name.short}.x3db"/>
                        </java>
                    </sequential>
                </outofdate>
            </sequential>
        </for>
        <antcall target="echo.timestamp"/>
        <echo>processScenes.X3dToX3dbCompressedBinaryEncoding complete.</echo>
    </target>

    <target name="processScenes.touch.ViewpointImages" description="update timestamp on captured viewpoint images to avoid need to reshoot">
        <touch verbose="true"> <!-- verbose logs creation of new files -->
            <fileset dir=".">
                <include name="**/_viewpoints/${name.short}.x3d.*.png"/>
            </fileset>
        </touch>
    </target>

    <target name="processScenes.touch.X3dModels" description="update timestamp on X3D scenes to allow reshooting images and processing scenes">
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="name.short"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
                <!-- process individual files here.  show full path to facilitate user loading, editing of reported files -->
                <if>
                    <available file="${relative.path1}/${relative.path2}/${name.short}.x3d"/>
                    <then>
                        <!-- verbose logs creation of new files -->
                        <touch file="${relative.path1}/${relative.path2}/${name.short}.x3d" verbose="true"/>
                         <echo>touch ${relative.path1}/${relative.path2}/${name.short}.x3d</echo>
                    </then>
                </if>
            </sequential>
        </for>
        <!-- original was silent:
        <touch verbose="true"> 
            <fileset dir=".">
                <include name="*.x3d"/>
            </fileset>
        </touch> -->
    </target>

    <target name="processScenes.touch.htmlPrettyPrintPages" description="update timestamp on X3D documentation pages to allow reshooting images and processing scenes">
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="name.short"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
                <!-- process individual files here.  show full path to facilitate user loading, editing of reported files -->
                <if>
                    <available file="${relative.path1}/${relative.path2}/${name.short}.html"/>
                    <then>
                        <!-- verbose logs creation of new files -->
                        <touch file="${relative.path1}/${relative.path2}/${name.short}.html" verbose="true"/>
                         <echo>touch ${relative.path1}/${relative.path2}/${name.short}.html</echo>
                    </then>
                </if>
            </sequential>
        </for>        
    </target>

    <target name="processScenes.touch.conversions" description="update timestamp on converted X3D models (java json python) to allow selectively rerunning other tasks">
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="name.short"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
                <!-- process individual files here.  show full path to facilitate user loading, editing of reported files -->
                <if>
                    <available file="${relative.path1}/${relative.path2}/${name.short}.java"/>
                    <then>
                        <!-- verbose logs creation of new files -->
                        <touch file="${relative.path1}/${relative.path2}/${name.short}.java" verbose="true"/>
                         <echo>touch ${relative.path1}/${relative.path2}/${name.short}.java</echo>
                    </then>
                </if>
                <if>
                    <available file="${relative.path1}/${relative.path2}/${name.short}.json"/>
                    <then>
                        <!-- verbose logs creation of new files -->
                        <touch file="${relative.path1}/${relative.path2}/${name.short}.json" verbose="true"/>
                         <echo>touch ${relative.path1}/${relative.path2}/${name.short}.json</echo>
                    </then>
                </if>
                <if>
                    <available file="${relative.path1}/${relative.path2}/${name.short}.py"/>
                    <then>
                        <!-- verbose logs creation of new files -->
                        <touch file="${relative.path1}/${relative.path2}/${name.short}.py" verbose="true"/>
                         <echo>touch ${relative.path1}/${relative.path2}/${name.short}.py</echo>
                    </then>
                </if>
            </sequential>
        </for>        
    </target>

    <target name="processScenes.regularExpressionChecks" description="find offensive lines using regexes">
        <property name="regexNegativeLookBehinds" value="(?&lt;!address=)(?&lt;!pecification)(?&lt;!ection)(?&lt;!aragraph)(?&lt;!CosmoPlayer)(?&lt;!CAD Exchanger)"/>
		<!-- (?<!address=) is a "negative lookbehind" to filter out strings starting with address= (that appear in the same line, remainder model still gets searched OK -->
		<!-- https://stackoverflow.com/questions/977251/regular-expressions-and-negating-a-whole-character-group -->
        <!-- these regexes track common pathologies like multiple decimal points (i.e. missing whitespace), leading zeroes, etc. -->
		<property name="regexGarbledFloats" value="(\s|,|&quot;|')(((\+|-)?((\.\d+)|(\d+\.\d*))((E|e)(\+|-)?\d+)?(\.|\+|-)+(\d*))|(\d+((\+|-)\d+)+))(\s|,|&quot;|')"/>
        <property name="regexLeadingZeroes" value="(\s|,|&quot;|')(\+|-)?0\d+(\.\d*)?((E|e)(\+|-)?\d+)?(\s|,|&quot;|')"/>
        <!-- reference:  X3dValuesRegexChecker.java https://www.web3d.org/x3d/tools/canonical/src/org/web3d/x3d/tools/X3dValuesRegexChecker.java -->
        <!-- reference:  X3dToolsConstants.java     https://www.web3d.org/x3d/tools/canonical/src/org/web3d/x3d/tools/X3dToolsConstants.java -->
        <!-- reference:  X3dValuesRegexChecker.java https://www.web3d.org/x3d/tools/X3dValidator/src/java/org/web3d/x3d/tools/X3dValuesRegexChecker.java -->
        <!-- reference:  X3dToolsConstants.java     https://www.web3d.org/x3d/tools/X3dValidator/src/java/org/web3d/x3d/tools/X3dToolsConstants.java -->
        <concat>
            <!-- destfile not specified, so concat goes to console -->
            <header filtering="no" trimleading="yes">==============================================
                regex ${regexNegativeLookBehinds}${regexGarbledFloats}
                Lines that contain malformed floats:
            </header>
            <path id='x3dFiles' description="contained x3d files">
                <fileset dir=".">
                    <include name="*.x3d"/>
                    <include name="*/*.x3d"/>
                    <include name="*/*/*.x3d"/>
                    <exclude name="**/_archive/**"/>
                    <exclude name="**/_archive/*.x3d"/>
                    <exclude name="**/hide/*.x3d"/>
                    <exclude name="**/originals/*.x3d"/>
                    <exclude name="**/.svn/*.x3d"/>
                </fileset>
            </path>
            <filterchain>
                <linecontainsregexp>
                    <regexp pattern="${regexNegativeLookBehinds}${regexGarbledFloats}"/>
                </linecontainsregexp>
            </filterchain>
            <footer filtering="no" trimleading="yes">==============================================
            </footer>
        </concat>
        <concat>
            <!-- destfile not specified, so concat goes to console -->
            <header filtering="no" trimleading="yes">regex ${regexLeadingZeroes}
                Lines that contain numbers with leading zeros:
            </header>
            <path refid='x3dFiles'/>
            <filterchain>
                <linecontainsregexp>
                    <regexp pattern="${regexLeadingZeroes}"/>
                    <!-- (?&lt;!latitude)(?&lt;!longitude) -->
                </linecontainsregexp>
            </filterchain>
            <footer filtering="no" trimleading="yes">==============================================
            </footer>
        </concat>
    </target>

<!--
original .x3db converter.sh invocation Xj3D SEP 2008 release:
java  -Xmx450M -Xbootclasspath/p:./bin -Dsun.java2d.noddraw=true -Djava.library.path=./bin
-classpath .;"%Xj3D_HOME%"/apps/cadfilter/${xj3d.cadfilter.jar};"%Xj3D_HOME%"/jars/xj3d-all_2.0.0.jar xj3d.cadfilter.CDFFilter Identity %1 %2 %3 %4 %5 %6

past invocation problems and fixes documented in http://bugzilla.xj3d.org/show_bug.cgi?id=510

TODO:  fix Xj3D from launching window, instead perform offline rendering while headless to permit server operation,
       possibly by using xvfb X-windows virtual frame buffer
-->

    <target name="processScenes.captureImages"
          description="Utilize Xj3D's Replica class to create thumbnails and viewpoint images for each scene for use as icons, triggered by html timestamp, then updates html">
        <echo message="Utilize Xj3D's Replica class to create thumbnails and viewpoint images for each scene for use as icons, triggered by html timestamp, then updates html"/>
        <echo message="Optional prerequisite: processScenes.touch.X3dModels or clean.htmlPrettyPrintPages prior to reshooting all images"/>
        <echo message="Rework usually minimized by only regenerating images for each triggering .html change as needed."/>
        <echo message="processScenes.captureImages depends on local Xj3D installation available, current directory xj3d.dir=${xj3d.dir}"/>
        <echo message="   -Djava.library.path=${xj3d.dir.jars}/../${native.library.path}"/>
        <echo message="Xj3D Replica help follows..."/>
        <!-- output help for Replica at the beginning -->
        <java classname="xj3d.replica.Replica" fork="${fork}" dir=".">
            <classpath>
                <pathelement path="${saxon.classpath}"/>
                <fileset refid="xj3d.jars.all"/>
            </classpath>
            <!-- -Djava.library.path needs to point to jogl.dll driver -->
            <jvmarg value="-Djava.library.path=${xj3d.dir.jars}/../${native.library.path}"/>
            <!-- Xj3D run.args -->
            <arg value="-help"/>
        </java>
        <if>
            <not>
                <equals arg1="${jenkins.prepared}" arg2="true" />
            </not>
            <then>
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="name.short"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
                <!-- trace
                <echo></echo>
                <echo>@file.path.name       = @{file.path.name}</echo>
                <echo>$archive.path         = ${archive.path}</echo>
                <echo>$relative.path1       = ${relative.path1}</echo>
                <echo>$relative.path2       = ${relative.path2}</echo>
                <echo>$name.short           = ${name.short}</echo>
                -->
                <outofdate>
                    <sourcefiles>
                        <filelist>
                            <file name="${archive.path}/${relative.path1}/${relative.path2}/${name.short}.x3d"/>
                        </filelist>
                    </sourcefiles>
                    <!-- match pretty-print .html creation as the trigger for viewpoint capture -->
                    <mapper dir="." type="glob" from="*.x3d" to="*.html"/>
                    <!-- note:  targetfiles match with image filenames is not working, probably due to * wildcard.
                         also note that viewpoint image names are multiple, and each are variations on the original filename.
                         attempted invocations follow.
                    <targetfiles>
                        <pathelement path="${archive.path}/${relative.path1}/${relative.path2}/_viewpoints/${name.short}.x3d.*.png"/>
                    </targetfiles>
                    or
                    <mapper dir="." type="glob" from="*.x3d" to="_viewpoints/*.png"/>
                    -->
                    <sequential>
                        <!-- process individual files here.  show full path to facilitate user loading, editing of reported files -->
                        <echo>============================================================================================================ </echo>
                        <echo>Xj3D Replica model loading and generation of Thumbnail (icon) image:</echo>
                        <echo>${archive.path}/${relative.path1}/${relative.path2}/${name.short}.x3d</echo>
                        <var name="outfilePath" value="${relative.path1}/${relative.path2}/_thumbnails/${name.short}Thumbnail.png"/>
                        <echo>${archive.path}/${outfilePath}</echo>
                        <mkdir                    dir="${relative.path1}/${relative.path2}/_thumbnails"/>
                        <!-- copy default thumbnail image as destination file to indicate if failure occurs and avoid repeated hangups -->
                        <copy file="../images/Xj3dRenderCaptureFailed.png" tofile="${outfilePath}" overwrite="true" verbose="false"/>

                        <java classname="xj3d.replica.Replica" fork="${fork}" dir="." failonerror="false">
                            <classpath>
                                <pathelement path="${saxon.classpath}"/>
                                <fileset refid="xj3d.jars.all"/>
                            </classpath>
                            <!-- -Djava.library.path needs to point to jogl.dll driver -->
                            <jvmarg value="-Djava.library.path=${xj3d.dir.jars}/../${native.library.path}"/>
                            <!-- Replica run.args -->
                            <arg value="-mode"/><arg value="thumbnail"/>
                            <arg value="-mipmaps"/>
                            <arg value="-antialias"/><arg value="8"/>
                            <arg value="-anisotropicDegree"/><arg value="16"/>
                            <arg value="-quiet"/> <!-- -verbose or -quiet -->
                            <arg value="-size"/><arg value="128x128"/>
                            <arg value="-view"/><arg value="AUTO"/> <!-- Fit to world -->
                            <arg value="-outfile"/><arg value="${outfilePath}"/> <!-- output directory and file name -->
                            <arg value="-threepointlight"/>
                            <arg value="-timeout"/><arg value="10000"/><!-- ms -->
                            <arg value="--illegal-access=warn"/><!-- enable warnings of further illegal reflective access operations -->
                            <arg value="${relative.path1}/${relative.path2}/${name.short}.x3d"/> <!-- sceneFile -->
                        </java>
                        <!-- process individual files here.  show full path to facilitate user loading, editing of reported files -->
                        <echo>- - - - - - - - - - - - - - - - - - - -</echo>
                        <echo>Xj3D Replica model loading and generation of Viewpoint images:</echo>
                        <echo>${archive.path}/${relative.path1}/${relative.path2}/${name.short}.x3d</echo>
                        <echo>${archive.path}/${relative.path1}/${relative.path2}/_viewpoints/ holds viewpoint images</echo>
                        <mkdir dir="${relative.path1}/${relative.path2}/_viewpoints"/>

                        <!-- see Xj3D/nbprojects/ide-file-targets.xml for example:

                            <java classname="${replica}" dir="${replica.dir}" fork="false">
                                <classpath refid="app.classpath"/>
                                <jvmarg line="${run.args}"/>
                                <arg line="${app.replica.args} ${scene.name} -outdir '${basedir}/${test.products.dir}' '${scene.path}'"/>
                            </java>
                        -->
                        <java classname="xj3d.replica.Replica" fork="${fork}" dir="." failonerror="false">
                            <classpath>
                                <pathelement path="${saxon.classpath}"/>
                                <fileset refid="xj3d.jars.all"/>
                            </classpath>
                            <!-- -Djava.library.path needs to point to jogl.dll driver -->
                            <jvmarg value="-Djava.library.path=${xj3d.dir.jars}/../${native.library.path}"/>
                            <!-- Xj3D run.args -->
                            <arg value="-mode"/><arg value="viewpoints"/>
                            <arg value="-mipmaps"/>
                            <arg value="-antialias"/><arg value="8"/>
                            <arg value="-anisotropicDegree"/><arg value="16"/>
                            <arg value="-quiet"/> <!-- -verbose or -quiet -->
                            <arg value="-stats"/>
                            <arg value="-size"/><arg value="792x465"/>
                            <arg value="-timeout"/><arg value="10000"/><!-- ms -->
                            <arg value="--illegal-access=warn"/><!-- enable warnings of further illegal reflective access operations -->
                       <!-- <arg value="-view"/><arg value="ICON_VIEWPOINT"/> -->
                            <arg value="-filePrefix"/><arg value="${name.short}"/>
                            <arg value="-outdir"/><arg value="${relative.path1}/${relative.path2}/_viewpoints"/> <!-- output directory -->
                            <arg value="${relative.path1}/${relative.path2}/${name.short}.x3d"/>
                        </java>

<!-- reference for Xj3D screenshot from Xj3D NPS branch build.xml and build.properties invocations:

# mode can be thumbnail=ThumbnailImager, scene=SceneThumbnailImager, or sequence=SceneRecorder.
app.replica.args=-mode scene -mipmaps -antialias 8 -anisotropicDegree 16 -verbose -stats -size 256x256 -filePrefix

    <target name="run.replica"
            depends="init"
            if="replica.class.present"
            description="Run the Xj3D Replica App">

        <echo></echo>
        <echo>Processing ${scene}</echo>
        <echo></echo>

        <java classname="${replica}" dir="${replica.dir}" fork="false">
            <classpath refid="app.classpath"/>
            <jvmarg line="${run.args}"/>

            <arg line="${app.replica.args} testCapture ${scene}"/>
        </java>
        <echo message="Look in ${replica.dir}/output for result"/>
    </target>
-->

                        <!-- now that images are collected, restore file/timestamp by regenerating html -->
                        <!-- X3dToXhtml.xslt process individual files here. show full path to facilitate user loading, editing of reported files -->
                        <echo>${archive.path}/${relative.path1}/${relative.path2}/${name.short}.x3d processing with X3dToXhtml stylesheet pretty-print .html</echo>
                        <!-- Saxon11 is locally defined macro -->
                        <Saxon11  scene="${relative.path1}/${relative.path2}/${name.short}"
                            stylesheet="${stylesheet.dir}/X3dToXhtml"
                             extension="html"
                        parameterPair1="linkImages=true"/>
                    </sequential>
                </outofdate>
            </sequential>
        </for>
            </then>
            <else>
                <echo message="No viewpoint capture when run on jenkins server"/>
            </else>
        </if>
        
        <antcall target="echo.timestamp"/>
        <echo>processScenes.captureImages complete, htmlPrettyPrintDocumentation updated.</echo>
    </target>

    <target name="canonicalScenesX3dToXml" description="save each canonicalized filename.x3d as filenameCanonical.xml">
        <for param="filenames">
            <path>
                <fileset dir="." includes="**/*Canonical.x3d"/>
            </path>
            <sequential>
                <propertyregex
                    property="filename.prefix"
                    override="true"
                    input="@{filenames}"
                    regexp="([^\\]*\\){6}([^\n]*)Canonical\.x3d"
                    select="\2"/>
                <echo>Moving ${filename.prefix}Canonical.x3d to ${filename.prefix}Canonical.xml</echo>
                <move file="${filename.prefix}Canonical.x3d" tofile="${filename.prefix}Canonical.xml"/>
            </sequential>
        </for>
        <antcall target="echo.timestamp"/>
        <echo>canonicalScenesX3dToXml complete.</echo>
    </target>

    <target name="processScenes.canonicalX3D" description="generate canonical X3D form" depends="clean.duplicates">
        <!-- TODO:  XMLUnit test comparing Filename.x3d to FilenameCanonical.xml -->
        <echo message="Verifying Apache Ant XML Catalog resolver classpath: ${resolver.dir}/${resolver.jar} (${resolver.jar.length} bytes)"/>
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="name.short"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
                <!-- trace
                <echo></echo>
                <echo>@file.path.name       = @{file.path.name}</echo>
                <echo>$archive.path         = ${archive.path}</echo>
                <echo>$relative.path1       = ${relative.path1}</echo>
                <echo>$relative.path2       = ${relative.path2}</echo>
                <echo>$name.short           = ${name.short}</echo>
                -->
                <outofdate>
                    <sourcefiles>
                        <filelist>
                            <file name="@{file.path.name}"/>
                        </filelist>
                    </sourcefiles>
                    <mapper dir="." type="glob" from="*.x3d" to="*Canonical.xml"/>
                    <sequential>
                        <copy file="@{file.path.name}" toFile="${relative.path1}/${relative.path2}/${name.short}Canonical.xml"/> <!-- verbose="true" -->
                        <!-- process individual files here.  show full path to facilitate user loading, editing of reported files. -->
                        <echo>@{file.path.name} processed by org.web3d.x3d.tools.x3db.X3dCanonicalizer:</echo>
                        <!-- canonicalX3D is locally defined macro -->
                        <canonicalX3D scene="${relative.path1}/${relative.path2}/${name.short}"/>
                        <!-- check XML header and DOCTYPE -->
                        <echo message="X3dDoctypeChecker ${relative.path1}/${relative.path2}/${name.short}.x3d"/>
                        <java classname="org.web3d.x3d.tools.X3dDoctypeChecker" classpath="${c14n.dir}/${c14n.jar}" failonerror="false">
                            <arg value="${relative.path1}/${relative.path2}/${name.short}.x3d"/>
                            <!-- <arg value="-verbose"/> -->
                        </java>
                    </sequential>
                </outofdate>
            </sequential>
        </for>
        <antcall target="echo.timestamp"/>
        <echo>processScenes.canonicalX3D complete.</echo>
    </target>

    <target name="X3dToXhtml.xsltNative" description="pretty print all .x3d examples as .html">
        <xslt destdir="." style="${stylesheet.dir}/X3dToXhtml.xslt" force="true">
            <include name="*/*/*.x3d"/>
            <mapper type="glob" from="*.x3d" to="*.html"/>
            <xmlcatalog refid="X3dCatalog"/>
            <!-- TODO get xmlcatalog working under jenkins
            <attribute name="http://xml.org/sax/features/validation" value="true"/>
            <attribute name="http://xml.org/sax/features/namespaces" value="true"/>
            -->
        </xslt>
        <antcall target="echo.timestamp"/>
    </target>

    <!-- warning:  xalan crashes Netbeans 5.0 completely without leaving a trace -->
    <target name="X3dToVrml97.xsltNative" description="convert all .x3d examples to .wrl">
        <xslt destdir="." style="${stylesheet.dir}/X3dToVrml97.xslt" force="true">
            <include name="*/*/*.x3d"/>
            <mapper type="glob" from="*.x3d" to="*.wrl"/>
            <xmlcatalog refid="X3dCatalog"/>
            <!-- TODO get xmlcatalog working under jenkins
            <attribute name="http://xml.org/sax/features/validation" value="true"/>
            <attribute name="http://xml.org/sax/features/namespaces" value="true"/>
            -->
        </xslt>
        <antcall target="echo.timestamp"/>
    </target>

    <!-- Xalan throws exception but then continues to completion:
         java.lang.ClassCastException: com.sun.org.apache.xalan.internal.xsltc.compiler.Variable  -->
    <target name="X3dToX3dvClassicVrmlEncoding.xsltNative" description="convert all .x3d examples to .x3dv">
        <xslt destdir="." style="${stylesheet.dir}/X3dToX3dvClassicVrmlEncoding.xslt" force="true">
            <classpath path="${cp}"/>
            <include name="*/*/*.x3d"/>
            <mapper type="glob" from="*.x3d" to="*.x3dv"/>
            <xmlcatalog refid="X3dCatalog"/>
            <!-- TODO get xmlcatalog working under jenkins
            <attribute name="http://xml.org/sax/features/validation" value="true"/>
            <attribute name="http://xml.org/sax/features/namespaces" value="true"/>
            -->
        </xslt>
        <antcall target="echo.timestamp"/>
    </target>

    <path id="project-classpath">
        <pathelement location="."/>
        <pathelement location="lib/CreateContentCatalog.jar"/>
        <pathelement location="${log4j.dir}/${log4j-api.jar}"/>
        <pathelement location="${log4j.dir}/${log4j-core.jar}"/>
        <!-- ensure system JAVA_HOME points to JDK -->
        <pathelement location="${java.home}/lib/rt.jar"/>
        <!--
            <fileset dir="${env.JWSDP_HOME}/jaxp/lib" includes="*.jar"/>
            <pathelement location="${jaxp.apis}/jaxp-api.jar"/>
            <pathelement location="${jaxp.lib}/sax.jar"/>
            <pathelement location="${jaxp.lib}/dom.jar"/>
            <pathelement location="${jaxp.lib}/xercesImpl.jar"/>
            <pathelement location="${jaxp.lib}/xalan.jar"/>
            <pathelement location="${samples.build.dir}/"/>
            -->
    </path>

    <target name="catalog"
            depends="catalog.builder,catalog.generateHtmlPages,catalog.generateXMLSpyProject,catalog.validate"
            description="generate catalog, XMLSPY project and HTML pages">
        <antcall target="echo.timestamp"/>
    </target>

    <target name="catalog.builder" depends="clean.duplicates"
     description="generate catalog XML holding archive information by reading directories and X3D files">
        <!-- TODO: modify filenames by adding timestamp -->
        <copy todir="_archive" verbose="true" failonerror="false">
            <fileset dir=".." includes="ContentCatalog${archive.name}.xml,ContentCatalogExamples${archive.name}.spp"/>
        </copy>
        <!-- Will be overridden if called from catalog.server or jenkins -->
        <property name="catalog.local.dtd" value="-localDTD"/> <!-- -localDTD or -onlineDTD for scene validation -->
        <echo  message="catalog.builder: catalog.local.dtd=${catalog.local.dtd}, passed archive.name=../${archive.name}, CreateContentCatalog.dir=${CreateContentCatalog.dir}"/>
        <echo  message="$log4j.dir=${log4j.dir} $log4j-api.jar=${log4j-api.jar} $log4j-core.jar=${log4j-core.jar}"/>
        <java classname="ContentCatalogBuilder" fork="no" failonerror="false">
            <classpath refid="project-classpath"/>
            <jvmarg value="-DentityExpansionLimit=4000000"/>
            <arg value="${catalog.local.dtd}"/>
            <arg value="../${archive.name}"/>
            <arg value="${CreateContentCatalog.dir}"/>
        </java>
        <echo  message="if a package.html chapter summary is not appearing in chapter.html output, check filters in"/>
        <echo  message="   tools/CreateContentCatalog/CreateContentCatalogPages.xslt ChapterPackageDescription"/>
        <echo  message="catalog creation complete, if successful then rename result to include archive name:"/>
        <move file="ContentCatalog.xml" tofile="ContentCatalog${archive.name}.xml" overwrite="true" failonerror="false" verbose="true"/>
    </target>

    <target name="catalog.validate" description="validate catalog" unless="jenkins.prepared">
        <echo message="check well-formedness and validate ContentCatalog${archive.name}.xml"/>
        <xmlvalidate file="ContentCatalog${archive.name}.xml" failonerror="false" warn="true"/>
        <xmlvalidate file="ContentCatalog${archive.name}.xml" failonerror="true"  warn="true" lenient="true"/>
    </target>

    <target name="catalog.generateHtmlPages" description="generate HTML pages for entire catalog" depends="get.web3d.saxon">
        <echo message="local.dir=${local.dir}"/>
        <echo message="check well-formedness ${CreateContentCatalog.dir}/CreateContentCatalogPages.xslt"/>
        <xmlvalidate file="${CreateContentCatalog.dir}/CreateContentCatalogPages.xslt" failonerror="true" warn="true" lenient="true"/>

        <echo message="generate complete set of HTML pages for ${archive.name} examples archive"/>
        <!-- cd    ../examples/; pwd; $(SAXON) -t ContentCatalog.xml $(CONTENT_DRIVE)/$(CONTENT_DIR)/../tools/CreateContentCatalog/CreateContentCatalogPages.xslt -->
        <!-- TODO: Xj3D -captureViewpoint option, selectively adding corresponding links in output HTML -->
        <property name="reduceArchiveSize" value="false"/>
        <echo message="attempted to set immutable property to false:  reduceArchiveSize=${reduceArchiveSize}"/>
        <java classname="net.sf.saxon.Transform" classpath="${saxon.classpath}" fork="false" failonerror="false">
            <arg value="-dtd:off"/> <!-- TODO problem with different relative directories while invoking under jenkins -->
            <arg value="-warnings:recover"/> <!-- recover after writing a warning message -->
            <!-- <arg value="-t"/> saxon version and timing information -->
            <arg value="-s:ContentCatalog${archive.name}.xml"/>
            <arg value="-xsl:${CreateContentCatalog.dir}/CreateContentCatalogPages.xslt"/>
            <!-- passed parameters, can also be locally set value in CatalogManager.properties -->
            <arg value="reduceArchiveSize=${reduceArchiveSize}"/>
            <arg value="jenkins=${jenkins.prepared}"/>
            <arg value="localDirectory=${archive.path}"/>
        </java>
        <!-- clean up erroneously created namespace artifacts -->
        <replace dir="." token=' xmlns=""' value="">
            <include name="**/*.html"/>
            <include name="**/*.xhtml"/>
        </replace>
        <echo message="Local example archive HTML pages available via file:///${archive.path}/index.html"/>
    </target>

    <!-- Warning:  the next two tasks are only used on subversion servers.  Do not use locally. -->
    <target name="catalog.retrieve.CreateContentCatalog.jar"
             description="retrieve CreateContentCatalog.jar from SourceForge subversion to support local build">
        <get src="${x3d.sourceforge.site}/x3d/tools/CreateContentCatalog/CreateContentCatalog.jar"
            dest="lib/CreateContentCatalog.jar" ignoreerrors="${ignoreSetupDownloadErrors}"/>
    <!--<copy toDir="${basedir}"
              file="${CreateContentCatalog.dir}/CreateContentCatalog.jar"/>-->
    </target>

    <target name="catalog.server"
            depends="catalog.retrieve.CreateContentCatalog.jar"
            description="utility task for subversion server-side regeneration of content catalog">
       <antcall target="catalog.builder" inheritAll="true">
           <param name="catalog.local.dtd" value=""/>
       </antcall>
    </target>

    <target name="catalog.generateXMLSpyProject" description="generate XMLSPY catalog">
        <echo message="check well-formedness ${CreateContentCatalog.dir}/ContentCatalogToXmlSpyProject.xslt"/>
        <xmlvalidate file="${CreateContentCatalog.dir}/ContentCatalogToXmlSpyProject.xslt" failonerror="true" warn="true" lenient="true"/>
        <echo message="generate XML Spy catalog ContentCatalog${archive.name}.spp"/>
        <xslt   in="ContentCatalog${archive.name}.xml"
                out="ContentCatalog${archive.name}.spp"
                style="${CreateContentCatalog.dir}/ContentCatalogToXmlSpyProject.xslt"
                reloadstylesheet="yes" force="yes">
            <classpath path="${cp}"/>
        </xslt>
        <echo message="validate ContentCatalog${archive.name}.spp"/>
        <xmlvalidate file="ContentCatalog${archive.name}.spp" failonerror="false" warn="true" lenient="true"/>
    </target>

    <target name="zip.reduced" description="generate .zip distribution, reduced size by omitting .x3dv and C14N .xml versions">
        <property name="reduceArchiveSize" value="true"/>
        <echo message="attempted to set immutable property to true:  reduceArchiveSize=${reduceArchiveSize}"/>
        <antcall target="catalog.generateHtmlPages"/>
        <antcall target="zip"/>
    </target>

    <property name="zipFileName" value="../X3dExamples${archive.name}.zip"/>
        
    <target name="zip.checksum" description="generate .zip checksum">
        <checksum file="${zipFileName}"/>
        <checksum file="${zipFileName}" property="zip.checksum"/>
    <!--<echo  message="zip.checksum="/> property value should match file -->
        <echo  message="${zipFileName}.MD5 checksum:"/> 
        <concat>
            <fileset file="${zipFileName}.MD5"/>
        </concat>
    </target>

    <target name="zip" depends="clean.backups,clean.duplicates,clean.RoundTrip,clean.X3dTidy,commonSetup" description="generate .zip distribution">
        <echo>Building ${zipFileName} distribution</echo>
        <!-- TODO:  figure out
        <if>
            <equals arg1="${archive.name}" arg2="Savage">
                <move file="Documents and Settings/All Users/Start Menu/Programs/X3D Extensible 3D Graphics/Savage Modeling Analysis Language (SMAL) metadata.lnk"/>
                <echo message="SavageLinks found"/>
            </equals>
        </if>
        -->
        <zip destfile="${zipFileName}">
            <zipfileset dir="." prefix="">
                <include name="README.txt"/>
            </zipfileset>
            <zipfileset dir="../../.." prefix="www.web3d.org">
                <include name="../README.txt"/>
            </zipfileset>
            <zipfileset dir="../.." prefix="www.web3d.org/x3d/content/">
                <include name="icons/*.*"/>
                <include name="images/x3d2-s.gif"/>
                <include name="images/web3d_logo2.png"/>
                <include name="${CreateContentCatalog.dir}/ContentCatalog.dtd"/>
                <exclude name="**/*.nrrd"/>
                <exclude name="CVS/*"/>
                <exclude name=".svn/*"/>
                <exclude name="_new*.*"/>
                <exclude name="*.bak"/>
                <exclude name="Thumbs.db"/>
                <exclude name="**/access.properties"/>
                <exclude name="*.$$$$$$"/>
                <exclude name="**/*.$$$$$$"/><!-- escape $ as $$ -->
                <!-- TODO:  debug _archive filters -->
                <exclude name="_archive/*"/>
                <exclude name="**/_archive"/>
                <exclude name="**/_archive/*"/>
                <exclude name="_schematron"/>
                <exclude name="**/_schematron"/>
                <exclude name="**/_schematron/*"/>
                <exclude name="hide"/>
                <exclude name="**/hide"/>
                <exclude name="**/hide/*"/>
                <exclude name="jenkins"/>
                <exclude name="nbproject/*"/>
                <exclude name="**/nbproject/*"/>
                <exclude name="**/CVS/*"/>
                <exclude name="**/.svn/*"/>
                <exclude name="**/_new*.*"/>
                <exclude name="**/*.bak"/>
                <exclude name="**/Thumbs.db"/>
            </zipfileset>
            <zipfileset dir="../../../../.." prefix="">
                <include name="index${archive.name}.localRedirect.html"/>
            </zipfileset>
            <zipfileset dir=".." prefix="www.web3d.org/x3d/content/examples/">
                <include name="images/*.*"/>
                <include name="*.xml"/>
                <include name="Makefile"/>
                <include name="*.html"/>
                <include name="license.*"/>
                <include name="Hello*.*"/>
                <include name="earth-topo*.*"/>
                <include name="newScene.*"/>
                <include name="newHtmlPageWithX3dObject.html"/>
                <include name="newEcmascript.js"/>
                <include name="newX3dScript.java"/>
                <include name="*.x3d"/>
                <include name="*.xml"/>
                <include name="*.html"/>
                <include name="*.wrl"/>
                <include name="*.x3dv"/>
                <include name="*.json"/>
                <include name="*.java"/>
                <include name="*.gif"/>
                <include name="*.jpg"/>
                <include name="*.png"/>
                <include name="*.txt"/>
                <include name="*.pdf"/>
                <include name="*.ppt"/>
                <include name="_svg/*.svg"/>
                <exclude name="index*Redirect.html"/>
                <exclude name="**/access.properties"/>
                <exclude name="**/*.nrrd"/>
                <exclude name="CVS/*"/>
                <exclude name=".svn/*"/>
                <exclude name="_new*.*"/>
                <exclude name="*.bak"/>
                <exclude name="Thumbs.db"/>
                <exclude name="*.$$$$$$"/>
                <exclude name="**/*.$$$$$$"/><!-- escape $ as $$ -->
                <exclude name="_archive/*"/>
                <exclude name="**/_archive"/>
                <exclude name="**/_archive/*"/>
                <exclude name="_schematron"/>
                <exclude name="**/_schematron"/>
                <exclude name="**/_schematron/*"/>
                <exclude name="hide"/>
                <exclude name="**/hide"/>
                <exclude name="**/hide/*"/>
                <exclude name="jenkins"/>
                <exclude name="nbproject/*"/>
                <exclude name="**/nbproject/*"/>
                <exclude name="**/CVS/*"/>
                <exclude name="**/.svn/*"/>
                <exclude name="**/_new*.*"/>
                <exclude name="**/*.bak"/>
                <exclude name="**/Thumbs.db"/>
            </zipfileset>
            <!-- windows shortcuts for this archive, no longer included
            <zipfileset dir="../../../../..">
                <include name="Documents and Settings/All Users/Start Menu/Programs/X3D Extensible 3D Graphics/X3D Examples/${archive.name} examples.lnk"/>
                <include name="WINDOWS/Start Menu/Programs/X3D Extensible 3D Graphics/X3D Examples/${archive.name} examples.lnk"/>
                <include name="WINDOWS/Profiles/All Users/Start Menu/Programs/X3D Extensible 3D Graphics/X3D Examples/${archive.name} examples.lnk"/>
                <include name="WINNT/Profiles/All Users/Start Menu/Programs/X3D Extensible 3D Graphics/X3D Examples/${archive.name} examples.lnk"/>
            </zipfileset>
            -->
            <zipfileset dir="." prefix="www.web3d.org/x3d/content/examples/${archive.name}/">
                <include name="*.xml"/>
                <include name="*.spp"/>
                <include name="Makefile"/>
                <include name="*.html"/>
                <include name="license.*"/>
                <include name="Hello*.*"/>
                <include name="earth-topo*.*"/>
                <include name="newScene.*"/>
                <include name="README.txt"/>
                <include name="**/*"/> <!-- all subdirectories -->
                <!-- intermediate directories on 2-level archives hold nothing but directories, no files to match -->
                <include          name="*.x3d"/>
                <include name="*/*/*.x3d"/> <!-- ${numberOfSections} level down only -->
                <include          name="*.js"/>
                <include name="*/*/*.js"/> <!-- ${numberOfSections} level down only -->
                <include          name="*.xml"/>
                <include name="*/*/*.xml"/> <!-- ${numberOfSections} level down only -->
                <include          name="*.dtd"/>
                <include name="*/*/*.dtd"/> <!-- ${numberOfSections} level down only -->
                <include          name="*.xsd"/>
                <include name="*/*/*.xsd"/> <!-- ${numberOfSections} level down only -->
                <include          name="*.html"/>
                <include name="*/*/*.html"/> <!-- ${numberOfSections} level down only -->
                <include          name="*.wrl"/>
                <include name="*/*/*.wrl"/> <!-- ${numberOfSections} level down only -->
                <include          name="*.x3dv"/>
                <include name="*/*/*.x3dv"/> <!-- ${numberOfSections} level down only -->
                <include          name="*.gif"/>
                <include name="*/*/*.gif"/> <!-- ${numberOfSections} level down only -->
                <include          name="*.jpg"/>
                <include name="*/*/*.jpg"/> <!-- ${numberOfSections} level down only -->
                <include          name="*.png"/>
                <include name="*/*/*.png"/> <!-- ${numberOfSections} level down only -->
                <include          name="*.txt"/>
                <include name="*/*/*.txt"/> <!-- ${numberOfSections} level down only -->
                <include          name="*.pdf"/>
                <include name="*/*/*.pdf"/> <!-- ${numberOfSections} level down only -->
                <include          name="*.ppt"/>
                <include name="*/*/*.ppt"/> <!-- ${numberOfSections} level down only -->
                <include          name="*.mpg"/>
                <include name="*/*/*.mpg"/> <!-- ${numberOfSections} level down only -->
                <include          name="*.mpeg"/>
                <include name="*/*/*.mpeg"/><!-- ${numberOfSections} level down only -->
                <include          name="*.xls"/>
                <include name="*/*/*.xls"/><!-- ${numberOfSections} level down only -->
                <include          name="*.wmv"/>
                <include name="*/*/*.wmv"/> <!-- ${numberOfSections} level down only -->
                <include          name="*.au"/>
                <include name="*/*/*.au"/>  <!-- ${numberOfSections} level down only -->
                <!-- autogenerated html-catalog content -->
                <include     name="_svg/*.svg"/>
                <include   name="*/_svg/*.svg"/>
                <include name="*/*/_svg/*.svg"/>
                <exclude name="**/*.nrrd"/>
                <exclude name="**/access.properties"/>
                <exclude name="_new*.*"/>
                <exclude name="*.bak"/>
                <exclude name="Thumbs.db"/>
                <exclude name="*.$$$$$$"/>
                <exclude name="**/*.$$$$$$"/><!-- escape $ as $$ -->
                <exclude name="_archive/*"/>
                <exclude name="**/_archive"/>
                <exclude name="**/_archive/*"/>
                <exclude name="_schematron"/>
                <exclude name="**/_schematron"/>
                <exclude name="**/_schematron/*"/>
                <exclude name="hide"/>
                <exclude name="**/hide"/>
                <exclude name="**/hide/*"/>
                <exclude name="jenkins"/>
                <exclude name="nbproject/*"/>
                <exclude name="**/nbproject/*"/>
                <exclude name="CVS/*"/>
                <exclude name="**/CVS/*"/>
                <exclude name=".svn/*"/>
                <exclude name="**/.svn/*"/>
                <exclude name="**/_new*.*"/>
                <exclude name="**/*.bak"/>
                <exclude name="**/Thumbs.db"/>
                <!-- other archive-unique excludes -->
                <!-- Savage archive -->
                <exclude name="SoundEffects/**/*.*"/>
                <!-- X3dForAdvancedModeling archive -->
                <exclude name="SanCarlosCathedral/photographs/"/>
            </zipfileset>
        </zip>
        <antcall target="zip.checksum"/>
        <length property="archive.zip.length" file="${zipFileName}"/>
        <echo>Building ${zipFileName} (${archive.zip.length} bytes) complete</echo>
    </target>

    <target name="view.javadoc.local" description="view local package javadoc in web browser (Netbeans only)">
        <nbbrowse file="javadoc/index.html" />
        <!-- TODO implementation-independent approach if possible, but note that other Ant approaches usually have to be customized for each OS. -->
    </target>

    <target name="view.javadoc.online" description="view local package javadoc in web browser (Netbeans only)">
        <echo message="${archive.site}/${archive.name}/javadoc" />
        <nbbrowse url="${archive.site}/${archive.name}/javadoc" /> <!-- do not follow with /index.html -->
        <!-- TODO implementation-independent approach if possible, but note that other Ant approaches usually have to be customized for each OS. -->
    </target>

    <target name="view.examples.local" description="view local examples in web browser (Netbeans only)">
        <nbbrowse file="index.html" />
        <!-- TODO implementation-independent approach if possible, but note that other Ant approaches usually have to be customized for each OS. -->
    </target>

    <target name="view.examples.online" description="view online examples in web browser (Netbeans only)">
        <echo message="${archive.site}/${archive.name}" />
        <nbbrowse url="${archive.site}/${archive.name}" />
        <!-- TODO implementation-independent approach if possible, but note that other Ant approaches usually have to be customized for each OS. -->
    </target>

    <target  name="clean.X3dTidy">
        <echo message="ensuring any prior intermediate X3dTidy results are cleaned out..."/>
        <delete verbose="true">
            <fileset dir=".">
                <include name="**/*Tidy.*"/>
                <include name="**/*TidyCanonical.xml"/>
                <!-- no need to keep TIdy examples in archive -->
                <include name="**/_archive/*Tidy.*"/>
                <include name="**/_archive/*TidyCanonical.xml"/>
                <exclude name="**/build.*Tidy*.log"/>
                <exclude name="**/build.*Tidy*.txt"/>
            </fileset>
        </delete>
    </target>

    <target name="processScenes.X3dTidy.all" description="Apply X3dTidy.xslt to clean up X3D scene problems (when .x3d is more recent than .html)"
         depends="clean.X3dTidy,clean.duplicates,processScenes.touch.X3dModels,processScenes.X3dTidy"/>

    <target name="processScenes.X3dTidy" description="Apply X3dTidy.xslt to clean up X3D scene errors (when .x3d is more recent than .html)" depends="clean.X3dTidy,clean.duplicates">
        <echo message="Apply X3dTidy.xslt to clean up X3D scene errors (when .x3d is more recent than .html)"/>
        <echo message="Verifying Apache Ant XML Catalog resolver classpath: ${resolver.dir}/${resolver.jar} (${resolver.jar.length} bytes)"/>
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="name.short"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
                <!-- trace
                <echo></echo>
                <echo>@file.path.name       = @{file.path.name}</echo>
                <echo>$archive.path         = ${archive.path}</echo>
                <echo>$relative.path1       = ${relative.path1}</echo>
                <echo>$relative.path2       = ${relative.path2}</echo>
                <echo>$name.short           = ${name.short}</echo>
                -->
                <outofdate>
                    <sourcefiles>
                        <filelist>
                            <file name="@{file.path.name}"/>
                        </filelist>
                    </sourcefiles>
                    <mapper dir="." type="glob" from="*.x3d" to="*.html"/>
                    <sequential>
                        <echo>==================================================</echo>
                        <echo message="@{file.path.name} "/>
                        <echo message="check well-formedness of original model..."/>
                        <xmlvalidate file="@{file.path.name}" failonerror="false" warn="true" lenient="true"/>
                        <echo message="check DTD validation  of original model..."/>
                        <xmlvalidate file="@{file.path.name}" failonerror="false" warn="true">
                            <xmlcatalog refid="X3dCatalog"/>
                        </xmlvalidate>
                        <echo message="check schema validation of original model..."/>
                        <schemavalidate file="@{file.path.name}" failonerror="false" fullchecking="false" lenient="false" warn="true">
                            <xmlcatalog refid="X3dCatalog"/>
                        </schemavalidate>
                        <echo message="check schematron validation of original model..."/>
                        <!-- process individual files here.  show full path to facilitate user loading, editing of reported files -->
                        <mkdir dir="${archive.path}/${relative.path1}/${relative.path2}/_schematron"/>
                        <echo>@{file.path.name} validation using X3D Schematron rules</echo>
                        <java classname="net.sf.saxon.Transform" classpath="${saxon.classpath}" fork="false">
                            <arg value="-warnings:recover"/>
                            <arg value="-s:@{file.path.name}"/>
                            <arg value="-o:${relative.path1}/${relative.path2}/_schematron/${name.short}.svrl"/> <!-- ${archive.path}/ -->
                            <arg value="-xsl:${X3dSchematronValidityChecks.dir}/${X3dSchematronValidityChecks}.xslt"/>
                        </java>
                        <java classname="net.sf.saxon.Transform" classpath="${saxon.classpath}" fork="false">
                            <arg value="-warnings:recover"/>
                            <arg value="-s:${relative.path1}/${relative.path2}/_schematron/${name.short}.svrl"/>
                            <arg value="-o:${relative.path1}/${relative.path2}/_schematron/${name.short}.svrl.txt"/> <!-- ${archive.path}/ -->
                            <arg value="-xsl:${X3dSchematronValidityChecks.dir}/${SvrlReportText}.xslt"/>
                        </java>
                        <concat>
                            <filelist dir="." files="${relative.path1}/${relative.path2}/_schematron/${name.short}.svrl.txt"/>
                        </concat>
                        <echo message="next check X3dTidy..."/>
                        <if>
                            <or>
                                <equals arg1="${name.short}" arg2="QuadTreeExamples"></equals>
                                <equals arg1="${name.short}" arg2="SceneNodePrototype"></equals>
                                <equals arg1="${name.short}" arg2="SpinGroupInternalSubsetDeclaration"></equals>
                                <equals arg1="${name.short}" arg2="TestRegularExpressionChecks"></equals>
                                <equals arg1="${name.short}" arg2="TestSchematronDiagnostics"></equals>
                                <equals arg1="${name.short}" arg2="X3DRetreatProtoExercise"></equals>
                            </or>
                            <then>
                                <!-- avoid modifying scenes with intentional errors -->
                                <echo>${archive.path}/${relative.path1}/${relative.path2}/${name.short}.x3d processing with X3dTidy.xslt stylesheet ignored for scene with intentional errors</echo>
                            </then>
                            <else>
                                <!-- process individual files here. show full path to facilitate user loading, editing of reported files -->
                                <echo>${archive.path}/${relative.path1}/${relative.path2}/${name.short}.x3d processing with X3dTidy.xslt stylesheet for tidied-up .x3d</echo>
                                <!-- X3dTidy is locally defined macro -->
                                <X3dTidy scene="${relative.path1}/${relative.path2}/${name.short}" title="${name.short}"/>
                            </else>
                        </if>
                        <echo message="check well-formedness of X3dTidy form:"/>
                        <xmlvalidate file="${relative.path1}/${relative.path2}/${name.short}.x3d" failonerror="false" warn="true" lenient="true"/>
                        <echo message="check DTD validation  of X3dTidy form"/>
                        <xmlvalidate file="${relative.path1}/${relative.path2}/${name.short}.x3d" failonerror="false" warn="true">
                            <xmlcatalog refid="X3dCatalog"/>
                        </xmlvalidate>
                        <echo message="check schema validation of X3dTidy form"/>
                        <schemavalidate file="${relative.path1}/${relative.path2}/${name.short}.x3d" failonerror="false" fullchecking="false" lenient="false" warn="true">
                            <xmlcatalog refid="X3dCatalog"/>
                        </schemavalidate>
                        <!-- from processScenes.htmlPrettyPrintPages -->
                        <!-- process individual files here. show full path to facilitate user loading, editing of reported files -->
                        <echo>${archive.path}/${relative.path1}/${relative.path2}/${name.short}.x3d processing with X3dToXhtml stylesheet for pretty-print .html</echo>
                        <!-- Saxon11 is locally defined macro -->
                        <Saxon11  scene="${relative.path1}/${relative.path2}/${name.short}"
                            stylesheet="${stylesheet.dir}/X3dToXhtml"
                             extension="html"
                        parameterPair1="linkImages=true"
                        expand="on"/>
                   <!-- expand:on since DTD defaults needed -->
                        <echo>${archive.path}/${relative.path1}/${relative.path2}/${name.short}.x3d processing with X3dExtrusionCrossSectionToSvg stylesheet for SVG diagrams (if Extrusion found)</echo>
                        <!-- Saxon11 is locally defined macro -->
                        <Saxon11  scene="${relative.path1}/${relative.path2}/${name.short}"
                            stylesheet="${stylesheet.dir}/X3dExtrusionCrossSectionToSvg"
                             extension="svg"
                                expand="on"/>
                        <!-- expand:on since DTD defaults needed -->
                        <echo>==================================================</echo>
                    </sequential>
                </outofdate>
            </sequential>
        </for>
        <antcall target="echo.timestamp"/>
        <echo>processScenes.X3dTidy complete.</echo>
        <echo>==================================================</echo>
        <echo>==================================================</echo>
    </target>

    <target  name="clean.java">
        <echo message="ensuring any prior java source files and javadoc are cleaned out..."/>
        <delete verbose="true">
            <fileset dir=".">
                    <include name="**/*.java"/>
                    <include name="**/*.class"/>
                    <exclude name="_archive/*"/>
                    <exclude name="**/CircleLines.*"/>
                    <exclude name="**/javasrc/**/*"/>
                    <exclude name="**/originals/**/*"/>
                    <!-- X3dForWebAuthors -->
                    <exclude name="KelpForestExhibit/FishSchoolCode/*"/>
                    <!-- Basic -->
                    <exclude name="course\ExtrusionXj3dGoldberg1999.*"/>
                    <exclude name="development/TestRegularExpressionChecks.*"/>
                    <exclude name="development/TestSchematronDiagnostics.*"/>
                    <exclude name="development/QuadTreeExamples.*"/>
                    <exclude name="development/SpinGroupInternalSubsetDeclaration.*"/>
                    <exclude name="DistributedInteractiveSimulation/EntityProcessor*"/>
                    <exclude name="DistributedInteractiveSimulation/BaseballBackspin/*"/>
                    <exclude name="DistributedInteractiveSimulation/CannonProject/*"/>
                    <exclude name="DistributedInteractiveSimulation/EntityProcessor.*"/>
                    <exclude name="ExperimentalBinaryCompression/isenburg/**/*"/>
                    <exclude name="ExternalAuthoringInterface/BoxEai.*"/>
                    <exclude name="ExternalAuthoringInterface/CreateSphereEai.*"/>
                    <exclude name="ExternalAuthoringInterface/HelixEai.*"/>
                    <exclude name="ExternalAuthoringInterface/SwitcherEai.*"/>
                    <exclude name="ExternalAuthoringInterface/ViewSwitchEai.*"/>
                    <exclude name="ExternalAuthoringInterface/BoxEai.*"/>
                    <exclude name="ExternalAuthoringInterface/CreateSphereEai.*"/>
                    <exclude name="ExternalAuthoringInterface/HelixEai.*"/>
                    <exclude name="ExternalAuthoringInterface/SwitcherEai.*"/>
                    <exclude name="ExternalAuthoringInterface/ViewSwitchEai.*"/>
                    <exclude name="ExternalAuthoringInterface/code/**/*"/>
                    <exclude name="ExternalAuthoringInterface/GraphicalLogAnalyzer*"/>
                    <exclude name="Geospatial/GeoVrmlSiteExamples/**/*"/>
                    <exclude name="HumanoidAnimation/ClientNetListener.*"/>
                    <exclude name="HumanoidAnimation/VoiceActivated/*"/>
                    <exclude name="LatticeXvl/XvlShell.*"/>
                    <exclude name="Networking/ConnectionScript.*"/>
                    <exclude name="Networking/NetworkSensorScript.*"/>
                    <exclude name="NURBS/NurbsCurve.*"/>
                    <exclude name="NURBS/NurbsPatchSurface.*"/>
                    <exclude name="NURBS/NurbsPositionInterpolator.*"/>
                    <exclude name="ScriptConformance/originalExamples/*"/>
                    <exclude name="ScriptConformance/SAIExample*.*"/>
                    <exclude name="ScriptConformance/ScriptNodeEventOutControl.*"/>
                    <exclude name="ScriptConformance/ScriptNodeFieldControl.*"/>
                    <exclude name="ScriptConformance/vrml/**/*"/>
                    <exclude name="ScriptConformance/originalExamples/*"/>
                    <exclude name="StudentProjects/DeadReckoningComparisons/*"/>
                    <exclude name="StudentProjects/melon/*"/>
                    <exclude name="StudentProjects/Race20/**/*"/>
                    <exclude name="X3dSpecifications/SAIExample*.*"/>
                    <!-- ConformanceNist -->
                    <exclude name="Miscellaneous/Script/**/*"/>
                    <!-- Vrml2Sourcebook/Siggraph98Course -->
                    <exclude name="**/Bounce2Script.*"/>
                    <!-- Savage -->
                    <exclude name="services/WebServices/**/*"/>
                    <exclude name="CommunicationsAndSensors/Sonobuoys/rra/**/*"/>
                    <exclude name="CommunicationsAndSensors/Sonobuoys/rra-orig/**/*"/>
                    <exclude name="CommunicationsAndSensors/TSSR/CommPduGenerator.*"/>
                    <exclude name="Scenarios/PiracyIncidents/java/**/*"/>
                    <exclude name="Scenarios/TankManeuver/SRTG.*"/>
                    <exclude name="Tools/Authoring/PixelTextureGenerator.*"/>
                    <exclude name="Tools/Slider/FloatScaler.*"/>
                    <exclude name="Tools/Slider/ScaledSFFloatScript.*"/>
                    <exclude name="Tools/Slider/SingleTypeConversionScript.*"/>
                    <exclude name="Tools/Slider/SliderScript.*"/>
                    <exclude name="Tools/Slider/widget/**/*"/>
                    <exclude name="Tools/Terrain/GeoManager.*"/>
                    <!-- SavageDefense -->
                    <exclude name="qrcode/**/*.*"/>
            </fileset>
			<!--
            <fileset dir="javadoc">
                <include name="**/*"/>
				<exclude name="overview.html"/>
            </fileset>
			-->
        </delete>
    </target>

    <target  name="clean.python" depends="clean.RoundTrip">
        <echo message="ensuring any prior converted python source files are cleaned out..."/>
		<!-- possible TODO python documentation, if ever added -->
        <delete verbose="true" failonerror="false">
            <fileset dir=".">
				<include name="**/*.py"/>
				<include name="**/*.new.x3d"/>
				<include name="**/*.newf.x3d"/>
				<include name="**/*.newFile.x3d"/>
				<exclude name="_archive/*"/>
				<exclude name="**/originals/**/*"/>
            </fileset>
        </delete>
    </target>

    <target  name="clean.RoundTrip">
        <echo message="ensuring any prior converted *RoundTrip*.* source files are cleaned out..."/>
        <delete verbose="true">
            <fileset dir=".">
				<include name="**/*RoundTrip*.*"/>
				<exclude name="_archive/*"/>
				<exclude name="**/originals/**/*"/>
            </fileset>
        </delete>
    </target>

    <target  name="clean.turtle">
        <echo message="ensuring any prior converted turtle source files are cleaned out..."/>
        <delete verbose="true" failonerror="false">
            <fileset dir=".">
				<include name="**/*.ttl"/>
				<include name="**/*.rq.txt"/>
				<exclude name="_archive/*"/>
				<exclude name="**/originals/**/*"/>
            </fileset>
        </delete>
    </target>

    <target name="processScenes.X3DJSAIL.DomLoaderTests" description="test DOM-based scene loading by X3DJSAIL.X3DLoader" depends="">
        <echo message="test DOM-based scene loading by X3DJSAIL.X3DLoader"/>
        <echo message="Verifying Apache Ant XML Catalog resolver classpath: ${resolver.dir}/${resolver.jar} (${resolver.jar.length} bytes)"/>
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="name.short"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
                <!-- trace
                <echo></echo>
                <echo>@file.path.name       = @{file.path.name}</echo>
                <echo>$archive.path         = ${archive.path}</echo>
                <echo>$relative.path1       = ${relative.path1}</echo>
                <echo>$relative.path2       = ${relative.path2}</echo>
                <echo>$name.short           = ${name.short}</echo>
                -->
				<echo message="org.web3d.x3d.jsail.CommandLine ${archive.path}/${relative.path1}/${relative.path2}/${name.short}.x3d -validate"/>
				<java classname="org.web3d.x3d.jsail.CommandLine" classpath="${x3djsail.stylesheets.dir}/${jsai.full.archive.jar.name};." fork="${fork}">
					<arg value="${archive.path}/${relative.path1}/${relative.path2}/${name.short}.x3d"/><!-- input model -->
					<arg value="-validate"/>
				</java>
				<echo message="==================================="/>
            </sequential>
        </for>
        <antcall target="echo.timestamp"/>
        <echo>processScenes.X3DJSAIL.X3DLoaderDomTests complete.</echo>
    </target>

    <target name="processScenes.java" description="generate java source, .class files, javadoc" depends="clean.RoundTrip">
	<mkdir  dir="${java.classes.dir}"/>
        <echo message="Verifying Apache Ant XML Catalog resolver classpath: ${resolver.dir}/${resolver.jar} (${resolver.jar.length} bytes)"/>
        <ant target="versions"/>
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="name.short"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
                <!-- trace
                <echo></echo>
                <echo>@file.path.name       = @{file.path.name}</echo>
                <echo>$archive.path         = ${archive.path}</echo>
                <echo>$relative.path1       = ${relative.path1}</echo>
                <echo>$relative.path2       = ${relative.path2}</echo>
                <echo>$name.short           = ${name.short}</echo>
                -->
                <outofdate>
                    <sourcefiles>
                        <filelist>
                            <file name="@{file.path.name}"/>
                        </filelist>
                    </sourcefiles>
                    <mapper dir="." type="glob" from="*.x3d" to="*.java"/>
                    <sequential>
                     <if>
                      <!-- https://ant.apache.org/manual/Tasks/conditions.html -->
                      <not>
                          <contains string="${name.short}" substring="XvlShell" />
                      </not>
                      <then>
                        <!-- process individual files here. show full path to facilitate user loading, editing of reported files -->
                        <echo>${archive.path}/${relative.path1}/${relative.path2}/${name.short}.x3d converted to ${name.short}.java</echo>
                        <!-- Saxon11 is locally defined macro -->
                        <!-- option parameterPair3="strictJava8=false" -->
                        <Saxon11  scene="${relative.path1}/${relative.path2}/${name.short}"
                            stylesheet="${stylesheet.dir}/X3dToJava"
                        parameterPair1="packageName=${archive.name}.${relative.path1}.${relative.path2}"
                        parameterPair2=  "className=${name.short}"
                        parameterPair3="includeLicense=true"
                                suffix=""
                             extension="java"
                                expand="on"/>
                        <!-- expand:on since DTD defaults needed -->
						<!-- <echo message="... compiling ${name.short}.java"/> -->
						<javac  srcdir="${relative.path1}/${relative.path2}/"
                                                      includes="${name.short}.java"
                                                     classpath="${x3djsail.stylesheets.dir}/${jsai.full.archive.jar.name}"
                                                       destdir="${java.classes.dir}"
                                                         debug="on"
                                                        source="${java.source}"
                                                        target="${java.target}"
                                                       verbose="${javac.verbose}"
                                                   failonerror="false"
                                             includeantruntime="false">
                            <!-- the following exclude statements are duplicated in processScenes.java and processScenes.javadoc since fileset is not allowed here -->
                            <exclude name="newX3dScript.java"/>
                            <exclude name="**/CircleLines.*"/>
                            <exclude name="**/bounce2.*"/>
                            <exclude name="**/javasrc/**/*"/>
                            <exclude name="**/originals/**/*"/>
                            <!-- X3dForWebAuthors -->
                            <exclude name="KelpForestExhibit/FishSchoolCode/*"/>
                            <!-- Basic -->
                            <exclude name="course\ExtrusionXj3dGoldberg1999.*"/>
                            <exclude name="development/TestRegularExpressionChecks.*"/>
                            <exclude name="development/TestSchematronDiagnostics.*"/>
                            <exclude name="development/QuadTreeExamples.*"/>
                            <exclude name="development/SpinGroupInternalSubsetDeclaration.*"/>
                            <exclude name="DistributedInteractiveSimulation/EntityProcessor*"/>
                            <exclude name="DistributedInteractiveSimulation/BaseballBackspin/*"/>
                            <exclude name="DistributedInteractiveSimulation/CannonProject/*"/>
                            <exclude name="DistributedInteractiveSimulation/EntityProcessor.*"/>
                            <exclude name="ExperimentalBinaryCompression/isenburg/**/*"/>
                            <exclude name="ExternalAuthoringInterface/BoxEai.*"/>
                            <exclude name="ExternalAuthoringInterface/CreateSphereEai.*"/>
                            <exclude name="ExternalAuthoringInterface/HelixEai.*"/>
                            <exclude name="ExternalAuthoringInterface/SwitcherEai.*"/>
                            <exclude name="ExternalAuthoringInterface/ViewSwitchEai.*"/>
                            <exclude name="ExternalAuthoringInterface/code/**/*"/>
                            <exclude name="ExternalAuthoringInterface/GraphicalLogAnalyzer*"/>
                            <exclude name="Geospatial/GeoVrmlSiteExamples/**/*"/>
                            <exclude name="HumanoidAnimation/ClientNetListener.*"/>
                            <exclude name="HumanoidAnimation/VoiceActivated/*"/>
                            <exclude name="LatticeXvl/XvlShell.*"/>
                            <exclude name="Networking/ConnectionScript.*"/>
                            <exclude name="Networking/NetworkSensorScript.*"/>
                            <exclude name="NURBS/NurbsCurve.*"/>
                            <exclude name="NURBS/NurbsPatchSurface.*"/>
                            <exclude name="NURBS/NurbsPositionInterpolator.*"/>
                            <exclude name="ScriptConformance/originalExamples/*"/>
                            <exclude name="ScriptConformance/SAIExample*.*"/>
                            <exclude name="ScriptConformance/ScriptNodeEventOutControl.*"/>
                            <exclude name="ScriptConformance/ScriptNodeFieldControl.*"/>
                            <exclude name="ScriptConformance/vrml/**/*"/>
                            <exclude name="ScriptConformance/originalExamples/*"/>
                            <exclude name="StudentProjects/DeadReckoningComparisons/*"/>
                            <exclude name="StudentProjects/melon/*"/>
                            <exclude name="StudentProjects/Race20/**/*"/>
                            <exclude name="X3dSpecifications/SAIExample*.*"/>
                            <!-- ConformanceNist -->
                            <exclude name="Miscellaneous/Script/**/*"/>
                            <!-- Savage -->
                            <exclude name="services/WebServices/**/*"/>
                            <exclude name="CommunicationsAndSensors/Sonobuoys/rra/**/*"/>
                            <exclude name="CommunicationsAndSensors/Sonobuoys/rra-orig/**/*"/>
                            <exclude name="CommunicationsAndSensors/TSSR/CommPduGenerator.*"/>
                            <exclude name="Scenarios/PiracyIncidents/java/**/*"/>
                            <exclude name="Scenarios/TankManeuver/SRTG.*"/>
                            <exclude name="Tools/Slider/FloatScaler.*"/>
                            <exclude name="Tools/Slider/ScaledSFFloatScript.*"/>
                            <exclude name="Tools/Slider/SingleTypeConversionScript.*"/>
                            <exclude name="Tools/Slider/SliderScript.*"/>
                            <exclude name="Tools/Slider/widget/**/*"/>
                            <exclude name="Tools/Terrain/GeoManager.*"/>
                            <!-- SavageDefense -->
                            <exclude name="qrcode/**/*.*"/>
                            
                            <!-- https://ant.apache.org/manual/Tasks/javac.html#bootstrap -->
                            <!-- https://stackoverflow.com/questions/4134803/ant-passing-compilerarg-into-javac -->
                            <!-- https://stackoverflow.com/questions/20174355/how-class-loading-is-done-by-using-xbootclasspath-ppath -->
                            <!-- https://stackoverflow.com/questions/48148607/how-to-add-a-jar-to-the-boot-classpath-in-java-9 -->
                            <!-- -Xbootclasspath/p became -Xbootclasspath/a in jdk 9 -->
                            <!-- <compilerarg value="-Xbootclasspath/p:${toString:lib.path.ref}"/> not allowed with target 15 -->
						</javac>
						<echo message="now run and validate the java model"/>
						<echo message="java -classpath ${java.classes.dir};${x3djsail.stylesheets.dir}/${jsai.full.archive.jar.name} ${archive.name}.${relative.path1}.${name.short}"/>
						<java    classname="${archive.name}.${relative.path1}.${relative.path2}.${name.short}"
								 classpath="${java.classes.dir};${x3djsail.stylesheets.dir}/${jsai.full.archive.jar.name}"
							   failonerror="false"/>
						<echo message="==================================="/>
                      </then>
                      <else>
                            <echo message=" ... no Java source produced for experimental LatticeXvl component, model ${name.short}.x3d"/>
                      </else>
                     </if>
                    </sequential>
                </outofdate>
            </sequential>
        </for>
        <antcall target="echo.timestamp"/>
        <echo>processScenes.java complete.</echo>
		<!-- <antcall target="processScenes.javadoc"/> -->
    </target>

    <target name="processScenes.python" description="generate python source, run validation test" depends="clean.RoundTrip">
        <!-- show python versions -->
        <exec executable="${python}"  dir="." vmlauncher="false">
            <arg value="--version"/>
        </exec>
        <!--
        <echo message="pip install - -user - -upgrade x3d"/>
        <exec executable="pip"  dir="." vmlauncher="false" timeout="${timeout}">
            <arg value="install"/>
            <arg value="- -user"/>
            <arg value="- -upgrade"/>
            <arg value="x3d"/>
        </exec>
        -->
        
        <!-- exec executable="pip"  dir="." vmlauncher="false" timeout="${timeout}" -->
        <echo message="python -m pip show x3d"/>
        <exec executable="python" dir="." vmlauncher="false" timeout="${timeout}">
            <arg value="-m"/>
            <arg value="pip"/>
            <arg value="show"/><!-- verbose -->
            <arg value="x3d"/>
        </exec>
        <property name="env.PYTHONPATH" value="${stylesheet.dir}/python"/><!-- local copy of package x3d.py -->
        <echo message="PYTHONPATH=${env.PYTHONPATH}"/>
        <!-- prior
        <echo message="$env.JAVA_HOME=${env.JAVA_HOME}"/>
		<echo message="$env.CLASSPATH=${env.CLASSPATH}"/>
		<echo message="$env.ANT_OPTS =${env.ANT_OPTS}"/>
        <echo message="$pyjnius.X3DautoclassPath =${pyjnius.X3DautoclassPath}"/>
        <echo message="$pyjnius.configurationPath=${pyjnius.configurationPath}"/>
        -->
        <echo message="Verifying Apache Ant XML Catalog resolver classpath: ${resolver.dir}/${resolver.jar} (${resolver.jar.length} bytes)"/>
        <echo message="====================="/>
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="name.short"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
                <!-- trace
                <echo></echo>
                <echo>@file.path.name       = @{file.path.name}</echo>
                <echo>$archive.path         = ${archive.path}</echo>
                <echo>$relative.path1       = ${relative.path1}</echo>
                <echo>$relative.path2       = ${relative.path2}</echo>
                <echo>$name.short           = ${name.short}</echo>
                -->
                <outofdate>
                    <sourcefiles>
                        <filelist>
                            <file name="@{file.path.name}"/>
                        </filelist>
                    </sourcefiles>
                    <mapper dir="." type="glob" from="*.x3d" to="*.py"/>
                    <sequential>
                        <!-- process individual files here. show full path to facilitate user loading, editing of reported files -->
                        <!-- see stylesheets/java/src/python/pyjnius/build.xml -->
                        <!--
						<echo message="validate original source: ${archive.path}/${relative.path1}/${relative.path2}/${name.short}.x3d"/>
						<java classname="org.web3d.x3d.jsail.CommandLine" classpath="${x3djsail.stylesheets.dir}//${jsai.full.archive.jar.name};." fork="${fork}">
                            <arg value="-validate"/>
                            <arg value="${archive.path}/${relative.path1}/${relative.path2}/${name.short}.x3d"/>< ! - - input model - - >
                        </java>
                        <echo message="- - - - - - - - - - -"/>
                        -->
			<echo message="create python:"/>
                        <!-- process individual files here.  show full path to facilitate user loading, editing of reported files -->
                        <echo>${archive.path}/${relative.path1}/${relative.path2}/${name.short}.x3d processing with X3dToPython stylesheet...</echo>
                        <!-- Saxon11 is locally defined macro -->
                        <Saxon11  scene="${relative.path1}/${relative.path2}/${name.short}"
                            stylesheet="${stylesheet.dir}/X3dToPython"
                             extension="py"
                        parameterPair1="insertPackagePrefix=false"
                                expand="on"/>
                        <!-- expand:on since DTD defaults needed -->
                        <!-- Default options:
                        parameterPair1="insertPackagePrefix=true"
                        -->
                        <echo>${archive.path}/${relative.path1}/${relative.path2}/${name.short}.py self-validation tests...</echo>
                        <if>
                            <!-- https://ant.apache.org/manual/Tasks/conditions.html -->
                            <contains string="${name.short}" substring="{name.short}" /><!-- undefined -->
                            <then>
                                <echo message="filename not found"/> <!-- in order to get a filename -->
                            </then>
                            <else>
                                <echo message="validate python:"/>
                            <!--<echo message="PYTHONPATH=${env.PYTHONPATH}"/>-->
                                <exec executable="${python}"  dir="." vmlauncher="false" timeout="${timeout}">
                                    <env key="PYTHONPATH" value="${env.PYTHONPATH}"/>
                                    <arg value="${relative.path1}/${relative.path2}/${name.short}.py"/> <!-- output-doc -->
                                    <arg value="-v"/><!-- verbose -->
                                </exec>
                            </else>
                        </if>
                        <echo message="==================================="/>
                    </sequential>
                </outofdate>
            </sequential>
        </for>
        <antcall target="echo.timestamp"/>
        <echo>processScenes.python complete.</echo>
        <echo message="==============================================================="/>
    </target>

    <target name="processScenes.turtle" description="generate turtle source, run validation test" depends="">
        <echo message="Verifying Apache Ant XML Catalog resolver classpath: ${resolver.dir}/${resolver.jar} (${resolver.jar.length} bytes)"/>
        <echo message="==================================="/>
        <for param="file.path.name">
            <path>
                <fileset refid="x3dScenes"/>
            </path>
            <sequential>
                <propertyregex
                        property="name.short"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path1"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n]*)\.x3d"
                        select="\2"/>
                <propertyregex
                        property="relative.path2"
                        override="true"
                        input="@{file.path.name}"
                        regexp="([^\n]*)Savage[\\/]([^\n^\\^/]*)[\\/]([^\n^\\^/]*)([\\/][^\n]*)\.x3d"
                        select="\3"/>
                <!-- trace
                <echo></echo>
                <echo>@file.path.name       = @{file.path.name}</echo>
                <echo>$archive.path         = ${archive.path}</echo>
                <echo>$relative.path1       = ${relative.path1}</echo>
                <echo>$relative.path2       = ${relative.path2}</echo>
                <echo>$name.short           = ${name.short}</echo>
                -->
                <outofdate>
                    <sourcefiles>
                        <filelist>
                            <file name="@{file.path.name}"/>
                        </filelist>
                    </sourcefiles>
                    <mapper dir="." type="glob" from="*.x3d" to="*.ttl"/>
                    <sequential>
                        <!-- process individual files here. show full path to facilitate user loading, editing of reported files -->
                        <!-- see ../semantics/build.xml -->
                        <!--
						<echo message="validate original source: ${archive.path}/${relative.path1}/${relative.path2}/${name.short}.x3d"/>
						<java classname="org.web3d.x3d.jsail.CommandLine" classpath="${x3djsail.stylesheets.dir}//${jsai.full.archive.jar.name};." fork="${fork}">
                            <arg value="-validate"/>
                            <arg value="${archive.path}/${relative.path1}/${relative.path2}/${name.short}.x3d"/>< ! - - input model - - >
                        </java>
                        <echo message="- - - - - - - - - - -"/>
                        -->
						<echo message="Create ${name.short}.ttl turtle representation:"/>
                        <!-- process individual files here.  show full path to facilitate user loading, editing of reported files -->
                        <echo>${archive.path}/${relative.path1}/${relative.path2}/${name.short}.x3d processing with X3dToTurtle stylesheet...</echo>
                        <!-- Saxon11 is locally defined macro -->
                        <Saxon11  scene="${relative.path1}/${relative.path2}/${name.short}"
                            stylesheet="${stylesheet.dir}/X3dToTurtle"
                             extension="ttl"
                        parameterPair1="defaultModelPrefix="
                                expand="on"/>
                        <!-- 
                        expand:on since DTD defaults needed -->
                        <!-- Default options:
                        parameterPair1="defaultModelPrefix="
                        -->
                        <echo>${archive.path}/${relative.path1}/${relative.path2}/${name.short}.ttl SPARQL query for self-validation check...</echo>
                        <if>
                            <!-- https://ant.apache.org/manual/Tasks/conditions.html -->
                            <contains string="${name.short}" substring="{name.short}" /><!-- undefined -->
                            <then>
                                    <echo message="filename not found"/> <!-- in order to get a filename -->
                            </then>
                            <else>
                                <!-- verbose output of converted .ttl file
                                <loadfile property="turtleFileContents" srcFile="${relative.path1}/${relative.path2}/${name.short}.ttl" />
                                <echo    message="${turtleFileContents}" />
                                <echo /> -->
                                <!-- create query output file -->
                                <copy file="${semantics.dir}/queries/X3dHelloWorldQuery_03.rq" tofile="${relative.path1}/${relative.path2}/${name.short}.rq.txt" overwrite="true"/>
                                <echo message="${arq} --data ${semantics.dir}/ontologies/X3dOntology4.0.ttl --query ${semantics.dir}/queries/X3dHelloWorldQuery_03.rq --graph ${relative.path1}/${relative.path2}/${name.short}.ttl"/>
                                <exec executable="${arq}"  dir="." vmlauncher="false" timeout="${timeout}">
                                    <arg value="--graph"/>
                                    <arg value="${relative.path1}/${relative.path2}/${name.short}.ttl"/>
                                    <arg value="--data"/>
                                    <arg value="${semantics.dir}/ontologies/X3dOntology4.0.ttl"/>
                                    <arg value="--query"/>
                                    <arg value="${semantics.dir}/queries/X3dHelloWorldQuery_03.rq"/>
                                    <redirector output="${relative.path1}/${relative.path2}/${name.short}.rq.txt" alwayslog="true" append="true"/>
                                </exec>
                                <echo message="X3dToTurtle.xslt conversion of ${name.short}.x3d to ${name.short}.ttl complete."/>
                            </else>
                        </if>
                        <echo message="==================================="/>
                    </sequential>
                </outofdate>
            </sequential>
        </for>
        <antcall target="echo.timestamp"/>
        <echo>processScenes.turtle complete.</echo>
        <echo message="==============================================================="/>
    </target>

	<target name="processScenes.javadoc">
		
		<property name="javadoc.windowtitle"     value="${archive.name} Examples Archive Javadoc using X3DJSAIL, X3D Java Scene Access Interface Library"/>
		<property name="javadoc.doctitle"        value="${archive.name} Examples Archive Javadoc"/>

		<javadoc     destdir="${javadoc.dir}"
				      author="${javadoc.author}"
                      bottom="${javadoc.copyright}"
               breakiterator="${javadoc.breakiterator}"
				   classpath="${x3djsail.stylesheets.dir}/${jsai.full.archive.jar.name}"
                    Encoding="${javadoc.encoding}"
                    Doctitle="${javadoc.doctitle}"
                      Header="${javadoc.doctitle}"
                   maxmemory="4096m"
                     noindex="${javadoc.noindex}"
                    nonavbar="${javadoc.nonavbar}"
                      notree="${javadoc.notree}"
                    Overview="${javadoc.dir}/overview.html"
                     Private="${javadoc.private}"
                      source="${java.source}"
                  Splitindex="${javadoc.splitindex}"
                         Use="${javadoc.use}" 
			 useexternalfile="yes"
		             verbose="true"
                     version="${javadoc.version}"
                 Windowtitle="${javadoc.windowtitle}">
			<!-- TODO
			https://stackoverflow.com/questions/10519558/createprocess-error-206-the-filename-or-extension-is-too-long-when-running-main

                  sourcepath="${src.org.web3d.x3d.sai}"
             useexternalfile="true"
                    Overview="${src.java.dir}/overview.html"
            <classpath refid="app.classpath"/>
                <include name="*/*.java"/>
			<packageset dir="${src.org.web3d.x3d.sai}" defaultexcludes="yes">
					<include name="*.java"/>
					<include name="*/*.java"/>
					<exclude name="**/*.html"/>
			</packageset>
			-->
            <fileset dir="." defaultexcludes="yes">
                <include name="*.java"/>
                <include name="*/*.java"/>
                <include name="*/*/*.java"/>
                
                            <!-- the following exclude statements are duplicated in processScenes.java and processScenes.javadoc since fileset is not allowed here -->
                            <exclude name="newX3dScript.java"/>
                            <exclude name="**/CircleLines.*"/>
                            <exclude name="**/bounce2.*"/>
                            <exclude name="**/javasrc/**/*"/>
                            <exclude name="**/originals/**/*"/>
                            <!-- X3dForWebAuthors -->
                            <exclude name="KelpForestExhibit/FishSchoolCode/*"/>
                            <!-- Basic -->
                            <exclude name="course\ExtrusionXj3dGoldberg1999.*"/>
                            <exclude name="development/TestRegularExpressionChecks.*"/>
                            <exclude name="development/TestSchematronDiagnostics.*"/>
                            <exclude name="development/QuadTreeExamples.*"/>
                            <exclude name="development/SpinGroupInternalSubsetDeclaration.*"/>
                            <exclude name="DistributedInteractiveSimulation/EntityProcessor*"/>
                            <exclude name="DistributedInteractiveSimulation/BaseballBackspin/*"/>
                            <exclude name="DistributedInteractiveSimulation/CannonProject/*"/>
                            <exclude name="DistributedInteractiveSimulation/EntityProcessor.*"/>
                            <exclude name="ExperimentalBinaryCompression/isenburg/**/*"/>
                            <exclude name="ExternalAuthoringInterface/BoxEai.*"/>
                            <exclude name="ExternalAuthoringInterface/CreateSphereEai.*"/>
                            <exclude name="ExternalAuthoringInterface/HelixEai.*"/>
                            <exclude name="ExternalAuthoringInterface/SwitcherEai.*"/>
                            <exclude name="ExternalAuthoringInterface/ViewSwitchEai.*"/>
                            <exclude name="ExternalAuthoringInterface/code/**/*"/>
                            <exclude name="ExternalAuthoringInterface/GraphicalLogAnalyzer*"/>
                            <exclude name="Geospatial/GeoVrmlSiteExamples/**/*"/>
                            <exclude name="HumanoidAnimation/ClientNetListener.*"/>
                            <exclude name="HumanoidAnimation/VoiceActivated/*"/>
                            <exclude name="LatticeXvl/XvlShell.*"/>
                            <exclude name="Networking/ConnectionScript.*"/>
                            <exclude name="Networking/NetworkSensorScript.*"/>
                            <exclude name="NURBS/NurbsCurve.*"/>
                            <exclude name="NURBS/NurbsPatchSurface.*"/>
                            <exclude name="NURBS/NurbsPositionInterpolator.*"/>
                            <exclude name="ScriptConformance/originalExamples/*"/>
                            <exclude name="ScriptConformance/SAIExample*.*"/>
                            <exclude name="ScriptConformance/ScriptNodeEventOutControl.*"/>
                            <exclude name="ScriptConformance/ScriptNodeFieldControl.*"/>
                            <exclude name="ScriptConformance/vrml/**/*"/>
                            <exclude name="ScriptConformance/originalExamples/*"/>
                            <exclude name="StudentProjects/DeadReckoningComparisons/*"/>
                            <exclude name="StudentProjects/melon/*"/>
                            <exclude name="StudentProjects/Race20/**/*"/>
                            <exclude name="X3dSpecifications/SAIExample*.*"/>
                            <!-- ConformanceNist -->
                            <exclude name="Miscellaneous/Script/**/*"/>
                            <!-- Savage -->
                            <exclude name="services/WebServices/**/*"/>
                            <exclude name="CommunicationsAndSensors/Sonobuoys/rra/**/*"/>
                            <exclude name="CommunicationsAndSensors/Sonobuoys/rra-orig/**/*"/>
                            <exclude name="CommunicationsAndSensors/TSSR/CommPduGenerator.*"/>
                            <exclude name="Scenarios/PiracyIncidents/java/**/*"/>
                            <exclude name="Scenarios/TankManeuver/SRTG.*"/>
                            <exclude name="Tools/Slider/FloatScaler.*"/>
                            <exclude name="Tools/Slider/ScaledSFFloatScript.*"/>
                            <exclude name="Tools/Slider/SingleTypeConversionScript.*"/>
                            <exclude name="Tools/Slider/SliderScript.*"/>
                            <exclude name="Tools/Slider/widget/**/*"/>
                            <exclude name="Tools/Terrain/GeoManager.*"/>
                            <!-- SavageDefense -->
                            <exclude name="qrcode/**/*.*"/>
            </fileset>
		</javadoc>
	</target>
	
    <!-- TODO:  targets for timestamp, makeWindowsShortcuts, others from Makefile -->

    <!--
    <path id="classpath">
        <fileset dir="${saxon.dir}" includes="*.jar"/>
    </path>
    <property name="cp" location="${saxon.classpath}"/>
    <target name="newScene.error" description="Copy newScene.x3d example from common example archives and convert to other encodings.  Warning:  does not override Xalan in Netbeans and fails.">
        <echo>xslt classpath=${cp}</echo>
        <delete>
            <fileset dir="." includes="newScene.*"/>
        </delete>
        <copy todir=".">
            <fileset dir=".." includes="newScene.x3d"/>
        </copy>
        <xmlvalidate file="newScene.x3d" failonerror="true" warn="true"/>
        <xslt in="newScene.x3d" out="newScene.html" style="${stylesheet.dir}/X3dToXhtml.xslt"  reloadstylesheet="yes">
                <classpath path="${cp}"/>
        </xslt>
        <xslt in="newScene.x3d" out="newScene.wrl"  style="${stylesheet.dir}/X3dToVrml97.xslt" reloadstylesheet="yes">
                <classpath path="${cp}"/>
        </xslt>
        <xslt in="newScene.x3d" out="newScene.x3dv" style="${stylesheet.dir}/X3dToX3dvClassicVrmlEncoding.xslt" reloadstylesheet="yes" basedir="." processor="trax" destdir=".">
                <classpath path="${saxon.dir}/${saxon.jar}"/>
        </xslt>
    </target>
-->

    <target name="java.run">
        <java classname="Basic.ChemicalMarkupLanguage.GlycerolDiacetate">
            <classpath path="classes;lib/${jsai.full.archive.jar.name}"/>
        </java>
    </target>
    
    <target name="versions" description="show tool versions and environment values">
        <echo>ant -version</echo>
        <exec executable="ant"     dir="." vmlauncher="false">
            <arg value="-version"/>
        </exec>
        <echo>java -version</echo>
        <exec executable="java"    dir="." vmlauncher="false">
            <arg value="-version"/>
        </exec>
        <echo>python -version</echo>
        <exec executable="${python}"  dir="." vmlauncher="false">
            <arg value="--version"/>
        </exec>
        <!-- https://www.saxonica.com/documentation9.5/using-xsl/commandline.html -->
        <echo>saxon -? help</echo>
        <java classname="net.sf.saxon.Transform" classpath="${saxon.classpath}" failonerror="true">
        <arg value="-?" description="help information"/>
        </java>
        <echo></echo>
        <!-- Ant environment variables https://ant.apache.org/manual/Tasks/property.html -->
        <echo>  ANT_HOME=${env.ANT_HOME}</echo>
        <echo> JAVA_HOME=${env.JAVA_HOME}</echo>
        <echo>PYTHONHOME=${env.PYTHONHOME}</echo>
        <echo>PYTHONPATH=${env.PYTHONPATH}</echo>
        <echo>Check for X3DJSAIL ${jsail.full.archive.jar.name} or ${jsai.classes.archive.jar.name}</echo>
        <echo>CLASSPATH=${env.CLASSPATH}</echo>
    <!--<echo>USER      =${env.USER}</echo> -->
        <!-- https://stackoverflow.com/questions/949678/ant-is-using-wrong-java-version -->
        <echo>javac source/target      $java.source=${java.source}</echo>
        <echo>Java/JVM version    $ant.java.version=${ant.java.version}</echo>
        <echo>Java/JVM detail version $java.version=${java.version}</echo>
        <echo>Ant version              $ant.version=${ant.version}</echo>
        <echo>Check for node.js installation from https://nodejs.org</echo>
        <exec executable="${node.exe}">
            <arg value="--version"/>
        </exec>
        <echo     >lib/X3DJSAIL.4.0.full.jar -version</echo>
        <java jar="lib/X3DJSAIL.4.0.full.jar" fork="${fork}">
            <arg value="-version" description="log report"/>
        </java>
        <echo>Configuration settings:  https://savage.nps.edu/Savage/developers.html</echo>
        <!-- TODO Netbeans version -->
        <!-- TODO Netbeans project version -->
        <!-- DEBUG: to show all environment and local properties, add
        <echoproperties/> -->
        <echo message="==========================================="/>
    </target>

</project>