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 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 { 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; queryIgsetElement(jobContext, querySchema, tableSrc); order++; if ((order % COMMITSIZE) == 0) { // OracleConnection connection = jobContext.getOracleConnection(); // connection.commit(); System.gc(); } } 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; } }