package com.ximple.eofms.jobs;
|
|
import java.io.File;
|
import java.io.IOException;
|
import java.math.BigDecimal;
|
import java.net.MalformedURLException;
|
import java.nio.ByteBuffer;
|
import java.nio.ByteOrder;
|
import java.sql.ResultSet;
|
import java.sql.SQLException;
|
import java.sql.Statement;
|
import java.sql.Types;
|
import java.util.Date;
|
|
import org.apache.commons.collections.OrderedMap;
|
import org.apache.commons.collections.OrderedMapIterator;
|
import org.apache.commons.collections.map.LinkedMap;
|
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.LogFactory;
|
import org.geotools.data.FeatureWriter;
|
import org.geotools.data.Transaction;
|
import org.geotools.data.shapefile.ShapefileDataStore;
|
import org.geotools.feature.AttributeTypeFactory;
|
import org.geotools.feature.Feature;
|
import org.geotools.feature.FeatureCollection;
|
import org.geotools.feature.FeatureCollections;
|
import org.geotools.feature.FeatureType;
|
import org.geotools.feature.FeatureTypeBuilder;
|
import org.geotools.feature.IllegalAttributeException;
|
import org.geotools.feature.SchemaException;
|
import org.geotools.feature.SimpleFeature;
|
import org.opengis.geometry.Geometry;
|
import org.quartz.JobDetail;
|
import org.quartz.JobExecutionContext;
|
import org.quartz.JobExecutionException;
|
|
import com.vividsolutions.jts.geom.GeometryFactory;
|
|
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.io.dgn7.ComplexElement;
|
import com.ximple.io.dgn7.Dgn7fileException;
|
import com.ximple.io.dgn7.Element;
|
import com.ximple.io.dgn7.ElementType;
|
import com.ximple.io.dgn7.IElementHandler;
|
import com.ximple.io.dgn7.LineElement;
|
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;
|
private static final int COMMITSIZE = 20;
|
|
class Pair
|
{
|
Object first;
|
Object second;
|
|
public Pair(Object first, Object second)
|
{
|
this.first = first;
|
this.second = second;
|
}
|
}
|
|
public Log getLogger()
|
{
|
return logger;
|
}
|
|
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)
|
{
|
logger.warn(e.getMessage(), e);
|
throw new JobExecutionException("Database error.", e);
|
}
|
|
}
|
|
private void exetcuteConvert(OracleConvertJobContext jobContext,
|
String querySchema, String dataPath) throws SQLException
|
{
|
int order = 0;
|
OrderedMap map = getBlobStorageList(jobContext.getOracleConnection(), querySchema, "SD$SPACENODES"
|
, null);
|
|
for (OrderedMapIterator it = map.orderedMapIterator(); it.hasNext();)
|
{
|
it.next();
|
|
Pair pair = (Pair) it.getValue();
|
|
String tableSrc = (String) pair.first;
|
|
logger.info("begin convert:[" + order + "]-" + tableSrc);
|
queryIgsetElement(jobContext, querySchema, tableSrc);
|
|
order++;
|
|
if (_testMode) break;
|
|
if ((order % COMMITSIZE) == 0)
|
{
|
// OracleConnection connection = jobContext.getOracleConnection();
|
// connection.commit();
|
System.gc();
|
}
|
}
|
|
logger.info("end convert job:[" + order + "]");
|
System.gc();
|
}
|
|
private OrderedMap getBlobStorageList(OracleConnection connection, String schemaSrc, String tableSrc,
|
OrderedMap orderedMap) throws SQLException
|
{
|
if (orderedMap == null)
|
orderedMap = new LinkedMap(99);
|
String fetchStmtFmt = "SELECT SNID, SPACETABLE FROM \"%s\".\"%s\"";
|
PrintfFormat spf = new PrintfFormat(fetchStmtFmt);
|
String fetchStmt = spf.sprintf(new Object[]{schemaSrc, tableSrc});
|
Statement stmt = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
|
|
stmt.setFetchSize(FETCHSIZE);
|
|
ResultSet rs = stmt.executeQuery(fetchStmt);
|
|
while (rs.next())
|
{
|
int size = rs.getMetaData().getColumnCount();
|
Object[] values = new Object[size];
|
|
for (int i = 0; i < size; i++)
|
{
|
values[i] = rs.getObject(i + 1);
|
}
|
|
Integer key = new Integer(((BigDecimal) values[0]).intValue());
|
String name = (String) values[1];
|
|
Pair pair = (Pair) orderedMap.get(key);
|
if (pair == null)
|
orderedMap.put(key, new Pair(name, null));
|
else
|
pair.first = name;
|
}
|
|
rs.close();
|
stmt.close();
|
|
return orderedMap;
|
}
|
|
private OrderedMap getRawFormatStorageList(OracleConnection connection, String schemaSrc, String tableSrc,
|
OrderedMap orderedMap) throws SQLException
|
{
|
if (orderedMap == null)
|
orderedMap = new LinkedMap(99);
|
String fetchStmtFmt = "SELECT RNID, SPACETABLE FROM \"%s\".\"%s\"";
|
PrintfFormat spf = new PrintfFormat(fetchStmtFmt);
|
String fetchStmt = spf.sprintf(new Object[]{schemaSrc, tableSrc});
|
Statement stmt = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
|
|
stmt.setFetchSize(FETCHSIZE);
|
|
ResultSet rs = stmt.executeQuery(fetchStmt);
|
|
while (rs.next())
|
{
|
int size = rs.getMetaData().getColumnCount();
|
Object[] values = new Object[size];
|
|
for (int i = 0; i < size; i++)
|
{
|
values[i] = rs.getObject(i + 1);
|
}
|
|
Integer key = new Integer(((BigDecimal) values[0]).intValue());
|
String name = (String) values[1];
|
|
Pair pair = (Pair) orderedMap.get(key);
|
if (pair == null)
|
orderedMap.put(key, new Pair(null, name));
|
else
|
pair.second = name;
|
}
|
|
rs.close();
|
stmt.close();
|
|
return orderedMap;
|
}
|
|
private void queryIgsetElement(OracleConvertJobContext jobContext,
|
String srcschema, String srctable) throws SQLException
|
{
|
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);
|
}
|
|
try
|
{
|
onBinaryElement(raw);
|
} catch (Dgn7fileException e)
|
{
|
logger.warn("Dgn7Exception", e);
|
}
|
}
|
}
|
|
private void queryRawElement(OracleConvertJobContext jobContext,
|
String srcschema, String srctable) throws SQLException
|
{
|
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);
|
|
|
try
|
{
|
onBinaryElement(rawDest);
|
} catch (Dgn7fileException e)
|
{
|
logger.warn("Dgn7Exception:" + e.getMessage(), e);
|
}
|
}
|
}
|
|
private void onBinaryElement(byte[] raws) throws Dgn7fileException
|
{
|
ByteBuffer buffer = ByteBuffer.wrap(raws);
|
buffer.order(ByteOrder.LITTLE_ENDIAN);
|
short signature = buffer.getShort();
|
|
// byte type = (byte) (buffer.get() & 0x7f);
|
byte type = (byte) ((signature >>> 8) & 0x007f);
|
|
// silly Bentley say contentLength is in 2-byte words
|
// and ByteByffer uses raws.
|
// track the record location
|
int elementLength = (buffer.getShort() * 2) + 4;
|
ElementType recordType = ElementType.forID(type);
|
IElementHandler handler = null;
|
|
handler = recordType.getElementHandler();
|
|
Element dgnElement = (Element) handler.read(buffer, signature, elementLength);
|
if (recordType.isComplexElement() && (elementLength < raws.length))
|
{
|
int offset = elementLength;
|
while (offset < (raws.length - 4))
|
{
|
buffer.position(offset);
|
signature = buffer.getShort();
|
type = (byte) ((signature >>> 8) & 0x007f);
|
elementLength = (buffer.getShort() * 2) + 4;
|
if (raws.length < (offset + elementLength))
|
{
|
System.out.println("Length not match:" + offset + ":" + buffer.position() + ":" + buffer.limit());
|
break;
|
}
|
recordType = ElementType.forID(type);
|
handler = recordType.getElementHandler();
|
if (handler != null)
|
{
|
Element subElement = (Element) handler.read(buffer, signature, elementLength);
|
((ComplexElement) dgnElement).add(subElement);
|
offset += elementLength;
|
} else
|
{
|
byte[] remain = new byte[buffer.remaining()];
|
System.arraycopy(raws, offset, remain, 0, buffer.remaining());
|
for (int i = 0; i < remain.length; i++)
|
{
|
if (remain[i] != 0)
|
{
|
logger.info("fetch element has some error. index=" + (offset + i) + ":value=" + remain[i]);
|
System.out.println("fetch element has some error. index=" + (offset + i) + ":value=" + remain[i]);
|
}
|
}
|
break;
|
}
|
}
|
}
|
|
Feature feature = convertElementToFeature(dgnElement);
|
}
|
|
private Feature convertElementToFeature(Element dgnElement)
|
{
|
GeometryFactory geomFactory = new GeometryFactory();
|
FeatureTypeBuilder typeBuilder = FeatureTypeBuilder.newInstance("Line");
|
|
typeBuilder.addType(AttributeTypeFactory.newAttributeType("GEOM", Geometry.class));
|
typeBuilder.addType(AttributeTypeFactory.newAttributeType("TID", Integer.class));
|
typeBuilder.addType(AttributeTypeFactory.newAttributeType("OID", Long.class));
|
typeBuilder.addType(AttributeTypeFactory.newAttributeType("CID", Integer.class));
|
typeBuilder.addType(AttributeTypeFactory.newAttributeType("LID", Integer.class));
|
typeBuilder.addType(AttributeTypeFactory.newAttributeType("LEVEL", Integer.class));
|
typeBuilder.addType(AttributeTypeFactory.newAttributeType("SYMCOLOR", Integer.class));
|
typeBuilder.addType(AttributeTypeFactory.newAttributeType("SYMWEIGHT", Integer.class));
|
typeBuilder.addType(AttributeTypeFactory.newAttributeType("SYMSTYLE", Integer.class));
|
typeBuilder.addType(AttributeTypeFactory.newAttributeType("FONT", String.class));
|
typeBuilder.addType(AttributeTypeFactory.newAttributeType("JUST", Integer.class));
|
typeBuilder.addType(AttributeTypeFactory.newAttributeType("HEIGHT", Double.class));
|
typeBuilder.addType(AttributeTypeFactory.newAttributeType("WIDTH", Double.class));
|
typeBuilder.addType(AttributeTypeFactory.newAttributeType("ANGLE", Double.class));
|
|
// typeBuilder.setNamespace(new URI(""));
|
Feature feature = null;
|
try
|
{
|
FeatureType featureType = typeBuilder.getFeatureType();
|
feature = featureType.create(new Object[]{
|
((LineElement) dgnElement).toGeometry(geomFactory)
|
});
|
|
FeatureCollection features = FeatureCollections.newCollection();
|
features.add(feature);
|
|
File sfile = new File("");
|
ShapefileDataStore shapefileDataStore = new ShapefileDataStore(sfile.toURL());
|
shapefileDataStore.createSchema(featureType);
|
FeatureWriter writer = shapefileDataStore.getFeatureWriter(featureType.getTypeName(), Transaction.AUTO_COMMIT);
|
((SimpleFeature) writer.next()).setAttributes(feature.getAttributes(null));
|
|
} catch (SchemaException e)
|
{
|
logger.warn(e.getMessage(), e);
|
} catch (IllegalAttributeException e)
|
{
|
logger.warn(e.getMessage(), e);
|
} catch (MalformedURLException e)
|
{
|
logger.warn(e.getMessage(), e);
|
} catch (IOException e)
|
{
|
logger.warn(e.getMessage(), e);
|
}
|
|
|
return null;
|
}
|
|
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;
|
}
|
|
public FeatureCollection loopupFeatureCollection(String name)
|
{
|
return null;
|
}
|
}
|