forked from geodmms/xdgnjobs

?? ?
2008-03-13 7f10d78b8971c812127b996fdb1d556a53fd378f
update for EOFM-16
1 files deleted
1 files modified
11 files added
6867 ■■■■■ changed files
.gitattributes 12 ●●●●● patch | view | raw | blame | history
ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/AbstractOracleDatabaseJob.java 108 ●●●●● patch | view | raw | blame | history
ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/ConvertDgn2ShpJob.java 51 ●●●●● patch | view | raw | blame | history
ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2ShpJob.java 184 ●●●●● patch | view | raw | blame | history
ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertJobContext.java 291 ●●●●● patch | view | raw | blame | history
ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleUpgradeBlob2UDTJob.java 53 ●●●●● patch | view | raw | blame | history
ximple-spatialjob/src/main/java/com/ximple/eofms/util/BinConverter.java 354 ●●●●● patch | view | raw | blame | history
ximple-spatialjob/src/main/java/com/ximple/eofms/util/Bits.java 323 ●●●●● patch | view | raw | blame | history
ximple-spatialjob/src/main/java/com/ximple/eofms/util/ByteArrayCompressor.java 97 ●●●●● patch | view | raw | blame | history
ximple-spatialjob/src/main/java/com/ximple/eofms/util/GeomUtil.java 30 ●●●●● patch | view | raw | blame | history
ximple-spatialjob/src/main/java/com/ximple/eofms/util/LangUtil.java 104 ●●●●● patch | view | raw | blame | history
ximple-spatialjob/src/main/java/com/ximple/eofms/util/PrintfFormat.java 4774 ●●●●● patch | view | raw | blame | history
ximple-spatialjob/src/main/java/com/ximple/eofms/util/TWDDatumConverter.java 486 ●●●●● patch | view | raw | blame | history
.gitattributes
@@ -38,4 +38,14 @@
ximple-jobcarrier/src/main/java/com/ximple/eofms/App.java svneol=native#text/plain
ximple-jobcarrier/src/test/java/com/ximple/eofms/AppTest.java svneol=native#text/plain
ximple-spatialjob/pom.xml svneol=native#text/xml
ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/ConvertDgn2ShpJob.java svneol=native#text/plain
ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/AbstractOracleDatabaseJob.java svneol=native#text/plain
ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2ShpJob.java svneol=native#text/plain
ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertJobContext.java svneol=native#text/plain
ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleUpgradeBlob2UDTJob.java svneol=native#text/plain
ximple-spatialjob/src/main/java/com/ximple/eofms/util/BinConverter.java svneol=native#text/plain
ximple-spatialjob/src/main/java/com/ximple/eofms/util/Bits.java svneol=native#text/plain
ximple-spatialjob/src/main/java/com/ximple/eofms/util/ByteArrayCompressor.java svneol=native#text/plain
ximple-spatialjob/src/main/java/com/ximple/eofms/util/GeomUtil.java svneol=native#text/plain
ximple-spatialjob/src/main/java/com/ximple/eofms/util/LangUtil.java svneol=native#text/plain
ximple-spatialjob/src/main/java/com/ximple/eofms/util/PrintfFormat.java svneol=native#text/plain
ximple-spatialjob/src/main/java/com/ximple/eofms/util/TWDDatumConverter.java svneol=native#text/plain
ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/AbstractOracleDatabaseJob.java
New file
@@ -0,0 +1,108 @@
package com.ximple.eofms.jobs;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.sql.SQLException;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import com.vividsolutions.jts.util.Assert;
import oracle.sql.BLOB;
public abstract class AbstractOracleDatabaseJob implements Job
{
    private static final String SHPDATA_DIR = "SHPDATA_DIR";
    private static final String SPATAILSCHEMA = "ORGSCHEMA";
    private static final String ORAHOST = "ORAHOST";
    private static final String ORAINST = "ORAINST";
    private static final String ORAPORT = "ORAPORT";
    private static final String ORAUSER = "ORAUSER";
    private static final String ORAPASS = "ORAPASS";
    protected String _dataPath;
    protected String _oracleHost;
    protected String _oracleInstance;
    protected String _oraclePort;
    protected String _username;
    protected String _password;
    protected String _orgSchema;
    public abstract void execute(JobExecutionContext context) throws JobExecutionException;
    protected void extractJobConfiguration(JobDetail jobDetail) throws JobExecutionException
    {
        // The directory to scan is stored in the job map
        JobDataMap dataMap = jobDetail.getJobDataMap();
        _dataPath = dataMap.getString(SHPDATA_DIR);
        _oracleHost = dataMap.getString(ORAHOST);
        _oracleInstance = dataMap.getString(ORAINST);
        _oraclePort = dataMap.getString(ORAPORT);
        _username = dataMap.getString(ORAUSER);
        _password = dataMap.getString(ORAPASS);
        _orgSchema = dataMap.getString(SPATAILSCHEMA);
        // Validate the required input
        if (_dataPath == null)
        {
            throw new JobExecutionException("Directory not configured");
        }
        // Make sure the directory exists
        File dir = new File(_dataPath);
        if (!dir.exists())
        {
            throw new JobExecutionException("Invalid Dir " + _dataPath);
        }
    }
    protected OracleConvertJobContext prepareJobContext()
    {
        return new OracleConvertJobContext();
    }
    protected static byte[] getBytesFromBLOB(BLOB blob) throws SQLException
    {
        byte[] raw = null;
        // BLOB        blob        = (BLOB) rs.getBlob(1);
        int         optimalSize = blob.getChunkSize();
        byte[]      chunk       = new byte[optimalSize];
        InputStream is          = blob.getBinaryStream(0);
        ByteBuffer buffer      = null;    // ByteBuffer.allocate(optimalSize);
        int         len         = 0;
        try
        {
            while ((len = (is.read(chunk))) != -1)
            {
                if (buffer != null)
                {
                    buffer.limit(buffer.limit() + len);
                } else
                {
                    buffer = ByteBuffer.allocate(len);
                }
                buffer.put(chunk);
            }
            is.close();
            buffer.position(0);
            raw = buffer.array();
        } catch (IOException e)
        {
            e.printStackTrace();    // To change body of catch statement use File | Settings | File Templates.
            Assert.shouldNeverReachHere();
        }
        return raw;
    }
}
ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/ConvertDgn2ShpJob.java
File was deleted
ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2ShpJob.java
New file
@@ -0,0 +1,184 @@
package com.ximple.eofms.jobs;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.TimeZone;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import oracle.jdbc.OracleConnection;
import oracle.jdbc.OracleResultSet;
import oracle.sql.ARRAY;
import oracle.sql.BLOB;
import com.ximple.eofms.util.BinConverter;
import com.ximple.eofms.util.ByteArrayCompressor;
import com.ximple.util.PrintfFormat;
/**
 *
 */
public class OracleConvertDgn2ShpJob extends AbstractOracleDatabaseJob
{
    static Log logger = LogFactory.getLog(OracleConvertDgn2ShpJob.class);
    private static final int FETCHSIZE = 30;
    private static final int BATCHSIZE = 25;
    public void execute(JobExecutionContext context) throws JobExecutionException
    {
        // Every job has its own job detail
        JobDetail jobDetail = context.getJobDetail();
        // The name is defined in the job definition
        String jobName = jobDetail.getName();
        // Log the time the job started
        logger.info(jobName + " fired at " + new Date());
        extractJobConfiguration(jobDetail);
        OracleConvertJobContext jobContext = prepareJobContext();
        jobContext.setConnectionInfo(_oracleHost, _oraclePort, _oracleInstance);
        jobContext.setLogin(_username, _password);
        try
        {
            exetcuteConvert(jobContext, _orgSchema, _dataPath);
        } catch (SQLException e)
        {
            throw new JobExecutionException("Database error.", e);
        }
    }
    private void exetcuteConvert(OracleConvertJobContext jobContext,
                                 String querySchema, String dataPath) throws SQLException
    {
        // verify igdsset_seed
        String srcTable = "IGSET_1";
        String destTable = OracleConvertJobContext.TABLE_PREFIX + "ELMSET_1";
        long startTime = System.currentTimeMillis();
        ArrayList srcElms = queryIgsetElement(jobContext, querySchema, srcTable);
        long currentTime = System.currentTimeMillis();
        SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss:SSS");
        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
        long elapsed = currentTime - startTime;
        System.out.println("Old Format:" + dateFormat.format(new Date(elapsed)));
        logger.info("query source element complete.");
        startTime = System.currentTimeMillis();
        ArrayList dstElms = queryRawElement(jobContext, querySchema, destTable);
        currentTime = System.currentTimeMillis();
        dateFormat = new SimpleDateFormat("HH:mm:ss:SSS");
        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
        elapsed = currentTime - startTime;
        System.out.println("New Format:" + dateFormat.format(new Date(elapsed)));
        logger.info("query dest element complete.");
        // Assert.isTrue(srcElms.size() == dstElms.size(), "src[" + srcElms.size() + "] != dest[" + dstElms.size() + "]");
    }
    private ArrayList queryIgsetElement(OracleConvertJobContext jobContext,
                                        String srcschema, String srctable) throws SQLException
    {
        ArrayList result = new ArrayList();
        OracleConnection connection = jobContext.getOracleConnection();
        String fetchSrcStmtFmt = "SELECT IGDSELM FROM \"%s\".\"%s\" ORDER BY ROWID";
        PrintfFormat spf = new PrintfFormat(fetchSrcStmtFmt);
        String fetchSrcStmt = spf.sprintf(new Object[]{srcschema, srctable});
        Statement stmtSrc = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
        stmtSrc.setFetchSize(FETCHSIZE);
        ResultSet rsSrc = stmtSrc.executeQuery(fetchSrcStmt);
        while (rsSrc.next())
        {
            byte[] raw = null;
            if (rsSrc.getMetaData().getColumnType(1) == Types.BLOB)
            {
                BLOB blob = (BLOB) rsSrc.getBlob(1);
                raw = getBytesFromBLOB(blob);
                blob.close();
            } else
            {
                raw = rsSrc.getBytes(1);
            }
            result.add(raw);
        }
        return result;
    }
    private ArrayList queryRawElement(OracleConvertJobContext jobContext,
                                      String srcschema, String srctable) throws SQLException
    {
        ArrayList result = new ArrayList();
        OracleConnection connection = jobContext.getOracleConnection();
        String fetchDestStmtFmt = "SELECT ELEMENT FROM \"%s\".\"%s\" ORDER BY ROWID";
        PrintfFormat spf = new PrintfFormat(fetchDestStmtFmt);
        String fetchDestStmt = spf.sprintf(new Object[]{srcschema, srctable});
        Statement stmtDest = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
        stmtDest.setFetchSize(FETCHSIZE);
        ResultSet rsDest = stmtDest.executeQuery(fetchDestStmt);
        while (rsDest.next())
        {
            ARRAY rawsValue = ((OracleResultSet) rsDest).getARRAY(1);
            long[] rawData = rawsValue.getLongArray();
            byte[] comparessedValue;
            /*
            if (dataMode == TransferTask.DataMode.Normal)
            {
                comparessedValue = BinConverter.unmarshalByteArray(rawData, true);
            } else
            {
                comparessedValue = BinConverter.unmarshalCompactByteArray(rawData);
            }
            */
            comparessedValue = BinConverter.unmarshalByteArray(rawData, true);
            byte[] rawDest = ByteArrayCompressor.decompressByteArray(comparessedValue);
            result.add(rawDest);
        }
        return result;
    }
    private boolean equalRawData(byte[] rawSrc, byte[] rawDest)
    {
        if (rawSrc.length != rawDest.length)
        {
            return false;
        }
        for (int i = 0; i < rawSrc.length; i++)
        {
            if (rawSrc[i] != rawDest[i])
            {
                return false;
            }
        }
        return true;
    }
}
ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertJobContext.java
New file
@@ -0,0 +1,291 @@
package com.ximple.eofms.jobs;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.vividsolutions.jts.util.Assert;
import oracle.jdbc.OracleConnection;
public class OracleConvertJobContext
{
    static Log logger = LogFactory.getLog(OracleConvertJobContext.class);
    private static final String ORACLE_URL = "jdbc:oracle:thin:@";
    private static final String PROPUsrKey = "user";
    private static final String PROPPassKey = "password";
    /**
     * Table Prefiex
     */
    protected static final String TABLE_PREFIX = "GEO$";
    protected static final String UDT_SCHEMA = "SPATIALDB";
    /**
     * User Types
     */
    protected static final String UDT_RAWS = "CREATE OR REPLACE TYPE \"" + UDT_SCHEMA + "\".\"RAWS\" AS VARRAY (1048576) OF NUMBER(38)";
    protected static final String UDT_OFMID = "CREATE OR REPLACE TYPE  \"" + UDT_SCHEMA + "\".\"OFMID\" AS OBJECT ("
            + "\"CLSID\" NUMBER(5), \"OID\" NUMBER(10), \"STATUS\" NUMBER(5), \"COMPID\" NUMBER(3), "
            + "\"RULEID\" NUMBER(3), \"OCCID\" NUMBER(3))";
    protected static final String UDT_RAWSNAME = "RAWS";
    protected static final String UDT_OFMIDNAME = "OFMID";
    /**
     * Utility SQL
     */
    protected static final String TAB_DROP = "DROP TABLE %s.%s CASCADE CONSTRAINTS";
    protected static final String TAB_DELETE = "DELETE FROM %s.%s";
    /**
     * Table Schema
     */
    protected static final String TAB_RANGENODEINDEX_1 = "CREATE TABLE \"%s\".\"%s\"\n"
            + "   (    \"RNID\" INTEGER NOT NULL ENABLE,\n"
            + "    \"RPID\" INTEGER NOT NULL ENABLE,\n"
            + "    \"RNG_LOWX\" BINARY_DOUBLE NOT NULL ENABLE,\n"
            + "    \"RNG_LOWY\" BINARY_DOUBLE NOT NULL ENABLE,\n"
            + "    \"RNG_HIGHX\" BINARY_DOUBLE NOT NULL ENABLE,\n"
            + "    \"RNG_HIGHY\" BINARY_DOUBLE NOT NULL ENABLE,\n"
            + "    \"EXTENTS\" MDSYS.SDO_GEOMETRY,\n"
            + "    \"RNDESCR\" VARCHAR2(255), \n"
            + "    PRIMARY KEY ( \"RNID\" ) ENABLE )";
    protected static final String TAB_RANGENODEINDEX = "CREATE TABLE \"%s\".\"%s\"\n"
            + "   (    \"RNID\" INTEGER NOT NULL ENABLE,\n"
            + "    \"RPID\" INTEGER NOT NULL ENABLE,\n"
            + "    \"RNG_LOWX\" FLOAT NOT NULL ENABLE,\n"
            + "    \"RNG_LOWY\" FLOAT NOT NULL ENABLE,\n"
            + "    \"RNG_HIGHX\" FLOAT NOT NULL ENABLE,\n"
            + "    \"RNG_HIGHY\" FLOAT NOT NULL ENABLE,\n"
            + "    \"RNDESCR\" VARCHAR2(255), \n"
            + "    PRIMARY KEY ( \"RNID\" ) ENABLE )";
    protected static final String TAB_RANGENODESTORAGE = "CREATE TABLE \"%s\".\"%s\"\n"
            + "   (    \"RNID\" INTEGER NOT NULL ENABLE,\n"
            + "    \"LAYERID\" NUMBER(5,0) NOT NULL ENABLE,\n"
            + "    \"LASTUPDATE\" DATE NOT NULL ENABLE,\n"
            + "    \"SPACETABLE\" VARCHAR2(255)\n" + "   )";
    protected static final String TAB_ELEMENTINDEX_1 = "CREATE TABLE %s.%s (\n"
            + "    \"ELMNO\" INTEGER NOT NULL ENABLE,\n"
            + "    \"TYPE\" NUMBER(5) NOT NULL ENABLE,\n"
            + "    \"XLOW\" BINARY_DOUBLE NOT NULL ENABLE,\n"
            + "    \"YLOW\" BINARY_DOUBLE NOT NULL ENABLE,\n"
            + "    \"ZLOW\" BINARY_DOUBLE NOT NULL ENABLE,\n"
            + "    \"XHIGH\" BINARY_DOUBLE NOT NULL ENABLE,\n"
            + "    \"YHIGH\" BINARY_DOUBLE NOT NULL ENABLE,\n"
            + "    \"ZHIGH\" BINARY_DOUBLE NOT NULL ENABLE,\n"
            + "    \"TAG_LUFID\" NUMBER(10) NOT NULL ENABLE,\n"
            + "    \"TAG_SFSC\" NUMBER(5) NOT NULL ENABLE,\n"
            + "    \"TAG_SSTAT\" NUMBER(5) NOT NULL ENABLE,\n"
            + "    \"TAG_BCOMPID\" NUMBER(3) NOT NULL ENABLE,\n"
            + "    \"TAG_BRULENO\" NUMBER(3) NOT NULL ENABLE,\n"
            + "    \"TAG_SOCCID\" NUMBER(5) NOT NULL ENABLE,\n"
            + "    \"SPACENAME\" VARCHAR2(255) NOT NULL ENABLE,\n"
            + "     PRIMARY KEY (\"ELMNO\") ENABLE\n"
            + "   )";
    protected static final String TAB_ELEMENTINDEX = "CREATE TABLE %s.%s (\n"
            + "    \"ELMNO\" INTEGER NOT NULL ENABLE,\n"
            + "    \"TYPE\" NUMBER(5) NOT NULL ENABLE,\n"
            + "    \"XLOW\" FLOAT NOT NULL ENABLE,\n"
            + "    \"YLOW\" FLOAT NOT NULL ENABLE,\n"
            + "    \"ZLOW\" FLOAT NOT NULL ENABLE,\n"
            + "    \"XHIGH\" FLOAT NOT NULL ENABLE,\n"
            + "    \"YHIGH\" FLOAT NOT NULL ENABLE,\n"
            + "    \"ZHIGH\" FLOAT NOT NULL ENABLE,\n"
            + "    \"TAG_LUFID\" NUMBER(10) NOT NULL ENABLE,\n"
            + "    \"TAG_SFSC\" NUMBER(5) NOT NULL ENABLE,\n"
            + "    \"TAG_SSTAT\" NUMBER(5) NOT NULL ENABLE,\n"
            + "    \"TAG_BCOMPID\" NUMBER(3) NOT NULL ENABLE,\n"
            + "    \"TAG_BRULENO\" NUMBER(3) NOT NULL ENABLE,\n"
            + "    \"TAG_SOCCID\" NUMBER(5) NOT NULL ENABLE,\n"
            + "    \"SPACENAME\" VARCHAR2(255) NOT NULL ENABLE,\n"
            + "     PRIMARY KEY (\"ELMNO\") ENABLE\n"
            + "   )";
    protected static final String TAB_IGDSSEED = "CREATE TABLE  %s.%s (\n"
            + "   \"ELMNO\" INTEGER NOT NULL ENABLE,\n"
            + "   \"SEEDELM\" \"" + UDT_SCHEMA
            + "\".\"RAWS\" NOT NULL ENABLE\n" + "   )";
    protected static final String TAB_STORAGE_1 = "CREATE TABLE %s.%s (\n" +
            "    \"ELMNO\" INTEGER NOT NULL ENABLE,\n" +
            "    \"XLOW\" BINARY_DOUBLE NOT NULL ENABLE,\n" +
            "    \"YLOW\" BINARY_DOUBLE NOT NULL ENABLE,\n" +
            "    \"XHIGH\" BINARY_DOUBLE NOT NULL ENABLE,\n" +
            "    \"YHIGH\" BINARY_DOUBLE NOT NULL ENABLE,\n" +
            "    \"EXTENTS\" MDSYS.SDO_GEOMETRY, \n" +
            "    \"PROPS\" INTEGER NOT NULL ENABLE,\n" +
            "    \"TAG_LUFID\" NUMBER(10) NOT NULL ENABLE,\n" +
            "    \"TAG_SFSC\" NUMBER(5) NOT NULL ENABLE,\n" +
            "    \"TAG_SSTAT\" NUMBER(5) NOT NULL ENABLE,\n" +
            "    \"TAG_BCOMPID\" NUMBER(3) NOT NULL ENABLE,\n" +
            "    \"TAG_BRULENO\" NUMBER(3) NOT NULL ENABLE,\n" +
            "    \"TAG_SOCCID\" NUMBER(5) NOT NULL ENABLE,\n" +
            "    \"LAYERID\" NUMBER(5) NOT NULL ENABLE,\n" +
            "    \"ELEMENT\" \"" + UDT_SCHEMA + "\".\"RAWS\" NOT NULL ENABLE, \n" +
            "    \"GEOM\" MDSYS.SDO_GEOMETRY \n" +
            "   )";
    protected static final String TAB_STORAGE = "CREATE TABLE %s.%s (\n" +
            "    \"ELMNO\" INTEGER NOT NULL ENABLE,\n" +
            "    \"XLOW\" FLOAT NOT NULL ENABLE,\n" +
            "    \"YLOW\" FLOAT NOT NULL ENABLE,\n" +
            "    \"XHIGH\" FLOAT NOT NULL ENABLE,\n" +
            "    \"YHIGH\" FLOAT NOT NULL ENABLE,\n" +
            "    \"PROPS\" INTEGER NOT NULL ENABLE,\n" +
            "    \"TAG_LUFID\" NUMBER(10) NOT NULL ENABLE,\n" +
            "    \"TAG_SFSC\" NUMBER(5) NOT NULL ENABLE,\n" +
            "    \"TAG_SSTAT\" NUMBER(5) NOT NULL ENABLE,\n" +
            "    \"TAG_BCOMPID\" NUMBER(3) NOT NULL ENABLE,\n" +
            "    \"TAG_BRULENO\" NUMBER(3) NOT NULL ENABLE,\n" +
            "    \"TAG_SOCCID\" NUMBER(5) NOT NULL ENABLE,\n" +
            "    \"LAYERID\" NUMBER(5) NOT NULL ENABLE,\n" +
            "    \"ELEMENT\" \"" + UDT_SCHEMA + "\".\"RAWS\" NOT NULL ENABLE \n" +
            "   )";
    protected static final String TAB_STORAGE2 = "CREATE TABLE %s.%s (\n" +
            "    \"ELMNO\" INTEGER NOT NULL ENABLE,\n" +
            "    \"XLOW\" BINARY_DOUBLE NOT NULL ENABLE,\n" +
            "    \"YLOW\" BINARY_DOUBLE NOT NULL ENABLE,\n" +
            "    \"XHIGH\" BINARY_DOUBLE NOT NULL ENABLE,\n" +
            "    \"YHIGH\" BINARY_DOUBLE NOT NULL ENABLE,\n" +
            "    \"EXTENTS\" MDSYS.SDO_GEOMETRY, \n" +
            "    \"PROPS\" INTEGER NOT NULL ENABLE,\n" +
            "    \"ID\" " + UDT_SCHEMA + ".OFMID NOT NULL ENABLE,\n" +
            "    \"LAYERID\" NUMBER(5) NOT NULL ENABLE,\n" +
            "    \"ELEMENT\" \"" + UDT_SCHEMA + "\".\"RAWS\" NOT NULL ENABLE \n" +
            "   )";
    /**
     * Trigger
     */
    protected static final String TRG_SPACENODE = "CREATE OR REPLACE TRIGGER \"%s\".\"%s\"\n"
            + "    AFTER DELETE OR INSERT OR UPDATE ON \"%s\".\"%s\"\n" + "    BEGIN\n"
            + "        UPDATE SPACENODES SET LASTUPDATE = SYSDATE\n" + "        WHERE SNID = \"%d\";\n"
            + "    END;";
    protected static final String TRG_ELMINDEX =
                    "CREATE OR REPLACE TRIGGER \"%s\".\"%s\"\n"
                    + "    AFTER INSERT OR UPDATE OR DELETE ON \"%s\".\"%s\"\n"
                    + "    REFERENCING OLD AS OLD NEW AS NEW FOR EACH ROW\n"
                    + "    BEGIN\n"
                    + "        IF INSERTING THEN\n"
                    + "            INSERT INTO \"%s\".\"%s\" (ELMNO, TYPE, XLOW, YLOW, XHIGH, YHIGH,\n"
                    + "                UFID, FSC, COMPID, OCCID, SPACENAME)\n"
                    + "            VALUES (SD$ELEMENTNUMBER_SEQ.NEXTVAL, :new.ELMTYPE, :new.XLOW, :new.YLOW, :new.XHIGH, :new.YHIGH,\n"
                    + "                :new.UFID, :new.FSC, :new.COMPID, :new.OCCID, '%s');\n"
                    + "        ELSIF DELETING THEN\n"
                    + "            DELETE FROM \"%s\".\"%s\"\n"
                    + "            WHERE \"%s\".UFID = :old.UFID AND\n"
                    + "                \"%s\".FSC = :old.FSC AND\n"
                    + "                \"%s\".COMPID = :old.COMPID AND\n"
                    + "                \"%s\".OCCID = :old.OCCID;\n"
                    + "        ELSE\n" + "            UPDATE \"%s\"\n"
                    + "            SET XLOW = :new.XLOW, YLOW = :new.YLOW, XHIGH = :new.XHIGH, YHIGH = :new.YHIGH\n"
                    + "            WHERE FSC = :new.FSC AND UFID = :new.UFID AND COMPID = :new.COMPID AND OCCID = :new.OCCID;\n"
                    + "        END IF;\n" + "    END;";
    /**
     *
     */
    protected static final String TAB_ELEMENTSET_PREFIX = "ELMSET_";
    protected static final String STMT_CLEARCYCLEBIN = "PURGE RECYCLEBIN";
    protected static final String SMTM_GRANTOBJECTTYPE = "GRANT EXECUTE ANY TYPE TO \"" + UDT_SCHEMA + "\"";
    private String _oracleHost;
    private String _oracleInstance;
    private String _oraclePort;
    static
    {
        try
        {
            DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
        } catch (SQLException e)
        {
            Assert.shouldNeverReachHere(e.getMessage());
        }
    }
    public static String getCurrentURL(String oracleHost, String oraclePort, String oracleInstance)
    {
        StringBuilder builder = new StringBuilder();
        builder.append(ORACLE_URL);
        builder.append(oracleHost);
        builder.append(":");
        builder.append(oraclePort);
        builder.append(":");
        builder.append(oracleInstance);
        return builder.toString();
    }
    private OracleConnection oracleConnection = null;
    private Properties properties;
    public OracleConvertJobContext()
    {
        properties = new Properties();
    }
    public void setLogin(String userName, String password)
    {
        properties.put(PROPUsrKey, userName);
        properties.put(PROPPassKey, password);
    }
    public OracleConnection getOracleConnection()
    {
        try
        {
            if (oracleConnection == null)
            {
                oracleConnection = (OracleConnection) DriverManager.getConnection(
                        getCurrentURL(_oracleHost, _oraclePort, _oracleInstance),
                        properties);
            }
            return oracleConnection;
        } catch (SQLException e)
        {
            logger.warn(e.getMessage(), e);
        }
        oracleConnection = null;
        return null;
    }
    public void closeConnection()
    {
        try
        {
            if (oracleConnection != null)
            {
                oracleConnection.close();
                oracleConnection = null;
            }
        } catch (SQLException e)
        {
            logger.warn(e.getMessage(), e);
        }
    }
    public void setConnectionInfo(String oracleHost, String oraclePort, String oracleInstance)
    {
        _oracleHost = oracleHost;
        _oracleInstance = oracleInstance;
        _oraclePort = oraclePort;
    }
}
ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleUpgradeBlob2UDTJob.java
New file
@@ -0,0 +1,53 @@
package com.ximple.eofms.jobs;
import java.util.Date;
import java.sql.SQLException;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobDetail;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import oracle.jdbc.OracleConnection;
import oracle.jdbc.OracleDatabaseMetaData;
import oracle.jdbc.OracleStatement;
public class OracleUpgradeBlob2UDTJob extends AbstractOracleDatabaseJob
{
    static Log logger = LogFactory.getLog(OracleUpgradeBlob2UDTJob.class);
    public void execute(JobExecutionContext context) throws JobExecutionException
    {
        // Every job has its own job detail
        JobDetail jobDetail = context.getJobDetail();
        // The name is defined in the job definition
        String jobName = jobDetail.getName();
        // Log the time the job started
        logger.info(jobName + " fired at " + new Date());
        extractJobConfiguration(jobDetail);
        OracleConvertJobContext jobContext = prepareJobContext();
        jobContext.setConnectionInfo(_oracleHost, _oraclePort, _oracleInstance);
        jobContext.setLogin(_username, _password);
        try
        {
            exetcuteConvert(jobContext, _orgSchema, _dataPath);
        } catch (SQLException e)
        {
            throw new JobExecutionException("Database error.", e);
        }
    }
    private void exetcuteConvert(OracleConvertJobContext jobContext,
                                 String orgSchema, String dataPath) throws SQLException
    {
        OracleConnection connection = jobContext.getOracleConnection();
        OracleDatabaseMetaData metaData   = (OracleDatabaseMetaData) connection.getMetaData();
        OracleStatement statement  = (OracleStatement) connection.createStatement();
    }
}
ximple-spatialjob/src/main/java/com/ximple/eofms/util/BinConverter.java
New file
@@ -0,0 +1,354 @@
package com.ximple.eofms.util;
//~--- JDK imports ------------------------------------------------------------
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.LongBuffer;
import org.testng.Assert;
/**
 * BinConverter
 * User: Ulysses
 * Date: 2007/9/17
 * Time: ¤W¤È 01:13:13
 */
public class BinConverter
{
    // our table for binhex conversion
    final static char[] HEXTAB =
    {
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
    };
    /**
     *  gets bytes from an array into a long
     *  @param buffer where to get the bytes
     *  @param nStartIndex index from where to read the data
     *  @return the 64bit integer
     */
    public static long byteArrayToLong(byte[] buffer, int nStartIndex)
    {
        return (((long) buffer[nStartIndex]) << 56) | (((long) buffer[nStartIndex + 1] & 0x0ffL) << 48)
               | (((long) buffer[nStartIndex + 2] & 0x0ffL) << 40) | (((long) buffer[nStartIndex + 3] & 0x0ffL) << 32)
               | (((long) buffer[nStartIndex + 4] & 0x0ffL) << 24) | (((long) buffer[nStartIndex + 5] & 0x0ffL) << 16)
               | (((long) buffer[nStartIndex + 6] & 0x0ffL) << 8) | ((long) buffer[nStartIndex + 7] & 0x0ff);
    }
    /**
     *  converts a long o bytes which are put into a given array
     *  @param lValue the 64bit integer to convert
     *  @param buffer the target buffer
     *  @param nStartIndex where to place the bytes in the buffer
     */
    public static void longToByteArray(long lValue, byte[] buffer, int nStartIndex)
    {
        buffer[nStartIndex]     = (byte) (lValue >>> 56);
        buffer[nStartIndex + 1] = (byte) ((lValue >>> 48) & 0x0ff);
        buffer[nStartIndex + 2] = (byte) ((lValue >>> 40) & 0x0ff);
        buffer[nStartIndex + 3] = (byte) ((lValue >>> 32) & 0x0ff);
        buffer[nStartIndex + 4] = (byte) ((lValue >>> 24) & 0x0ff);
        buffer[nStartIndex + 5] = (byte) ((lValue >>> 16) & 0x0ff);
        buffer[nStartIndex + 6] = (byte) ((lValue >>> 8) & 0x0ff);
        buffer[nStartIndex + 7] = (byte) lValue;
    }
    /**
     *  converts values from an integer array to a long
     *  @param buffer where to get the bytes
     *  @param nStartIndex index from where to read the data
     *  @return the 64bit integer
     */
    public static long intArrayToLong(int[] buffer, int nStartIndex)
    {
        return (((long) buffer[nStartIndex]) << 32) | (((long) buffer[nStartIndex + 1]) & 0x0ffffffffL);
    }
    /**
     *  converts a long to integers which are put into a given array
     *  @param lValue the 64bit integer to convert
     *  @param buffer the target buffer
     *  @param nStartIndex where to place the bytes in the buffer
     */
    public static void longToIntArray(long lValue, int[] buffer, int nStartIndex)
    {
        buffer[nStartIndex]     = (int) (lValue >>> 32);
        buffer[nStartIndex + 1] = (int) lValue;
    }
    /**
     *  makes a long from two integers (treated unsigned)
     *  @param nLo lower 32bits
     *  @param nHi higher 32bits
     *  @return the built long
     */
    public static long makeLong(int nLo, int nHi)
    {
        return (((long) nHi << 32) | ((long) nLo & 0x00000000ffffffffL));
    }
    /**
     *  gets the lower 32 bits of a long
     *  @param lVal the long integer
     *  @return lower 32 bits
     */
    public static int longLo32(long lVal)
    {
        return (int) lVal;
    }
    /**
     *  gets the higher 32 bits of a long
     *  @param lVal the long integer
     *  @return higher 32 bits
     */
    public static int longHi32(long lVal)
    {
        return (int) ((long) (lVal >>> 32));
    }
    /**
     *  converts a byte array to a binhex string
     *  @param data the byte array
     *  @return the binhex string
     */
    public static String bytesToBinHex(byte[] data)
    {
        // just map the call
        return bytesToBinHex(data, 0, data.length);
    }
    /**
     *  converts a byte array to a binhex string
     *  @param data the byte array
     *  @param nStartPos start index where to get the bytes
     *  @param nNumOfBytes number of bytes to convert
     *  @return the binhex string
     */
    public static String bytesToBinHex(byte[] data, int nStartPos, int nNumOfBytes)
    {
        StringBuffer sbuf = new StringBuffer();
        sbuf.setLength(nNumOfBytes << 1);
        int nPos = 0;
        for (int nI = 0; nI < nNumOfBytes; nI++)
        {
            sbuf.setCharAt(nPos++, HEXTAB[(data[nI + nStartPos] >> 4) & 0x0f]);
            sbuf.setCharAt(nPos++, HEXTAB[data[nI + nStartPos] & 0x0f]);
        }
        return sbuf.toString();
    }
    /**
     *  converts a binhex string back into a byte array (invalid codes will be skipped)
     *  @param sBinHex binhex string
     *  @param data the target array
     *  @param nSrcPos from which character in the string the conversion should begin,
     *                 remember that (nSrcPos modulo 2) should equals 0 normally
     *  @param nDstPos to store the bytes from which position in the array
     *  @param nNumOfBytes number of bytes to extract
     *  @return number of extracted bytes
     */
    public static int binHexToBytes(String sBinHex, byte[] data, int nSrcPos, int nDstPos, int nNumOfBytes)
    {
        // check for correct ranges
        int nStrLen     = sBinHex.length();
        int nAvailBytes = (nStrLen - nSrcPos) >> 1;
        if (nAvailBytes < nNumOfBytes)
        {
            nNumOfBytes = nAvailBytes;
        }
        int nOutputCapacity = data.length - nDstPos;
        if (nNumOfBytes > nOutputCapacity)
        {
            nNumOfBytes = nOutputCapacity;
        }
        // convert now
        int nResult = 0;
        for (int nI = 0; nI < nNumOfBytes; nI++)
        {
            byte    bActByte    = 0;
            boolean blConvertOK = true;
            for (int nJ = 0; nJ < 2; nJ++)
            {
                bActByte <<= 4;
                char cActChar = sBinHex.charAt(nSrcPos++);
                if ((cActChar >= 'a') && (cActChar <= 'f'))
                {
                    bActByte |= (byte) (cActChar - 'a') + 10;
                } else if ((cActChar >= '0') && (cActChar <= '9'))
                {
                    bActByte |= (byte) (cActChar - '0');
                } else
                {
                    blConvertOK = false;
                }
            }
            if (blConvertOK)
            {
                data[nDstPos++] = bActByte;
                nResult++;
            }
        }
        return nResult;
    }
    /**
     *  converts a byte array into an UNICODE string
     *  @param data the byte array
     *  @param nStartPos where to begin the conversion
     *  @param nNumOfBytes number of bytes to handle
     *  @return the string
     */
    public static String byteArrayToUNCString(byte[] data, int nStartPos, int nNumOfBytes)
    {
        // we need two bytes for every character
        nNumOfBytes &= ~1;
        // enough bytes in the buffer?
        int nAvailCapacity = data.length - nStartPos;
        if (nAvailCapacity < nNumOfBytes)
        {
            nNumOfBytes = nAvailCapacity;
        }
        StringBuffer sbuf = new StringBuffer();
        sbuf.setLength(nNumOfBytes >> 1);
        int nSBufPos = 0;
        while (nNumOfBytes > 0)
        {
            sbuf.setCharAt(nSBufPos++, (char) (((int) data[nStartPos] << 8) | ((int) data[nStartPos + 1] & 0x0ff)));
            nStartPos   += 2;
            nNumOfBytes -= 2;
        }
        return sbuf.toString();
    }
    public static long[] marshalByteArray(byte[] raws, boolean hasSignature)
    {
        int        remainder = raws.length % 8;
        ByteBuffer rawData   = ByteBuffer.wrap(raws);
        rawData.rewind();
        rawData.order(ByteOrder.LITTLE_ENDIAN);
        LongBuffer longBuffer = ((ByteBuffer) rawData.rewind()).asLongBuffer();
        int        resultSize = longBuffer.limit() + ((remainder != 0)
            ? 1
            : 0) + (hasSignature
                    ? 1
                    : 0);
        long[]     result     = new long[resultSize];
        int        i          = 0;
        if (hasSignature)
        {
            result[i] = raws.length;
            i++;
        }
        while (longBuffer.hasRemaining())
        {
            result[i] = longBuffer.get();
            i++;
        }
        if (remainder != 0)
        {
            int pos = (i - (hasSignature
                            ? 1
                            : 0)) * 8;
            // int pos = rawData.position();
            byte[] temp = new byte[8];
            for (int j = 0; j < remainder; j++)
            {
                temp[7 - j] = raws[pos + j];
            }
            // System.arraycopy(raws, pos, temp, 0, remainder);
            result[i] = BinConverter.byteArrayToLong(temp, 0);
        }
        return result;
    }
    public static byte[] unmarshalByteArray(long[] raws, boolean hasSignature)
    {
        LongBuffer longBuffer       = LongBuffer.wrap(raws);
        int        resultBufferSize = (raws.length - (hasSignature
            ? 1
            : 0)) * 8;
        int        resultSize       = resultBufferSize;
        if (hasSignature)
        {
            resultSize = (int) longBuffer.get();
        }
        ByteBuffer result = ByteBuffer.allocate(resultBufferSize);
        result.order(ByteOrder.LITTLE_ENDIAN);
        while (longBuffer.hasRemaining())
        {
            result.putLong(longBuffer.get());
        }
        if (resultSize == resultBufferSize)
        {
            return result.array();
        }
        byte[] resultData = new byte[resultSize];
        result.position(0);
        result.get(resultData, 0, resultSize);
        return resultData;
    }
    public static long[] marshalCompactByteArray(byte[] raws)
    {
        byte[] compactRaws = new byte[raws.length + 2];
        ByteBuffer bbCompact = ByteBuffer.wrap(compactRaws);
        bbCompact.order(ByteOrder.LITTLE_ENDIAN);
        bbCompact.putShort((short) raws.length);
        bbCompact.put(raws);
        long[] longData = BinConverter.marshalByteArray(compactRaws, false);
        return longData;
    }
    public static byte[] unmarshalCompactByteArray(long[] raws)
    {
        byte[] rawData = BinConverter.unmarshalByteArray(raws, false);
        ByteBuffer bbCompact = ByteBuffer.wrap(rawData);
        bbCompact.order(ByteOrder.LITTLE_ENDIAN);
        short originSize = bbCompact.getShort();
        byte[] rawOriginData = new byte[originSize];
        bbCompact.get(rawOriginData, 0, originSize);
        return rawOriginData;
    }
}
ximple-spatialjob/src/main/java/com/ximple/eofms/util/Bits.java
New file
@@ -0,0 +1,323 @@
package com.ximple.eofms.util;
//~--- JDK imports ------------------------------------------------------------
import java.nio.ByteOrder;
import java.security.AccessController;
import java.security.PrivilegedAction;
import sun.misc.Unsafe;
import sun.misc.VM;
/**
 * Bits
 * User: Ulysses
 * Date: 2007/6/17
 * Time: ¤W¤È 01:16:39
 */
public class Bits
{
    // -- Unsafe access --
    // private static final Unsafe unsafe = Unsafe.getUnsafe();
    // -- Processor and memory-system properties --
    private static ByteOrder byteOrder = null;
    private static int       pageSize  = -1;
    private static boolean   unaligned;
    private static boolean   unalignedKnown = false;
    // -- Direct memory management --
    // A user-settable upper limit on the maximum amount of allocatable
//  direct buffer memory. This value may be changed during VM
    // initialization if it is launched with "-XX:MaxDirectMemorySize=<size>".
    private static volatile long maxMemory      = VM.maxDirectMemory();
    private static volatile long reservedMemory = 0;
    private static boolean       memoryLimitSet = false;
    private Bits()
    {
    }
    // -- Swapping --
    public static short swap(short x)
    {
        return (short) ((x << 8) | ((x >> 8) & 0xff));
    }
    public static char swap(char x)
    {
        return (char) ((x << 8) | ((x >> 8) & 0xff));
    }
    public static int swap(int x)
    {
        return (int) ((swap((short) x) << 16) | (swap((short) (x >> 16)) & 0xffff));
    }
    public static long swap(long x)
    {
        return (long) (((long) swap((int) (x)) << 32) | ((long) swap((int) (x >> 32)) & 0xffffffffL));
    }
    // -- get/put char --
    static private char makeChar(byte b1, byte b0)
    {
        return (char) ((b1 << 8) | (b0 & 0xff));
    }
    private static byte char1(char x)
    {
        return (byte) (x >> 8);
    }
    private static byte char0(char x)
    {
        return (byte) (x >> 0);
    }
    // --get/put short--
    public static short makeShort(byte b1, byte b0)
    {
        return (short) ((b1 << 8) | (b0 & 0xff));
    }
    private static byte short1(short x)
    {
        return (byte) (x >> 8);
    }
    public static byte short0(short x)
    {
        return (byte) (x >> 0);
    }
    // -- get/put int --
    public static int makeInt(byte b3, byte b2, byte b1, byte b0)
    {
        return (int) ((((b3 & 0xff) << 24) | ((b2 & 0xff) << 16) | ((b1 & 0xff) << 8) | ((b0 & 0xff) << 0)));
    }
    public static int makeInt(short hiword, short loword)
    {
        return ((hiword & 0xffff) << 16) + (loword & 0xffff);
    }
    public static short getHiShort(int qwValue)
    {
        return ((short) (qwValue >>> 16));
    }
    public static short getLoShort(int qwValue)
    {
        return ((short) (qwValue & 0xFFFF));
    }
    public static byte int3(int x)
    {
        return (byte) (x >> 24);
    }
    public static byte int2(int x)
    {
        return (byte) (x >> 16);
    }
    private static byte int1(int x)
    {
        return (byte) (x >> 8);
    }
    private static byte int0(int x)
    {
        return (byte) (x >> 0);
    }
    // -- get/put long --
    public static long makeLong(byte b7, byte b6, byte b5, byte b4, byte b3, byte b2, byte b1, byte b0)
    {
        return ((((long) b7 & 0xff) << 56) | (((long) b6 & 0xff) << 48) | (((long) b5 & 0xff) << 40) | (((long) b4 & 0xff) << 32)
                | (((long) b3 & 0xff) << 24) | (((long) b2 & 0xff) << 16) | (((long) b1 & 0xff) << 8)
                | (((long) b0 & 0xff) << 0));
    }
    public static long makeLong(int LoValue, int HiValue)
    {
        return (((long) HiValue & 0xFFFFFFFF) << 32) + (((long) LoValue) & 0xFFFFFFFF);
    }
    public static int getHiInt(long qwValue)
    {
        return ((int)(qwValue >>> 32));
    }
    public static int getLoInt(long qwValue)
    {
        return ((int) (qwValue & 0xFFFFFFFF));
    }
    private static byte long7(long x)
    {
        return (byte) (x >> 56);
    }
    private static byte long6(long x)
    {
        return (byte) (x >> 48);
    }
    private static byte long5(long x)
    {
        return (byte) (x >> 40);
    }
    private static byte long4(long x)
    {
        return (byte) (x >> 32);
    }
    private static byte long3(long x)
    {
        return (byte) (x >> 24);
    }
    private static byte long2(long x)
    {
        return (byte) (x >> 16);
    }
    private static byte long1(long x)
    {
        return (byte) (x >> 8);
    }
    private static byte long0(long x)
    {
        return (byte) (x >> 0);
    }
    // -- get/put float --
    // -- get/put double --
    /*
    private static byte _get(long a)
    {
        return unsafe.getByte(a);
    }
    private static void _put(long a, byte b)
    {
        unsafe.putByte(a, b);
    }
    static Unsafe unsafe()
    {
        return unsafe;
    }
    static ByteOrder byteOrder()
    {
        if (byteOrder != null)
        {
            return byteOrder;
        }
        long a = unsafe.allocateMemory(8);
        try
        {
            unsafe.putLong(a, 0x0102030405060708L);
            byte b = unsafe.getByte(a);
            switch (b)
            {
            case 0x01 :
                byteOrder = ByteOrder.BIG_ENDIAN;
                break;
            case 0x08 :
                byteOrder = ByteOrder.LITTLE_ENDIAN;
                break;
            default :
                throw new Error("Unknown byte order");
            }
        } finally
        {
            unsafe.freeMemory(a);
        }
        return byteOrder;
    }
    */
    static boolean unaligned()
    {
        if (unalignedKnown)
        {
            return unaligned;
        }
        PrivilegedAction pa   = new sun.security.action.GetPropertyAction("os.arch");
        String           arch = (String) AccessController.doPrivileged(pa);
        unaligned      = arch.equals("i386") || arch.equals("x86");
        unalignedKnown = true;
        return unaligned;
    }
    // These methods should be called whenever direct memory is allocated or
    //  freed. They allow the user to control the amount of direct memory
    // which a process may access. All sizes are specified in bytes.
    static void reserveMemory(long size)
    {
        synchronized (Bits.class)
        {
            if (!memoryLimitSet && VM.isBooted())
            {
                maxMemory      = VM.maxDirectMemory();
                memoryLimitSet = true;
            }
            if (size <= maxMemory - reservedMemory)
            {
                reservedMemory += size;
                return;
            }
        }
        System.gc();
        try
        {
            Thread.sleep(100);
        } catch (InterruptedException x)
        {
            // Restore interrupt status
            Thread.currentThread().interrupt();
        }
        synchronized (Bits.class)
        {
            if (reservedMemory + size > maxMemory)
            {
                throw new OutOfMemoryError("Direct buffer memory");
            }
            reservedMemory += size;
        }
    }
    static synchronized void unreserveMemory(long size)
    {
        if (reservedMemory > 0)
        {
            reservedMemory -= size;
            assert(reservedMemory > -1);
        }
    }
}
ximple-spatialjob/src/main/java/com/ximple/eofms/util/ByteArrayCompressor.java
New file
@@ -0,0 +1,97 @@
package com.ximple.eofms.util;
//~--- JDK imports ------------------------------------------------------------
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
/**
 * ByteArrayCompressor
 * User: Ulysses
 * Date: 2007/6/15
 * Time: ¤U¤È 02:21:00
 * To change this template use File | Settings | File Templates.
 */
public final class ByteArrayCompressor
{
    public static byte[] decompressByteArray(byte[] raw)
    {
        // Create the decompressor and give it the data to compress
        Inflater decompressor = new Inflater();
        decompressor.setInput(raw);
        // Create an expandable byte array to hold the decompressed data
        ByteArrayOutputStream bos = new ByteArrayOutputStream(raw.length);
        // Decompress the data
        byte[] buf = new byte[1024];
        while (!decompressor.finished())
        {
            try
            {
                int count = decompressor.inflate(buf);
                bos.write(buf, 0, count);
            } catch (DataFormatException e)
            {
            }
        }
        try
        {
            bos.close();
        } catch (IOException e)
        {
        }
        // Get the decompressed data
        byte[] decompressedData = bos.toByteArray();
        return decompressedData;
    }
    public static byte[] compressByteArray(byte[] raw)
    {
        // Create the compressor with highest level of compression
        Deflater compressor = new Deflater();
        compressor.setLevel(Deflater.BEST_SPEED);
        // Give the compressor the data to compress
        compressor.setInput(raw);
        compressor.finish();
        // Create an expandable byte array to hold the compressed data.
        // You cannot use an array that's the same size as the orginal because
        // there is no guarantee that the compressed data will be smaller than
        // the uncompressed data.
        ByteArrayOutputStream bos = new ByteArrayOutputStream(raw.length);
        // Compress the data
        byte[] buf = new byte[1024];
        while (!compressor.finished())
        {
            int count = compressor.deflate(buf);
            bos.write(buf, 0, count);
        }
        try
        {
            bos.close();
        } catch (IOException e)
        {
        }
        // Get the compressed data
        byte[] compressedData = bos.toByteArray();
        return compressedData;
    }
}
ximple-spatialjob/src/main/java/com/ximple/eofms/util/GeomUtil.java
New file
@@ -0,0 +1,30 @@
package com.ximple.eofms.util;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Coordinate;
/**
 * Created by IntelliJ IDEA.
 * User: Ulysses
 * Date: 2007/6/15
 * Time: ¤W¤È 01:20:20
 * To change this template use File | Settings | File Templates.
 */
public final class GeomUtil
{
    public static double convertLogicalValue(double value)
    {
        return value / 1000.0 + 2147483.648;
    }
    public static Coordinate convertLogicalCooridate(Coordinate value)
    {
        return new Coordinate(convertLogicalValue(value.x), convertLogicalValue(value.y), convertLogicalValue(value.z));
    }
    public static Envelope convertLogicalEnvelope(Envelope value)
    {
        return new Envelope(convertLogicalValue(value.getMinX()), convertLogicalValue(value.getMaxX()),
                            convertLogicalValue(value.getMinY()), convertLogicalValue(value.getMaxY()));
    }
}
ximple-spatialjob/src/main/java/com/ximple/eofms/util/LangUtil.java
New file
@@ -0,0 +1,104 @@
package com.ximple.eofms.util;
import java.util.Collection;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.HashMap;
import com.vividsolutions.jts.util.Assert;
/**
 * Created by IntelliJ IDEA.
 * User: Ulysses
 * Date: 2007/6/15
 * Time: ¤W¤È 01:21:25
 * To change this template use File | Settings | File Templates.
 */
public class LangUtil
{
    private static Map primitiveToWrapperMap = new HashMap()
    {
        {
            put(byte.class, Byte.class);
            put(char.class, Character.class);
            put(short.class, Short.class);
            put(int.class, Integer.class);
            put(long.class, Long.class);
            put(float.class, Float.class);
            put(double.class, Double.class);
            put(boolean.class, Boolean.class);
        }
    };
    public static String emptyStringIfNull(String s)
    {
        return (s == null) ? "" : s;
    }
    /**
     * Useful because an expression used to generate o need only be
     * evaluated once.
     */
    public static Object ifNull(Object o, Object alternative)
    {
        return (o == null) ? alternative : o;
    }
    public static Object ifNotNull(Object o, Object alternative)
    {
        return (o != null) ? alternative : o;
    }
    public static Class toPrimitiveWrapperClass(Class primitiveClass)
    {
        return (Class) primitiveToWrapperMap.get(primitiveClass);
    }
    public static boolean isPrimitive(Class c)
    {
        return primitiveToWrapperMap.containsKey(c);
    }
    public static boolean bothNullOrEqual(Object a, Object b)
    {
        return (a == null && b == null) || (a != null && b != null && a.equals(b));
    }
    public static Object newInstance(Class c)
    {
        try
        {
            return c.newInstance();
        } catch (Exception e)
        {
            Assert.shouldNeverReachHere(e.toString());
            return null;
        }
    }
    public static Collection classesAndInterfaces(Class c)
    {
        ArrayList classesAndInterfaces = new ArrayList();
        classesAndInterfaces.add(c);
        superclasses(c, classesAndInterfaces);
        for (Iterator i = new ArrayList(classesAndInterfaces).iterator(); i.hasNext();)
        {
            Class x = (Class) i.next();
            classesAndInterfaces.addAll(Arrays.asList(x.getInterfaces()));
        }
        return classesAndInterfaces;
    }
    private static void superclasses(Class c, Collection results)
    {
        if (c.getSuperclass() == null)
        {
            return;
        }
        results.add(c.getSuperclass());
        superclasses(c.getSuperclass(), results);
    }
}
ximple-spatialjob/src/main/java/com/ximple/eofms/util/PrintfFormat.java
New file
Diff too large
ximple-spatialjob/src/main/java/com/ximple/eofms/util/TWDDatumConverter.java
New file
@@ -0,0 +1,486 @@
package com.ximple.eofms.util;
/**
 * TWDDatumConverter
 * User: Ulysses
 * Date: 2007/10/8
 * Time: ¤U¤È 01:35:03
 * To change this template use File | Settings | File Templates.
 */
public class TWDDatumConverter
{
    /*
     *   Definition of math related value
     */
    private static final double COS67_5 = 0.3826834323650897717284599840304e0;
    private static final double PI      = 3.14159265358979323e0;
    private static final double HALF_PI = 1.570796326794896615e0;
    private static final double DEG_RAD = 0.01745329251994329572e0;
    private static final double RAD_DEG = 57.295779513082321031e0;
    /*
     * Definition of datum related value
     */
    private static final double AD_C       = 1.0026000e0;
    private static final double TWD67_A    = 6378160.0e0;
    private static final double TWD67_B    = 6356774.7192e0;
    private static final double TWD67_ECC  = 0.00669454185458e0;
    private static final double TWD67_ECC2 = 0.00673966079586e0;
    // different from garmin and already knowned value, but those all value only
    private static final double TWD67_DX = -752.32e0;
    // got 5-15m accuracy. the real offical value is holded by somebody and not
    private static final double TWD67_DY = -361.32e0;
    // release to public. if can got more enough twd67/twd97 control point coordinare,
    private static final double TWD67_DZ   = -180.51e0;
    private static final double TWD67_RX   = -0.00000117e0;    // then we can calculate a better value than now.
    private static final double TWD67_RY   = 0.00000184e0;     //
    private static final double TWD67_RZ   = 0.00000098e0;     // and, also lack twd67/twd97 altitude convertion value...
    private static final double TWD67_S    = 0.00002329e0;     //
    private static final double TWD97_A    = 6378137.0e0;
    private static final double TWD97_B    = 6356752.3141e0;
    private static final double TWD97_ECC  = 0.00669438002290e0;
    private static final double TWD97_ECC2 = 0.00673949677556e0;
    private static final double TWD67_TM2  = 0.9999e0;         // TWD67->TM2 scale
    private static final double TWD97_TM2  = 0.9999e0;         // TWD97->TM2 scale
    /*
     * datum convert function
     */
    void toTWD97(double x, double y, double z)
    {
        double newX, newY, newZ;
        double r, pole, sin_lat, cos_lat;
        double lat, lon, height;
        double x1, y1, z1, x2, y2, z2;
        double q, q2, t, t1, s, s1, sum, sin_b, cos_b, sin_p, cos_p;
        lon    = x * DEG_RAD;
        lat    = y * DEG_RAD;
        height = z * DEG_RAD;
        if ((lat < -HALF_PI) && (lat > -1.001 * HALF_PI))
        {
            lat = -HALF_PI;
        } else if ((lat > HALF_PI) && (lat < 1.001 * HALF_PI))
        {
            lat = HALF_PI;
        } else if ((lat < -HALF_PI) || (lat > HALF_PI))
        {
            return;
        }
        if (lon > PI)
        {
            lon -= (2 * PI);
        }
        sin_lat = Math.sin(lat);
        cos_lat = Math.cos(lat);
        r       = TWD67_A / (Math.sqrt(1.0 - TWD67_ECC * sin_lat * sin_lat));
        x1      = (r + height) * cos_lat * Math.cos(lon);
        y1      = (r + height) * cos_lat * Math.sin(lon);
        z1      = ((r * (1 - TWD67_ECC)) + height) * sin_lat;
        x2      = x1 + TWD67_DX + TWD67_S * (lon + TWD67_RZ * lat - TWD67_RY * height);
        y2      = y1 + TWD67_DY + TWD67_S * (-TWD67_RZ * lon + lat + TWD67_RX * height);
        z2      = z1 + TWD67_DZ + TWD67_S * (TWD67_RY * lon - TWD67_RX * lat + height);
        pole    = 0.0;
        if (x2 != 0.0)
        {
            lon = Math.atan2(y2, x2);
        } else
        {
            if (y2 > 0)
            {
                lon = HALF_PI;
            } else if (y2 < 0)
            {
                lon = -HALF_PI;
            } else
            {
                pole = 1;
                lon  = 0;
                if (z2 > 0)
                {
                    lat = HALF_PI;
                } else if (z2 < 0)
                {
                    lat = -HALF_PI;
                } else
                {
                    lat  = HALF_PI;
                    newX = lon * RAD_DEG;
                    newY = lat * RAD_DEG;
                    newZ = -TWD97_B;
                    return;
                }
            }
        }
        q2    = x2 * x2 + y2 * y2;
        q     = Math.sqrt(q2);
        t     = z2 * AD_C;
        s     = Math.sqrt(t * t + q2);
        sin_b = t / s;
        cos_b = q / s;
        t1    = z2 + TWD97_B * TWD97_ECC2 * sin_b * sin_b * sin_b;
        sum   = q - TWD97_A * TWD97_ECC * cos_b * cos_b * cos_b;
        s1    = Math.sqrt(t1 * t1 + sum * sum);
        sin_p = t1 / s1;
        cos_p = sum / s1;
        r     = TWD97_A / Math.sqrt(1.0 - TWD97_ECC * sin_p * sin_p);
        if (cos_p >= COS67_5)
        {
            height = q / cos_p - r;
        } else if (cos_p <= -COS67_5)
        {
            height = q / -cos_p - r;
        } else
        {
            height = z2 / sin_p + r * (TWD97_ECC - 1.0);
        }
        if (pole !=0.0)
        {
            lat = Math.atan(sin_p / cos_p);
        }
        newX = lon * RAD_DEG;
        newY = lat * RAD_DEG;
        newZ = height;
    }
    void toTWD67(double x, double y, double z)
    {
        double newX, newY, newZ;
        double r, pole, sin_lat, cos_lat;
        double lat, lon, height;
        double x1, y1, z1, x2, y2, z2;
        double q, q2, t, t1, s, s1, sum, sin_b, cos_b, sin_p, cos_p;
        lon    = x * DEG_RAD;
        lat    = y * DEG_RAD;
        height = z * DEG_RAD;
        if ((lat < -HALF_PI) && (lat > -1.001 * HALF_PI))
        {
            lat = -HALF_PI;
        } else if ((lat > HALF_PI) && (lat < 1.001 * HALF_PI))
        {
            lat = HALF_PI;
        } else if ((lat < -HALF_PI) || (lat > HALF_PI))
        {
            return;
        }
        if (lon > PI)
        {
            lon -= (2 * PI);
        }
        sin_lat = Math.sin(lat);
        cos_lat = Math.cos(lat);
        r       = TWD97_A / (Math.sqrt(1.0 - TWD97_ECC * sin_lat * sin_lat));
        x1      = (r + height) * cos_lat * Math.cos(lon);
        y1      = (r + height) * cos_lat * Math.sin(lon);
        z1      = ((r * (1 - TWD97_ECC)) + height) * sin_lat;
        x2      = x1 - TWD67_DX - TWD67_S * (lon + TWD67_RZ * lat - TWD67_RY * height);
        y2      = y1 - TWD67_DY - TWD67_S * (-TWD67_RZ * lon + lat + TWD67_RX * height);
        z2      = z1 - TWD67_DZ - TWD67_S * (TWD67_RY * lon - TWD67_RX * lat + height);
        pole    = 0;
        if (x2 != 0.0)
        {
            lon = Math.atan2(y2, x2);
        } else
        {
            if (y2 > 0)
            {
                lon = HALF_PI;
            } else if (y2 < 0)
            {
                lon = -HALF_PI;
            } else
            {
                pole = 1;
                lon  = 0;
                if (z2 > 0)
                {
                    lat = HALF_PI;
                } else if (z2 < 0)
                {
                    lat = -HALF_PI;
                } else
                {
                    lat  = HALF_PI;
                    newX = lon * RAD_DEG;
                    newY = lat * RAD_DEG;
                    newZ = -TWD67_B;
                    return;
                }
            }
        }
        q2    = x2 * x2 + y2 * y2;
        q     = Math.sqrt(q2);
        t     = z2 * AD_C;
        s     = Math.sqrt(t * t + q2);
        sin_b = t / s;
        cos_b = q / s;
        t1    = z2 + TWD67_B * TWD67_ECC2 * sin_b * sin_b * sin_b;
        sum   = q - TWD67_A * TWD67_ECC * cos_b * cos_b * cos_b;
        s1    = Math.sqrt(t1 * t1 + sum * sum);
        sin_p = t1 / s1;
        cos_p = sum / s1;
        r     = TWD67_A / Math.sqrt(1.0 - TWD67_ECC * sin_p * sin_p);
        if (cos_p >= COS67_5)
        {
            height = q / cos_p - r;
        } else if (cos_p <= -COS67_5)
        {
            height = q / -cos_p - r;
        } else
        {
            height = z2 / sin_p + r * (TWD67_ECC - 1.0);
        }
        if (pole != 0.0)
        {
            lat = Math.atan(sin_p / cos_p);
        }
        newX = lon * RAD_DEG;
        newY = lat * RAD_DEG;
        newZ = height;
    }
    void toTM2(double a, double ecc, double ecc2, double lat, double lon, double scale, double x, double y)
    {
        double x0, y0, x1, y1, m0, m1;
        double n, t, c, A;
        double newX, newY;
        x0   = x * DEG_RAD;
        y0   = y * DEG_RAD;
        x1   = lon * DEG_RAD;
        y1   = lat * DEG_RAD;
        m0   = mercator(y1, a, ecc);
        m1   = mercator(y0, a, ecc);
        n    = a / Math.sqrt(1 - ecc * Math.pow(Math.sin(y0), 2.0));
        t    = Math.pow(Math.tan(y0), 2.0);
        c    = ecc2 * Math.pow(Math.cos(y0), 2.0);
        A    = (x0 - x1) * Math.cos(y0);
        newX = scale * n
               * (A + (1.0 - t + c) * A * A * A / 6.0
                  + (5.0 - 18.0 * t + t * t + 72.0 * c - 58.0 * ecc2) * Math.pow(A, 5.0) / 120.0);
        newY = scale
               * (m1 - m0
                  + n * Math.tan(y0)
                    * (A * A / 2.0 + (5.0 - t + 9.0 * c + 4 * c * c) * Math.pow(A, 4.0) / 24.0
                       + (61.0 - 58.0 * t + t * t + 600.0 * c - 330.0 * ecc2) * Math.pow(A, 6.0) / 720.0));
    }
    void fromTM2(double a, double ecc, double ecc2, double lat, double lon, double scale, double x, double y)
    {
        double newX, newY;
        double x0, y0, x1, y1, phi, m, m0, mu, e1;
        double c1, t1, n1, r1, d;
        x0  = x;
        y0  = y;
        x1  = lon * DEG_RAD;
        y1  = lat * DEG_RAD;
        m0  = mercator(y1, a, ecc);
        m   = m0 + y0 / scale;
        e1  = (1.0 - Math.sqrt(1.0 - ecc)) / (1.0 + Math.sqrt(1.0 - ecc));
        mu  = m / (a * (1.0 - ecc / 4.0 - 3.0 * ecc * ecc / 64.0 - 5.0 * ecc * ecc * ecc / 256.0));
        phi = mu + (3.0 * e1 / 2.0 - 27.0 * Math.pow(e1, 3.0) / 32.0) * Math.sin(2.0 * mu)
              + (21.0 * e1 * e1 / 16.0 - 55.0 * Math.pow(e1, 4.0) / 32.0) * Math.sin(4.0 * mu)
              + 151.0 * Math.pow(e1, 3.0) / 96.0 * Math.sin(6.0 * mu) + 1097.0 * Math.pow(e1, 4.0) / 512.0 * Math.sin(8.0 * mu);
        c1   = ecc2 * Math.pow(Math.cos(phi), 2.0);
        t1   = Math.pow(Math.tan(phi), 2.0);
        n1   = a / Math.sqrt(1 - ecc * Math.pow(Math.sin(phi), 2.0));
        r1   = a * (1.0 - ecc) / Math.pow(1.0 - ecc * Math.pow(Math.sin(phi), 2.0), 1.5);
        d    = x0 / (n1 * scale);
        newX = (x1 + (d - (1.0 + 2.0 * t1 + c1) * Math.pow(d, 3.0) / 6.0
                      + (5.0 - 2.0 * c1 + 28.0 * t1 - 3.0 * c1 * c1 + 8.0 * ecc2 + 24.0 * t1 * t1) * Math.pow(d, 5.0)
                        / 120.0) / Math.cos(phi)) * RAD_DEG;
        newY = (phi
                - n1 * Math.tan(phi) / r1
                  * (d * d / 2.0 - (5.0 + 3.0 * t1 + 10.0 * c1 - 4.0 * c1 * c1 - 9.0 * ecc2) * Math.pow(d, 4.0) / 24.0
                     + (61.0 + 90.0 * t1 + 298.0 * c1 + 45.0 * t1 * t1 - 252.0 * ecc2 - 3.0 * c1 * c1) * Math.pow(d, 6.0)
                       / 72.0)) * RAD_DEG;
    }
    double mercator(double y, double a, double ecc)
    {
        if (y == 0.0)
        {
            return 0.0;
        } else
        {
            return a * ((1.0 - ecc / 4.0 - 3.0 * ecc * ecc / 64.0 - 5.0 * ecc * ecc * ecc / 256.0) * y
                        - (3.0 * ecc / 8.0 + 3.0 * ecc * ecc / 32.0 + 45.0 * ecc * ecc * ecc / 1024.0) * Math.sin(2.0 * y)
                        + (15.0 * ecc * ecc / 256.0 + 45.0 * ecc * ecc * ecc / 1024.0) * Math.sin(4.0 * y)
                        - (35.0 * ecc * ecc * ecc / 3072.0) * Math.sin(6.0 * y));
        }
    }
    /**
     *
     *  Sample code below, using coordinate in Dan Jacob's website.
     *
     *
     * int main()
     * {
     *   double x1, y1, z1, x2, y2, z2;
     *   double tx1, ty1, tx2, ty2;
     *   double dx, dy, dz, dx1, dy1;
     *
     *   x1 = 120.85788004;          // TWD67
     *   y1 = 24.18347242;
     *   z1 = 777;
     *
     *   x2 = 120.86603958;          // TWD97
     *   y2 = 24.18170479;
     *   z2 = 777;
     *
     *   tx1 = 235561;               // TWD67->TM2
     *   ty1 = 2675359;
     *
     *   tx2 = 236389.849;           // TWD97->TM2
     *   ty2 = 2675153.168;
     *
     *   ////////////////////////////////////////////
     *   /
     *   /
     *   // convert TWD67->TM2
     *   /
     *   /
     *   ////////////////////////////////////////////
     *
     *   dx = x1;
     *   dy = y1;
     *
     *   toTM2(TWD67_A, TWD67_ECC, TWD67_ECC2, 0, 121, TWD67_TM2, &dx, &dy);
     *   // center longitude of taiwan is 121, for penghu is 119
     *
     *   dx += 250000;   // TM2 in Taiwan should add 250000
     *
     *   printf("TWD67->TM2nTWD67   (%f, %f)nConvert (%.3f, %.3f)nOrigin  (%.3f, %.3f)n", x1, y1, dx, dy, tx1, ty1);
     *   printf("Acuuracy (%.3f, X:%.3f, Y:%.3f)nn", sqrt((dx-tx1)*(dx-tx1)+(dy-ty1)*(dy-ty1)), (dx-tx1), (dy-ty1));
     *
     *   ////////////////////////////////////////////
     *   /
     *   /
     *   // convert TWD97->TM2
     *   /
     *   /
     *   ////////////////////////////////////////////
     *
     *   dx = x2;
     *   dy = y2;
     *
     *   toTM2(TWD97_A, TWD97_ECC, TWD97_ECC2, 0, 121, TWD97_TM2, &dx, &dy);
     *   // center longitude of taiwan is 121, for penghu is 119
     *
     *   dx += 250000;   // TM2 in Taiwan should add 250000
     *
     *   printf("TWD97->TM2nTWD97   (%f, %f)nConvert (%.3f, %.3f)nOrigin  (%.3f, %.3f)n", x2, y2, dx, dy, tx2, ty2);
     *   printf("Acuuracy (%.3f, X:%.3f, Y:%.3f)nn", sqrt((dx-tx2)*(dx-tx2)+(dy-ty2)*(dy-ty2)), (dx-tx2), (dy-ty2));
     *
     *   ////////////////////////////////////////////
     *   /
     *   /
     *   // convert TM2->TWD67
     *   /
     *   /
     *   ////////////////////////////////////////////
     *
     *   dx = tx1-250000;    // should minus 250000 first in Taiwan
     *   dy = ty1;
     *
     *   fromTM2(TWD67_A, TWD67_ECC, TWD67_ECC2, 0, 121, TWD67_TM2, &dx, &dy);
     *
     *   printf("TM2->TWD67nTM2     (%f, %f)nConvert (%.9f, %.9f)nOrigin  (%.9f, %.9f)n", tx1, ty1, dx, dy, x1, y1);
     *   printf("Acuuracy (%.9f, X:%.9f, Y:%.9f)nn", sqrt((dx-x1)*(dx-x1)+(dy-y1)*(dy-y1)), (dx-x1), (dy-y1));
     *
     *   ////////////////////////////////////////////
     *   /
     *   /
     *   // convert TM2->TWD97
     *   /
     *   /
     *   ////////////////////////////////////////////
     *
     *   dx = tx2-250000;    // should minus 250000 first in Taiwan
     *   dy = ty2;
     *
     *   fromTM2(TWD97_A, TWD97_ECC, TWD97_ECC2, 0, 121, TWD97_TM2, &dx, &dy);
     *
     *   printf("TM2->TWD97nTM2     (%f, %f)nConvert (%.9f, %.9f)nOrigin  (%.9f, %.9f)n", tx2, ty2, dx, dy, x2, y2);
     *   printf("Acuuracy (%.9f, X:%.9f, Y:%.9f)nn", sqrt((dx-x2)*(dx-x2)+(dy-y2)*(dy-y2)), (dx-x2), (dy-y2));
     *
     *   ////////////////////////////////////////////
     *   /
     *   /
     *   // convert TWD67->TWD97
     *   /
     *   /
     *   ////////////////////////////////////////////
     *
     *   dx = x1;
     *   dy = y1;
     *   dz = z1;
     *
     *   toTWD97(&dx, &dy, &dz);
     *
     *   dx1 = dx;
     *   dy1 = dy;
     *
     *   toTM2(TWD97_A, TWD97_ECC, TWD97_ECC2, 0, 121, TWD97_TM2, &dx1, &dy1);
     *
     *   dx1 += 250000;  // TM2 in Taiwan should add 250000
     *
     *   printf("TWD67->TWD97nTWD67   (%.9f, %.9f, %6.2f) (%.3f, %.3f)n", x1, y1, z1, tx1, ty1);
     *   printf("Convert (%.9f, %.9f, %6.2f) (%.3f, %.3f)n", dx, dy, dz, dx1, dy1);
     *   printf("Origin  (%.9f, %.9f, %6.2f) (%.3f, %.3f)n", x2, y2, z2, tx2, ty2);
     *   printf("Acuuracy (%.4f, X:%.4f, Y:%.4f)nn", sqrt((dx1-tx2)*(dx1-tx2)+(dy1-ty2)*(dy1-ty2)), (dx1-tx2), (dy1-ty2));
     *
     *   ////////////////////////////////////////////
     *   /
     *   /
     *   // convert TWD97->TWD67
     *   /
     *   /
     *   ////////////////////////////////////////////
     *
     *   dx = x2;
     *   dy = y2;
     *   dz = z2;
     *
     *   toTWD67(&dx, &dy, &dz);
     *
     *   dx1 = dx;
     *   dy1 = dy;
     *
     *   toTM2(TWD67_A, TWD67_ECC, TWD67_ECC2, 0, 121, TWD67_TM2, &dx1, &dy1);
     *
     *   dx1 += 250000;  // TM2 in Taiwan should add 250000
     *
     *   printf("TWD97->TWD67nTWD97   (%.9f, %.9f, %6.2f) (%.3f, %.3f)n", x2, y2, z2, tx2, ty2);
     *   printf("Convert (%.9f, %.9f, %6.2f) (%.3f, %.3f)n", dx, dy, dz, dx1, dy1);
     *   printf("Origin  (%.9f, %.9f, %6.2f) (%.3f, %.3f)n", x1, y1, z1, tx1, ty1);
     *   printf("Acuuracy (%.4f, X:%.4f, Y:%.4f)nn", sqrt((dx1-tx1)*(dx1-tx1)+(dy1-ty1)*(dy1-ty1)), (dx1-tx1), (dy1-ty1));
     * }
     */
}