From f74be0cace55a2d65fa65329b521b50e0cef2c31 Mon Sep 17 00:00:00 2001 From: ?? ? <ulysseskao@ximple.com.tw> Date: Thu, 12 Jun 2008 13:03:49 +0800 Subject: [PATCH] update for EOFM-116, EOFM-117 --- xdgnjobs/ximple-jobcarrier/src/main/resources/log4j.properties | 2 .gitattributes | 2 xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateShapeStrategy.java | 29 xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateFeatureTypeStrategy.java | 4 xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/FeatureTypeEvent.java | 28 xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2OraSDOJob.java | 11 xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2ShpJob.java | 3 xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/TypeIdDispatchableFilter.java | 8 xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateSymbolStrategy.java | 29 xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/TypeCompLevelIdDispatchableFilter.java | 7 xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateLineStringStrategy.java | 29 xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2PostGISJob.java | 17 xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/context/postgis/IndexDgnConvertPostGISJobContext.java | 261 ++++-- xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/context/postgis/AbstractOracleToPostGISJobContext.java | 718 ++++++++++++++++++ xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/AbstractDispatchableFilter.java | 26 xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateFeatureTypeEventListener.java | 8 xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/util/FeatureTypeBuilderUtil.java | 64 xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/context/postgis/GeneralDgnConvertPostGISJobContext.java | 190 +++- xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2MySQLJob.java | 3 xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateTextStrategy.java | 34 xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/TypeCompIdDispatchableFilter.java | 7 xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateLineTextStrategy.java | 29 xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/context/postgis/AbstractDgnToPostGISJobContext.java | 720 ++++++++++++++++++ 23 files changed, 2,032 insertions(+), 197 deletions(-) diff --git a/.gitattributes b/.gitattributes index 26fec7b..f224d43 100644 --- a/.gitattributes +++ b/.gitattributes @@ -51,6 +51,7 @@ xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/AbstractFLinkageDispatchableFilter.java svneol=native#text/plain xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateArcLineStringStrategy.java svneol=native#text/plain xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateEllipseShapeStrategy.java svneol=native#text/plain +xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateFeatureTypeEventListener.java svneol=native#text/plain xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateFeatureTypeStrategy.java svneol=native#text/plain xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateLineStringStrategy.java svneol=native#text/plain xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateLineTextStrategy.java svneol=native#text/plain @@ -61,6 +62,7 @@ xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/ElementDispatcher.java svneol=native#text/plain xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/ElementLevelCriterion.java svneol=native#text/plain xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/ElementTypeCriterion.java svneol=native#text/plain +xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/FeatureTypeEvent.java svneol=native#text/plain xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/TypeCompIdDispatchableFilter.java svneol=native#text/plain xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/TypeCompLevelIdDispatchableFilter.java svneol=native#text/plain xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/TypeIdDispatchableFilter.java svneol=native#text/plain diff --git a/xdgnjobs/ximple-jobcarrier/src/main/resources/log4j.properties b/xdgnjobs/ximple-jobcarrier/src/main/resources/log4j.properties index 2691982..e7c6650 100644 --- a/xdgnjobs/ximple-jobcarrier/src/main/resources/log4j.properties +++ b/xdgnjobs/ximple-jobcarrier/src/main/resources/log4j.properties @@ -25,4 +25,4 @@ # Print messages of level INFO or above for examples log4j.logger.org.cavaness.quartzbook=INFO -log4j.logger.com.ximple.eofms=INFO \ No newline at end of file +log4j.logger.com.ximple.eofms=DEBUG \ No newline at end of file diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/AbstractDispatchableFilter.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/AbstractDispatchableFilter.java index b39643c..d6e91b1 100644 --- a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/AbstractDispatchableFilter.java +++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/AbstractDispatchableFilter.java @@ -2,6 +2,8 @@ import java.util.LinkedList; +import javax.swing.event.EventListenerList; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -15,6 +17,9 @@ private LinkedList<ElementLevelCriterion> levelCriterions; protected Log logger = LogFactory.getLog(AbstractFLinkageDispatchableFilter.class); + + // Create the listener list + protected EventListenerList listenerList = new EventListenerList(); public AbstractDispatchableFilter() { @@ -72,4 +77,25 @@ return -1; } + public void addCreateFeatureTypeEventListener(CreateFeatureTypeEventListener listener) + { + listenerList.add(CreateFeatureTypeEventListener.class, listener); + } + + public void removeCreateFeatureTypeEventListener(CreateFeatureTypeEventListener listener) + { + listenerList.remove(CreateFeatureTypeEventListener.class, listener); + } + + protected void fireFeatureTypeEvent(FeatureTypeEvent evt) + { + Object[] listeners = listenerList.getListenerList(); + for (int i = 0; i < listeners.length; i += 2) + { + if (listeners[i] == CreateFeatureTypeEventListener.class) + { + ((CreateFeatureTypeEventListener) listeners[i + 1]).createFeatureTypeOccurred(evt); + } + } + } } diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateFeatureTypeEventListener.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateFeatureTypeEventListener.java new file mode 100644 index 0000000..4a81200 --- /dev/null +++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateFeatureTypeEventListener.java @@ -0,0 +1,8 @@ +package com.ximple.eofms.filter; + +import java.util.EventListener; + +public interface CreateFeatureTypeEventListener extends EventListener +{ + public void createFeatureTypeOccurred(FeatureTypeEvent evt); +} diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateFeatureTypeStrategy.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateFeatureTypeStrategy.java index 7f8c9f7..83d0074 100644 --- a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateFeatureTypeStrategy.java +++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateFeatureTypeStrategy.java @@ -10,6 +10,8 @@ public interface CreateFeatureTypeStrategy { public FeatureType createFeatureElement(String featureName) throws SchemaException; - public Feature createFeature(FeatureType featureType, Element element) throws IllegalAttributeException; + + public void addCreateFeatureTypeEventListener(CreateFeatureTypeEventListener listener); + public void removeCreateFeatureTypeEventListener(CreateFeatureTypeEventListener listener); } diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateLineStringStrategy.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateLineStringStrategy.java index 65cf4a3..8c134c3 100644 --- a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateLineStringStrategy.java +++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateLineStringStrategy.java @@ -3,6 +3,8 @@ import java.util.List; import java.util.TreeMap; +import javax.swing.event.EventListenerList; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.geotools.feature.Feature; @@ -31,6 +33,9 @@ TreeMap<String, FeatureTypeBuilder> typeBuilders = new TreeMap<String, FeatureTypeBuilder>(); TWD97GeometryConverterDecorator convertDecorator = new TWD97GeometryConverterDecorator(); + // Create the listener list + protected EventListenerList listenerList = new EventListenerList(); + public CreateLineStringStrategy() { } @@ -57,6 +62,7 @@ { FeatureTypeBuilder typeBuilder = FeatureTypeBuilderUtil.createLineStringFeatureTypeBuilder(featureName); typeBuilders.put(featureName, typeBuilder); + fireFeatureTypeEvent(new FeatureTypeEvent(this, typeBuilder.getFeatureType())); } return typeBuilders.get(featureName).getFeatureType(); } @@ -132,4 +138,27 @@ return feature; } + + + public void addCreateFeatureTypeEventListener(CreateFeatureTypeEventListener listener) + { + listenerList.add(CreateFeatureTypeEventListener.class, listener); + } + + public void removeCreateFeatureTypeEventListener(CreateFeatureTypeEventListener listener) + { + listenerList.remove(CreateFeatureTypeEventListener.class, listener); + } + + protected void fireFeatureTypeEvent(FeatureTypeEvent evt) + { + Object[] listeners = listenerList.getListenerList(); + for (int i = 0; i < listeners.length; i += 2) + { + if (listeners[i] == CreateFeatureTypeEventListener.class) + { + ((CreateFeatureTypeEventListener) listeners[i + 1]).createFeatureTypeOccurred(evt); + } + } + } } diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateLineTextStrategy.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateLineTextStrategy.java index 1561e70..b8095bc 100644 --- a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateLineTextStrategy.java +++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateLineTextStrategy.java @@ -3,6 +3,8 @@ import java.util.List; import java.util.TreeMap; +import javax.swing.event.EventListenerList; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.geotools.feature.Feature; @@ -34,6 +36,9 @@ TreeMap<String, FeatureTypeBuilder> typeBuilders = new TreeMap<String, FeatureTypeBuilder>(); TWD97GeometryConverterDecorator convertDecorator = new TWD97GeometryConverterDecorator(); + // Create the listener list + protected EventListenerList listenerList = new EventListenerList(); + public CreateLineTextStrategy() { } @@ -60,6 +65,7 @@ { FeatureTypeBuilder typeBuilder = FeatureTypeBuilderUtil.createLineStringFeatureTypeBuilder(featureName); typeBuilders.put(featureName, typeBuilder); + fireFeatureTypeEvent(new FeatureTypeEvent(this, typeBuilder.getFeatureType())); } return typeBuilders.get(featureName).getFeatureType(); } @@ -147,5 +153,28 @@ return feature; } + + + public void addCreateFeatureTypeEventListener(CreateFeatureTypeEventListener listener) + { + listenerList.add(CreateFeatureTypeEventListener.class, listener); + } + + public void removeCreateFeatureTypeEventListener(CreateFeatureTypeEventListener listener) + { + listenerList.remove(CreateFeatureTypeEventListener.class, listener); + } + + protected void fireFeatureTypeEvent(FeatureTypeEvent evt) + { + Object[] listeners = listenerList.getListenerList(); + for (int i = 0; i < listeners.length; i += 2) + { + if (listeners[i] == CreateFeatureTypeEventListener.class) + { + ((CreateFeatureTypeEventListener) listeners[i + 1]).createFeatureTypeOccurred(evt); + } + } + } } diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateShapeStrategy.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateShapeStrategy.java index dbb80a7..b51b9af 100644 --- a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateShapeStrategy.java +++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateShapeStrategy.java @@ -3,6 +3,8 @@ import java.util.List; import java.util.TreeMap; +import javax.swing.event.EventListenerList; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.geotools.feature.Feature; @@ -28,6 +30,9 @@ GeometryFactory geometryFactory = new GeometryFactory(); TreeMap<String, FeatureTypeBuilder> typeBuilders = new TreeMap<String, FeatureTypeBuilder>(); TWD97GeometryConverterDecorator convertDecorator = new TWD97GeometryConverterDecorator(); + + // Create the listener list + protected EventListenerList listenerList = new EventListenerList(); public CreateShapeStrategy() { @@ -55,6 +60,7 @@ { FeatureTypeBuilder typeBuilder = FeatureTypeBuilderUtil.createPolygonFeatureTypeBuilder(featureName); typeBuilders.put(featureName, typeBuilder); + fireFeatureTypeEvent(new FeatureTypeEvent(this, typeBuilder.getFeatureType())); } return typeBuilders.get(featureName).getFeatureType(); } @@ -98,4 +104,27 @@ } return feature; } + + + public void addCreateFeatureTypeEventListener(CreateFeatureTypeEventListener listener) + { + listenerList.add(CreateFeatureTypeEventListener.class, listener); + } + + public void removeCreateFeatureTypeEventListener(CreateFeatureTypeEventListener listener) + { + listenerList.remove(CreateFeatureTypeEventListener.class, listener); + } + + protected void fireFeatureTypeEvent(FeatureTypeEvent evt) + { + Object[] listeners = listenerList.getListenerList(); + for (int i = 0; i < listeners.length; i += 2) + { + if (listeners[i] == CreateFeatureTypeEventListener.class) + { + ((CreateFeatureTypeEventListener) listeners[i + 1]).createFeatureTypeOccurred(evt); + } + } + } } diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateSymbolStrategy.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateSymbolStrategy.java index 6e08a86..78604d0 100644 --- a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateSymbolStrategy.java +++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateSymbolStrategy.java @@ -5,6 +5,8 @@ import java.util.List; import java.util.TreeMap; +import javax.swing.event.EventListenerList; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.geotools.feature.Feature; @@ -29,6 +31,9 @@ GeometryFactory geometryFactory = new GeometryFactory(); TreeMap<String, FeatureTypeBuilder> typeBuilders = new TreeMap<String, FeatureTypeBuilder>(); TWD97GeometryConverterDecorator convertDecorator = new TWD97GeometryConverterDecorator(); + + // Create the listener list + protected EventListenerList listenerList = new EventListenerList(); public CreateSymbolStrategy() { @@ -56,6 +61,7 @@ { FeatureTypeBuilder typeBuilder = FeatureTypeBuilderUtil.createSymbolFeatureTypeBuilder(featureName); typeBuilders.put(featureName, typeBuilder); + fireFeatureTypeEvent(new FeatureTypeEvent(this, typeBuilder.getFeatureType())); } return typeBuilders.get(featureName).getFeatureType(); } @@ -107,5 +113,28 @@ } return feature; } + + + public void addCreateFeatureTypeEventListener(CreateFeatureTypeEventListener listener) + { + listenerList.add(CreateFeatureTypeEventListener.class, listener); + } + + public void removeCreateFeatureTypeEventListener(CreateFeatureTypeEventListener listener) + { + listenerList.remove(CreateFeatureTypeEventListener.class, listener); + } + + protected void fireFeatureTypeEvent(FeatureTypeEvent evt) + { + Object[] listeners = listenerList.getListenerList(); + for (int i = 0; i < listeners.length; i += 2) + { + if (listeners[i] == CreateFeatureTypeEventListener.class) + { + ((CreateFeatureTypeEventListener) listeners[i + 1]).createFeatureTypeOccurred(evt); + } + } + } } diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateTextStrategy.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateTextStrategy.java index a8ba4c8..238eeda 100644 --- a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateTextStrategy.java +++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/CreateTextStrategy.java @@ -4,6 +4,7 @@ import java.math.RoundingMode; import java.util.List; import java.util.TreeMap; +import javax.swing.event.EventListenerList; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -31,6 +32,9 @@ TreeMap<String, FeatureTypeBuilder> typeBuilders = new TreeMap<String, FeatureTypeBuilder>(); TWD97GeometryConverterDecorator convertDecorator = new TWD97GeometryConverterDecorator(); + // Create the listener list + protected EventListenerList listenerList = new EventListenerList(); + public CreateTextStrategy() { } @@ -57,6 +61,7 @@ { FeatureTypeBuilder typeBuilder = FeatureTypeBuilderUtil.createPointFeatureTypeBuilder(featureName); typeBuilders.put(featureName, typeBuilder); + fireFeatureTypeEvent(new FeatureTypeEvent(this, typeBuilder.getFeatureType())); } return typeBuilders.get(featureName).getFeatureType(); } @@ -73,6 +78,8 @@ double angle = txtElement.getRotationAngle(); angle = BigDecimal.valueOf(angle).setScale(3, RoundingMode.HALF_UP).doubleValue(); convertDecorator.setConverter(txtElement); + String content = txtElement.getText(); + content = content.replace('\u0000', ' '); feature = featureType.create(new Object[]{ convertDecorator.toGeometry(geometryFactory), fLinkage.getFsc(), @@ -87,7 +94,7 @@ (float) txtElement.getTextHeight(), (float) txtElement.getTextWidth(), (float) angle, - txtElement.getText() + content }); } else if (element instanceof TextNodeElement) { @@ -98,7 +105,8 @@ { if (sb.length() != 0) sb.append("\n"); - sb.append(text); + String content = text.replace('\u0000', ' '); + sb.append(content); } double angle = nodeElement.getRotationAngle(); @@ -123,4 +131,26 @@ } return feature; } + + public void addCreateFeatureTypeEventListener(CreateFeatureTypeEventListener listener) + { + listenerList.add(CreateFeatureTypeEventListener.class, listener); + } + + public void removeCreateFeatureTypeEventListener(CreateFeatureTypeEventListener listener) + { + listenerList.remove(CreateFeatureTypeEventListener.class, listener); + } + + protected void fireFeatureTypeEvent(FeatureTypeEvent evt) + { + Object[] listeners = listenerList.getListenerList(); + for (int i = 0; i < listeners.length; i += 2) + { + if (listeners[i] == CreateFeatureTypeEventListener.class) + { + ((CreateFeatureTypeEventListener) listeners[i + 1]).createFeatureTypeOccurred(evt); + } + } + } } diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/FeatureTypeEvent.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/FeatureTypeEvent.java new file mode 100644 index 0000000..c821382 --- /dev/null +++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/FeatureTypeEvent.java @@ -0,0 +1,28 @@ +package com.ximple.eofms.filter; + +import java.util.EventObject; + +import org.geotools.feature.FeatureType; + +public class FeatureTypeEvent extends EventObject +{ + private FeatureType featureType; + + /** + * Constructs a prototypical Event. + * + * @param source The object on which the Event initially occurred. + * @param featureType featureType + * @throws IllegalArgumentException if source is null. + */ + public FeatureTypeEvent(Object source, FeatureType featureType) + { + super(source); + this.featureType = featureType; + } + + public FeatureType getFeatureType() + { + return featureType; + } +} diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/TypeCompIdDispatchableFilter.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/TypeCompIdDispatchableFilter.java index 7c8ea7a..83c9651 100644 --- a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/TypeCompIdDispatchableFilter.java +++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/TypeCompIdDispatchableFilter.java @@ -9,6 +9,7 @@ import com.ximple.io.dgn7.FrammeAttributeData; public class TypeCompIdDispatchableFilter extends AbstractFLinkageDispatchableFilter + implements CreateFeatureTypeEventListener { private int tid; private int cid; @@ -27,6 +28,7 @@ this.tid = tid; this.cid = compid; this.createStrategy = createStrategy; + this.createStrategy.addCreateFeatureTypeEventListener(this); } public int getTid() @@ -111,4 +113,9 @@ } return sb.toString(); } + + public void createFeatureTypeOccurred(FeatureTypeEvent evt) + { + fireFeatureTypeEvent(evt); + } } diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/TypeCompLevelIdDispatchableFilter.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/TypeCompLevelIdDispatchableFilter.java index df378c7..2956b46 100644 --- a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/TypeCompLevelIdDispatchableFilter.java +++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/TypeCompLevelIdDispatchableFilter.java @@ -9,6 +9,7 @@ import com.ximple.io.dgn7.FrammeAttributeData; public class TypeCompLevelIdDispatchableFilter extends AbstractFLinkageDispatchableFilter + implements CreateFeatureTypeEventListener { private int tid; private int cid; @@ -29,6 +30,7 @@ this.cid = compid; this.lid = level; this.createStrategy = createStrategy; + this.createStrategy.addCreateFeatureTypeEventListener(this); } public int getTid() @@ -120,4 +122,9 @@ } return sb.toString(); } + + public void createFeatureTypeOccurred(FeatureTypeEvent evt) + { + fireFeatureTypeEvent(evt); + } } diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/TypeIdDispatchableFilter.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/TypeIdDispatchableFilter.java index 465bdc8..fd25d05 100644 --- a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/TypeIdDispatchableFilter.java +++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/filter/TypeIdDispatchableFilter.java @@ -8,7 +8,7 @@ import com.ximple.io.dgn7.Element; import com.ximple.io.dgn7.FrammeAttributeData; -public class TypeIdDispatchableFilter extends AbstractFLinkageDispatchableFilter +public class TypeIdDispatchableFilter extends AbstractFLinkageDispatchableFilter implements CreateFeatureTypeEventListener { private int tid; private CreateFeatureTypeStrategy createStrategy; @@ -24,6 +24,7 @@ this.setName(fname); this.tid = tid; this.createStrategy = createStrategy; + this.createStrategy.addCreateFeatureTypeEventListener(this); } public int getTid() @@ -93,4 +94,9 @@ } return sb.toString(); } + + public void createFeatureTypeOccurred(FeatureTypeEvent evt) + { + fireFeatureTypeEvent(evt); + } } diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2MySQLJob.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2MySQLJob.java index 2ed8406..1cd3c29 100644 --- a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2MySQLJob.java +++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2MySQLJob.java @@ -622,6 +622,7 @@ convertContext.setExecutionContext(context); String dgnPaths[] = StringUtils.splitToArray(dgnFile.toString(), File.separator); convertContext.setFilename(dgnPaths[dgnPaths.length - 1]); + convertContext.startTransaction(); FileInputStream fs = new FileInputStream(dgnFile); FileChannel fc = fs.getChannel(); @@ -754,6 +755,7 @@ convertContext.setExecutionContext(context); String dgnPaths[] = StringUtils.splitToArray(dgnFile.toString(), File.separator); convertContext.setFilename(dgnPaths[dgnPaths.length - 1]); + convertContext.startTransaction(); FileInputStream fs = new FileInputStream(dgnFile); FileChannel fc = fs.getChannel(); @@ -930,6 +932,7 @@ convertContext.setExecutionContext(context); String dgnPaths[] = StringUtils.splitToArray(dgnFile.toString(), File.separator); convertContext.setFilename(dgnPaths[dgnPaths.length - 1]); + convertContext.startTransaction(); FileInputStream fs = new FileInputStream(dgnFile); FileChannel fc = fs.getChannel(); diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2OraSDOJob.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2OraSDOJob.java index fba160a..e22cdb6 100644 --- a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2OraSDOJob.java +++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2OraSDOJob.java @@ -201,8 +201,7 @@ throw new JobExecutionException("Cannot connect source postgreSQL database."); } - Calendar cal = Calendar.getInstance(); - Date startTime = cal.getTime(); + long t1 = System.currentTimeMillis(); try { logger.info("-- step:clearOutputDatabase --"); @@ -255,11 +254,10 @@ } disconnect(); - Date endTime = cal.getTime(); - Date time = new Date(endTime.getTime() - startTime.getTime()); + long t2 = System.currentTimeMillis(); // public static final String DATE_FORMAT_NOW = "yyyy-MM-dd HH:mm:ss"; // SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_NOW); - logger.warn("use time = " + time); + logger.warn("use time = " + ((t2 - t1) / 60000.0) + " min"); } catch (SQLException e) { logger.warn(e.getMessage(), e); @@ -624,6 +622,7 @@ convertContext.setExecutionContext(context); String dgnPaths[] = StringUtils.splitToArray(dgnFile.toString(), File.separator); convertContext.setFilename(dgnPaths[dgnPaths.length - 1]); + convertContext.startTransaction(); FileInputStream fs = new FileInputStream(dgnFile); FileChannel fc = fs.getChannel(); @@ -756,6 +755,7 @@ convertContext.setExecutionContext(context); String dgnPaths[] = StringUtils.splitToArray(dgnFile.toString(), File.separator); convertContext.setFilename(dgnPaths[dgnPaths.length - 1]); + convertContext.startTransaction(); FileInputStream fs = new FileInputStream(dgnFile); FileChannel fc = fs.getChannel(); @@ -932,6 +932,7 @@ convertContext.setExecutionContext(context); String dgnPaths[] = StringUtils.splitToArray(dgnFile.toString(), File.separator); convertContext.setFilename(dgnPaths[dgnPaths.length - 1]); + convertContext.startTransaction(); FileInputStream fs = new FileInputStream(dgnFile); FileChannel fc = fs.getChannel(); diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2PostGISJob.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2PostGISJob.java index d7dbdf7..99bfa96 100644 --- a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2PostGISJob.java +++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2PostGISJob.java @@ -71,7 +71,6 @@ private static final String USEWKB = "USEWKB"; private static final int FETCHSIZE = 30; - private static final int BATCHSIZE = 25; private static final int COMMITSIZE = 20; class Pair @@ -231,8 +230,7 @@ throw new JobExecutionException("Cannot connect source postgreSQL database."); } - Calendar cal = Calendar.getInstance(); - Date startTime = cal.getTime(); + long t1 = System.currentTimeMillis(); try { logger.info("-- step:clearOutputDatabase --"); @@ -285,11 +283,11 @@ } disconnect(); - Date endTime = cal.getTime(); - Date time = new Date(endTime.getTime() - startTime.getTime()); + long t2 = System.currentTimeMillis(); // public static final String DATE_FORMAT_NOW = "yyyy-MM-dd HH:mm:ss"; // SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_NOW); - logger.warn("use time = " + time); + logger.warn("use time = " + ((int) ((t2 - t1) / 60000.0)) + " min - " + + (((int) ((t2 - t1) % 60000.0)) / 1000) + " sec"); } catch (SQLException e) { logger.warn(e.getMessage(), e); @@ -651,9 +649,11 @@ logger.debug("--- start dgnfile-" + dgnFile.toString() + " ---"); try { + convertContext.clearOutputDatabase(); convertContext.setExecutionContext(context); String dgnPaths[] = StringUtils.splitToArray(dgnFile.toString(), File.separator); convertContext.setFilename(dgnPaths[dgnPaths.length - 1]); + convertContext.startTransaction(); FileInputStream fs = new FileInputStream(dgnFile); FileChannel fc = fs.getChannel(); @@ -786,6 +786,7 @@ convertContext.setExecutionContext(context); String dgnPaths[] = StringUtils.splitToArray(dgnFile.toString(), File.separator); convertContext.setFilename(dgnPaths[dgnPaths.length - 1]); + convertContext.startTransaction(); FileInputStream fs = new FileInputStream(dgnFile); FileChannel fc = fs.getChannel(); @@ -962,6 +963,7 @@ convertContext.setExecutionContext(context); String dgnPaths[] = StringUtils.splitToArray(dgnFile.toString(), File.separator); convertContext.setFilename(dgnPaths[dgnPaths.length - 1]); + convertContext.startTransaction(); FileInputStream fs = new FileInputStream(dgnFile); FileChannel fc = fs.getChannel(); @@ -1089,7 +1091,7 @@ if (!pgProperties.containsKey(PostgisDataStoreFactory.MAXCONN.key)) { - pgProperties.put(PostgisDataStoreFactory.MAXCONN.key, "2"); + pgProperties.put(PostgisDataStoreFactory.MAXCONN.key, "10"); } if (!pgProperties.containsKey(PostgisDataStoreFactory.MINCONN.key)) @@ -1116,4 +1118,5 @@ throw new JobExecutionException(e.getMessage(), e); } } + } diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2ShpJob.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2ShpJob.java index b14ab22..ee488c5 100644 --- a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2ShpJob.java +++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2ShpJob.java @@ -523,6 +523,7 @@ convertContext.setExecutionContext(context); String dgnPaths[] = StringUtils.splitToArray(dgnFile.toString(), File.separator); convertContext.setFilename(dgnPaths[dgnPaths.length - 1]); + convertContext.startTransaction(); FileInputStream fs = new FileInputStream(dgnFile); FileChannel fc = fs.getChannel(); @@ -653,6 +654,7 @@ convertContext.setExecutionContext(context); String dgnPaths[] = StringUtils.splitToArray(dgnFile.toString(), File.separator); convertContext.setFilename(dgnPaths[dgnPaths.length - 1]); + convertContext.startTransaction(); FileInputStream fs = new FileInputStream(dgnFile); FileChannel fc = fs.getChannel(); @@ -826,6 +828,7 @@ convertContext.setExecutionContext(context); String dgnPaths[] = StringUtils.splitToArray(dgnFile.toString(), File.separator); convertContext.setFilename(dgnPaths[dgnPaths.length - 1]); + convertContext.startTransaction(); FileInputStream fs = new FileInputStream(dgnFile); FileChannel fc = fs.getChannel(); diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/context/postgis/AbstractDgnToPostGISJobContext.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/context/postgis/AbstractDgnToPostGISJobContext.java index 68aa3cc..ed63d2b 100644 --- a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/context/postgis/AbstractDgnToPostGISJobContext.java +++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/context/postgis/AbstractDgnToPostGISJobContext.java @@ -1,24 +1,133 @@ package com.ximple.eofms.jobs.context.postgis; import java.io.IOException; +import java.math.BigDecimal; import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import org.geotools.data.DataSourceException; import org.geotools.data.DataStore; -import org.geotools.data.Transaction; import org.geotools.data.SchemaNotFoundException; +import org.geotools.data.Transaction; +import org.geotools.data.jdbc.JDBCUtils; import org.geotools.data.postgis.PostgisDataStore; +import org.geotools.feature.AttributeType; +import org.geotools.feature.Feature; import org.geotools.feature.FeatureType; +import org.geotools.feature.GeometryAttributeType; +import org.geotools.filter.LengthFunction; +import org.geotools.referencing.NamedIdentifier; +import org.geotools.referencing.crs.DefaultGeographicCRS; +import org.opengis.filter.BinaryComparisonOperator; +import org.opengis.filter.Filter; +import org.opengis.filter.PropertyIsLessThan; +import org.opengis.filter.PropertyIsLessThanOrEqualTo; +import org.opengis.filter.expression.Literal; +import org.opengis.referencing.crs.CoordinateReferenceSystem; + +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.GeometryCollection; +import com.vividsolutions.jts.geom.LineString; +import com.vividsolutions.jts.geom.MultiLineString; +import com.vividsolutions.jts.geom.MultiPoint; +import com.vividsolutions.jts.geom.MultiPolygon; +import com.vividsolutions.jts.geom.Point; +import com.vividsolutions.jts.geom.Polygon; +import com.vividsolutions.jts.io.WKBWriter; +import com.vividsolutions.jts.io.WKTWriter; import com.ximple.eofms.jobs.context.AbstractDgnFileJobContext; public abstract class AbstractDgnToPostGISJobContext extends AbstractDgnFileJobContext { + private static Map<String, Class> GEOM_TYPE_MAP = new HashMap<String, Class>(); + + static + { + GEOM_TYPE_MAP.put("GEOMETRY", Geometry.class); + GEOM_TYPE_MAP.put("POINT", Point.class); + GEOM_TYPE_MAP.put("POINTM", Point.class); + GEOM_TYPE_MAP.put("LINESTRING", LineString.class); + GEOM_TYPE_MAP.put("LINESTRINGM", LineString.class); + GEOM_TYPE_MAP.put("POLYGON", Polygon.class); + GEOM_TYPE_MAP.put("POLYGONM", Polygon.class); + GEOM_TYPE_MAP.put("MULTIPOINT", MultiPoint.class); + GEOM_TYPE_MAP.put("MULTIPOINTM", MultiPoint.class); + GEOM_TYPE_MAP.put("MULTILINESTRING", MultiLineString.class); + GEOM_TYPE_MAP.put("MULTILINESTRINGM", MultiLineString.class); + GEOM_TYPE_MAP.put("MULTIPOLYGON", MultiPolygon.class); + GEOM_TYPE_MAP.put("MULTIPOLYGONM", MultiPolygon.class); + GEOM_TYPE_MAP.put("GEOMETRYCOLLECTION", GeometryCollection.class); + GEOM_TYPE_MAP.put("GEOMETRYCOLLECTIONM", GeometryCollection.class); + } + + private static Map<Class, String> CLASS_MAPPINGS = new HashMap<Class, String>(); + + static + { + CLASS_MAPPINGS.put(String.class, "VARCHAR"); + + CLASS_MAPPINGS.put(Boolean.class, "BOOLEAN"); + + CLASS_MAPPINGS.put(Short.class, "SMALLINT"); + CLASS_MAPPINGS.put(Integer.class, "INTEGER"); + CLASS_MAPPINGS.put(Long.class, "BIGINT"); + + CLASS_MAPPINGS.put(Float.class, "REAL"); + CLASS_MAPPINGS.put(Double.class, "DOUBLE PRECISION"); + + CLASS_MAPPINGS.put(BigDecimal.class, "DECIMAL"); + + CLASS_MAPPINGS.put(java.sql.Date.class, "DATE"); + CLASS_MAPPINGS.put(java.util.Date.class, "DATE"); + CLASS_MAPPINGS.put(java.sql.Time.class, "TIME"); + CLASS_MAPPINGS.put(java.sql.Timestamp.class, "TIMESTAMP"); + } + + private static Map<Class, String> GEOM_CLASS_MAPPINGS = new HashMap<Class, String>(); + + //why don't we just stick this in with the non-geom class mappings? + static + { + // init the inverse map + Set keys = GEOM_TYPE_MAP.keySet(); + + for (Object key : keys) + { + String name = (String) key; + Class geomClass = GEOM_TYPE_MAP.get(name); + GEOM_CLASS_MAPPINGS.put(geomClass, name); + } + } + + /** + * Maximum string size for postgres + */ + private static final int MAX_ALLOWED_VALUE = 10485760; + + protected static final int BATCHSIZE = 25; + + /** + * Well Known Text writer (from JTS). + */ + protected static WKTWriter geometryWriter = new WKTWriter(); + protected PostgisDataStore targetDataStore; + private Connection connection; + protected boolean schemaEnabled = true; public AbstractDgnToPostGISJobContext(String dataPath, DataStore targetDataStore) { super(dataPath); this.targetDataStore = (PostgisDataStore) targetDataStore; + this.connection = null; } public PostgisDataStore getTargetDataStore() @@ -33,26 +142,37 @@ public Connection getConnection() { + if (connection != null) return connection; + if (targetDataStore != null) { try { - return targetDataStore.getConnection(Transaction.AUTO_COMMIT); - } catch (IOException e) + connection = targetDataStore.getDataSource().getConnection(); + } catch (SQLException e) { getLogger().warn(e.getMessage(), e); + return null; } } - return null; + return connection; } + public void closeConnection() + { + if (connection == null) + { + JDBCUtils.close(connection, Transaction.AUTO_COMMIT, null); + connection = null; + } + } protected boolean isExistFeature(FeatureType featureType) { try { FeatureType existFeatureType = targetDataStore.getSchema(featureType.getTypeName()); - return existFeatureType != null && existFeatureType.equals(featureType); + return existFeatureType != null; // && existFeatureType.equals(featureType); } catch (SchemaNotFoundException e) { return false; @@ -62,4 +182,594 @@ return false; } } + + protected void deleteTable(Connection conn, String tableName) throws SQLException + { + Statement stmt = conn.createStatement(); + StringBuilder sb = new StringBuilder(); + sb.append("DELETE FROM \""); + sb.append(targetDataStore.getDatabaseSchemaName()); + sb.append("\".\""); + sb.append(tableName); + sb.append('\"'); + getLogger().info("Execute-" + sb.toString()); + stmt.execute(sb.toString()); + stmt.close(); + conn.commit(); + } + + protected void dropTable(Connection conn, String tableName) throws SQLException + { + Statement stmt = conn.createStatement(); + StringBuilder sb = new StringBuilder(); + sb.append("DROP TABLE \""); + sb.append(targetDataStore.getDatabaseSchemaName()); + sb.append("\".\""); + sb.append(tableName); + sb.append("\" CASCADE"); + getLogger().info("Execute-" + sb.toString()); + stmt.execute(sb.toString()); + stmt.close(); + conn.commit(); + } + + protected void dropGeometryColumn(Connection conn, String tableName, String geomField) throws SQLException + { + Statement stmt = conn.createStatement(); + StringBuilder sb = new StringBuilder(); + sb.append("SELECT DropGeometryColumn('','"); + sb.append(tableName); + sb.append("','"); + sb.append(geomField); + sb.append("')"); + getLogger().info("Execute-" + sb.toString()); + stmt.execute(sb.toString()); + stmt.close(); + conn.commit(); + } + + public ArrayList<String> createSchemaTexts(FeatureType featureType) throws IOException + { + String tableName = featureType.getTypeName(); + + // String lcTableName = tableName.toLowerCase(); + ArrayList<String> result = new ArrayList<String>(); + + AttributeType[] attributeType = featureType.getAttributeTypes(); + String dbSchema = targetDataStore.getDatabaseSchemaName(); + + Connection con = getConnection(); + + boolean shouldExecute = !tablePresent(tableName, con); + + try + { + StringBuffer sql = new StringBuffer("CREATE TABLE "); + sql.append(encodeSchemaTableName(tableName)); + sql.append(" ("); + sql.append(makeSqlCreate(attributeType)); + sql.append(");"); + + String sqlStr = sql.toString(); + getLogger().info(sqlStr); + + if (shouldExecute) + { + result.add(sqlStr); + } + + //fix from pr: it may be that table existed and then was dropped + //without removing its geometry info from GEOMETRY_COLUMNS. + //To support this, try to delete before inserting. + //Preserving case for table names gives problems, + //so convert to lower case + + sql = new StringBuffer("DELETE FROM GEOMETRY_COLUMNS WHERE f_table_catalog=''"); + sql.append(" AND f_table_schema = '"); + sql.append(dbSchema); + sql.append("'"); + sql.append("AND f_table_name = '"); + sql.append(tableName); + sql.append("';"); + + //prints statement for later reuse + sqlStr = sql.toString(); + getLogger().info(sqlStr); + + if (shouldExecute) + { + result.add(sqlStr); + } + + //Ok, so Paolo Rizzi suggested that we get rid of our hand-adding + //of geometry column information and use AddGeometryColumn instead + //as it is better (this is in GEOT-379, he attached an extended + //datastore that does postgis fixes). But I am pretty positive + //the reason we are doing things this way is to preserve the order + //of FeatureTypes. I know this is fairly silly, from most + //information perspectives, but from another perspective it seems + //to make sense - if you were transfering a featureType from one + //data store to another then it should have the same order, right? + //And order is important in WFS. There are a few caveats though + //for one I don't even know if things work right. I imagine the + //proper constraints that a AddGeometryColumn operation does are + //not set in our hand version, for one. I would feel better about + //ignoring the order and just doing things as we like if we had + //views in place, if users could add the schema, and then be able + //to get it back in exactly the order they wanted. So for now + //let's leave things as is, and maybe talk about it in an irc. -ch + for (AttributeType anAttributeType : attributeType) + { + if (!(anAttributeType instanceof GeometryAttributeType)) + { + continue; + } + GeometryAttributeType geomAttribute = (GeometryAttributeType) anAttributeType; + String columnName = anAttributeType.getLocalName(); + + CoordinateReferenceSystem refSys = geomAttribute + .getCoordinateSystem(); + int SRID; + + if (refSys != null) + { + try + { + Set ident = refSys.getIdentifiers(); + if ((ident == null || ident.isEmpty()) && refSys == DefaultGeographicCRS.WGS84) + { + SRID = 4326; + } else + { + String code = ((NamedIdentifier) ident.toArray()[0]).getCode(); + SRID = Integer.parseInt(code); + } + } catch (Exception e) + { + getLogger().warn("SRID could not be determined"); + SRID = -1; + } + } else + { + SRID = -1; + } + + String typeName; + + //this construct seems unnecessary, since we already would + //pass over if this wasn't a geometry... + Class type = geomAttribute.getType(); + + if (geomAttribute instanceof GeometryAttributeType) + { + typeName = getGeometrySQLTypeName(type); + } else + { + typeName = CLASS_MAPPINGS.get(type); + } + + if (typeName != null) + { + //add a row to the geometry_columns table + sql = new StringBuffer("INSERT INTO GEOMETRY_COLUMNS VALUES ("); + sql.append("'','"); + sql.append(dbSchema); + sql.append("','"); + sql.append(tableName); + sql.append("','"); + sql.append(columnName); + sql.append("',2,"); + sql.append(SRID); + sql.append(",'"); + sql.append(typeName); + sql.append("');"); + + sqlStr = sql.toString(); + getLogger().info(sqlStr); + + if (shouldExecute) + { + result.add(sqlStr); + } + + //add geometry constaints to the table + if (SRID > -1) + { + sql = new StringBuffer("ALTER TABLE "); + sql.append(encodeSchemaTableName(tableName)); + sql.append(" ADD CONSTRAINT enforce_srid_"); + sql.append(columnName); + sql.append(" CHECK (SRID("); + sql.append(encodeSchemaColumnName(columnName)); + sql.append(") = "); + sql.append(SRID); + sql.append(");"); + sqlStr = sql.toString(); + getLogger().info(sqlStr); + if (shouldExecute) + { + result.add(sqlStr); + } + } + + sql = new StringBuffer("ALTER TABLE "); + sql.append(encodeSchemaTableName(tableName)); + sql.append(" ADD CONSTRAINT enforce_dims_"); + sql.append(columnName); + sql.append(" CHECK (ndims("); + sql.append(encodeSchemaColumnName(columnName)); + sql.append(") = 2);"); + sqlStr = sql.toString(); + getLogger().info(sqlStr); + if (shouldExecute) + { + result.add(sqlStr); + } + + if (!typeName.equals("GEOMETRY")) + { + sql = new StringBuffer("ALTER TABLE "); + sql.append(encodeSchemaTableName(tableName)); + sql.append(" ADD CONSTRAINT enforce_geotype_"); + sql.append(columnName); + sql.append(" CHECK (geometrytype("); + sql.append(encodeSchemaColumnName(columnName)); + sql.append(") = '"); + sql.append(typeName); + sql.append("'::text OR "); + sql.append(encodeSchemaColumnName(columnName)); + sql.append(" IS NULL);"); + sqlStr = sql.toString(); + getLogger().info(sqlStr); + if (shouldExecute) + { + result.add(sqlStr); + } + } + + } else + { + getLogger().warn("Error: " + geomAttribute.getLocalName() + " unknown type!!!"); + } + + //also build a spatial index on each geometry column. + sql = new StringBuffer("CREATE INDEX spatial_"); + sql.append(tableName); + sql.append("_"); + sql.append(anAttributeType.getLocalName().toLowerCase()); + sql.append(" ON "); + sql.append(encodeSchemaTableName(tableName)); + sql.append(" USING GIST ("); + sql.append(encodeSchemaColumnName(anAttributeType.getLocalName())); + sql.append(");"); + + sqlStr = sql.toString(); + getLogger().info(sqlStr); + + if (shouldExecute) + { + result.add(sqlStr); + } + } + + con.commit(); + + } catch (SQLException e) + { + try + { + if (con != null) + { + con.rollback(); + } + } catch (SQLException sqle) + { + throw new IOException(sqle.getMessage()); + } + + throw (IOException) new IOException(e.getMessage()).initCause(e); + } finally + { + } + + if (!shouldExecute) + { + throw new IOException("The table " + tableName + " already exists."); + } + + return result; + } + + private boolean tablePresent(String table, Connection conn) throws IOException + { + final int TABLE_NAME_COL = 3; + + try + { + conn = getConnection(); + + DatabaseMetaData meta = conn.getMetaData(); + String[] tableType = {"TABLE"}; + ResultSet tables = meta.getTables(null, + targetDataStore.getDatabaseSchemaName(), "%", tableType); + + while (tables.next()) + { + String tableName = tables.getString(TABLE_NAME_COL); + + if (allowTable(tableName) && (tableName != null) + && (tableName.equalsIgnoreCase(table))) + { + return (true); + } + } + + return false; + } catch (SQLException sqlException) + { + // JDBCUtils.close(conn, Transaction.AUTO_COMMIT, sqlException); + // conn = null; + + String message = "Error querying database for list of tables:" + + sqlException.getMessage(); + throw new DataSourceException(message, sqlException); + } finally + { + // JDBCUtils.close(conn, Transaction.AUTO_COMMIT, null); + } + } + + protected boolean allowTable(String tablename) + { + if (tablename.equals("geometry_columns")) + { + return false; + } else if (tablename.startsWith("spatial_ref_sys")) + { + return false; + } + + //others? + return true; + } + + + private StringBuffer makeSqlCreate(AttributeType[] attributeType) + throws IOException + { + StringBuffer buf = new StringBuffer(""); + + for (AttributeType anAttributeType : attributeType) + { + String typeName; + typeName = CLASS_MAPPINGS.get(anAttributeType.getBinding()); + if (typeName == null) + typeName = GEOM_CLASS_MAPPINGS.get(anAttributeType.getBinding()); + + if (typeName != null) + { + if (anAttributeType instanceof GeometryAttributeType) + { + typeName = "GEOMETRY"; + } else if (typeName.equals("VARCHAR")) + { + int length = -1; + Filter f = anAttributeType.getRestriction(); + if (f != null && f != Filter.EXCLUDE && f != Filter.INCLUDE && + (f instanceof PropertyIsLessThan || f instanceof PropertyIsLessThanOrEqualTo)) + { + try + { + BinaryComparisonOperator cf = (BinaryComparisonOperator) f; + if (cf.getExpression1() instanceof LengthFunction) + { + length = Integer.parseInt(((Literal) cf.getExpression2()).getValue().toString()); + } else + { + if (cf.getExpression2() instanceof LengthFunction) + { + length = Integer.parseInt(((Literal) cf.getExpression1()).getValue().toString()); + } + } + } catch (NumberFormatException e) + { + length = 256; + } + } else + { + length = 256; + } + + if (length < 1) + { + getLogger().warn("FeatureType did not specify string length; defaulted to 256"); + length = 256; + } else if (length > MAX_ALLOWED_VALUE) + { + length = MAX_ALLOWED_VALUE; + } + typeName = typeName + "(" + length + ")"; + } + + if (!anAttributeType.isNillable()) + { + typeName = typeName + " NOT NULL"; + } + + //TODO review!!! Is toString() always OK??? + Object defaultValue = anAttributeType.createDefaultValue(); + + if (defaultValue != null) + { + typeName = typeName + " DEFAULT '" + + defaultValue.toString() + "'"; + } + + buf.append(" \"").append(anAttributeType.getLocalName()).append("\" ").append(typeName).append(","); + + } else + { + String msg; + if (anAttributeType == null) + { + msg = "AttributeType was null!"; + } else + { + msg = "Type '" + anAttributeType.getBinding() + "' not supported!"; + } + throw (new IOException(msg)); + } + } + + return buf.deleteCharAt(buf.length() - 1); + } + + private String getGeometrySQLTypeName(Class type) + { + String res = GEOM_CLASS_MAPPINGS.get(type); + + if (res == null) + { + throw new RuntimeException("Unknown type name for class " + type + + " please update GEOMETRY_MAPPINGS"); + } + + return res; + } + + protected String getGeometryInsertText(Geometry geom, int srid) // throws IOException + { + if (geom == null) + { + return "null"; + } + + if (targetDataStore.isWKBEnabled()) + { + //String wkb = WKBEncoder.encodeGeometryHex(geom); + String wkb = WKBWriter.bytesToHex(new WKBWriter().write(geom)); + + if (targetDataStore.isByteaWKB()) + { + return "setSRID('" + wkb + "'::geometry," + srid + ")"; + } else + { + return "GeomFromWKB('" + wkb + "', " + srid + ")"; + } + } + + String geoText = geometryWriter.write(geom); + + return "GeometryFromText('" + geoText + "', " + srid + ")"; + } + + protected String makeInsertSql(Feature feature, int srid) // throws IOException + { + FeatureType featureType = feature.getFeatureType(); + + String tableName = encodeSchemaTableName(featureType.getTypeName()); + AttributeType[] attributeTypes = featureType.getAttributeTypes(); + + String attrValue; + + StringBuffer statementSQL = new StringBuffer("INSERT INTO " + tableName + " ("); + + // encode insertion for attributes, but remember to avoid auto-increment ones, + // they may be included in the feature type as well + for (AttributeType attributeType : attributeTypes) + { + String attName = attributeType.getLocalName(); + + if (feature.getAttribute(attName) != null) + { + String colName = encodeSchemaColumnName(attName); + statementSQL.append(colName).append(","); + } + } + + statementSQL.setCharAt(statementSQL.length() - 1, ')'); + statementSQL.append(" VALUES ("); + + Object[] attributes = feature.getAttributes(null); + + for (int i = 0; i < attributeTypes.length; i++) + { + attrValue = null; + + if (attributeTypes[i] instanceof GeometryAttributeType) + { + // String geomName = attributeTypes[i].getLocalName(); + // int srid = ftInfo.getSRID(geomName); + Geometry geometry = (Geometry) attributes[i]; + + if (geometry == null) + { + attrValue = "NULL"; + } else + { + attrValue = getGeometryInsertText(geometry, srid); + } + } else + { + if (attributes[i] != null) + { + attrValue = addQuotes(attributes[i]); + } + } + + if (attrValue != null) + { + statementSQL.append(attrValue).append(","); + } + } + + statementSQL.setCharAt(statementSQL.length() - 1, ')'); + + return (statementSQL.toString()); + } + + protected String addQuotes(Object value) + { + String retString; + + if (value != null) + { + if (value instanceof Number) + { + retString = value.toString(); + } else + { + retString = "'" + doubleQuote(value) + "'"; + } + } else + { + retString = "null"; + } + + return retString; + } + + String doubleQuote(Object obj) + { + return obj.toString().replaceAll("'", "''"); + } + + protected String encodeName(String tableName) + { + return tableName; + } + + protected String encodeColumnName(String colName) + { + return encodeName(colName); + } + + public String encodeSchemaTableName(String tableName) { + return schemaEnabled ? ("\"" + targetDataStore.getDatabaseSchemaName() + "\".\"" + tableName + "\"") + : ("\"" + tableName + "\""); + } + + public String encodeSchemaColumnName(String columnName) { + return "\"" + columnName + "\""; + } } diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/context/postgis/AbstractOracleToPostGISJobContext.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/context/postgis/AbstractOracleToPostGISJobContext.java index 5cf53db..74dcd4d 100644 --- a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/context/postgis/AbstractOracleToPostGISJobContext.java +++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/context/postgis/AbstractOracleToPostGISJobContext.java @@ -2,18 +2,127 @@ import java.io.IOException; import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.util.Map; +import java.util.HashMap; +import java.util.Set; +import java.util.ArrayList; +import java.math.BigDecimal; import org.geotools.data.DataStore; import org.geotools.data.Transaction; import org.geotools.data.SchemaNotFoundException; +import org.geotools.data.DataSourceException; +import org.geotools.data.jdbc.JDBCUtils; import org.geotools.data.postgis.PostgisDataStore; import org.geotools.feature.FeatureType; +import org.geotools.feature.AttributeType; +import org.geotools.feature.GeometryAttributeType; +import org.geotools.feature.Feature; +import org.geotools.referencing.crs.DefaultGeographicCRS; +import org.geotools.referencing.NamedIdentifier; +import org.geotools.filter.LengthFunction; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.filter.Filter; +import org.opengis.filter.PropertyIsLessThan; +import org.opengis.filter.PropertyIsLessThanOrEqualTo; +import org.opengis.filter.BinaryComparisonOperator; +import org.opengis.filter.expression.Literal; + +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.Point; +import com.vividsolutions.jts.geom.LineString; +import com.vividsolutions.jts.geom.Polygon; +import com.vividsolutions.jts.geom.MultiPoint; +import com.vividsolutions.jts.geom.MultiLineString; +import com.vividsolutions.jts.geom.MultiPolygon; +import com.vividsolutions.jts.geom.GeometryCollection; +import com.vividsolutions.jts.io.WKTWriter; +import com.vividsolutions.jts.io.WKBWriter; import com.ximple.eofms.jobs.context.AbstractOracleJobContext; public abstract class AbstractOracleToPostGISJobContext extends AbstractOracleJobContext { + private static Map<String, Class> GEOM_TYPE_MAP = new HashMap<String, Class>(); + + static + { + GEOM_TYPE_MAP.put("GEOMETRY", Geometry.class); + GEOM_TYPE_MAP.put("POINT", Point.class); + GEOM_TYPE_MAP.put("POINTM", Point.class); + GEOM_TYPE_MAP.put("LINESTRING", LineString.class); + GEOM_TYPE_MAP.put("LINESTRINGM", LineString.class); + GEOM_TYPE_MAP.put("POLYGON", Polygon.class); + GEOM_TYPE_MAP.put("POLYGONM", Polygon.class); + GEOM_TYPE_MAP.put("MULTIPOINT", MultiPoint.class); + GEOM_TYPE_MAP.put("MULTIPOINTM", MultiPoint.class); + GEOM_TYPE_MAP.put("MULTILINESTRING", MultiLineString.class); + GEOM_TYPE_MAP.put("MULTILINESTRINGM", MultiLineString.class); + GEOM_TYPE_MAP.put("MULTIPOLYGON", MultiPolygon.class); + GEOM_TYPE_MAP.put("MULTIPOLYGONM", MultiPolygon.class); + GEOM_TYPE_MAP.put("GEOMETRYCOLLECTION", GeometryCollection.class); + GEOM_TYPE_MAP.put("GEOMETRYCOLLECTIONM", GeometryCollection.class); + } + + private static Map<Class, String> CLASS_MAPPINGS = new HashMap<Class, String>(); + + static + { + CLASS_MAPPINGS.put(String.class, "VARCHAR"); + + CLASS_MAPPINGS.put(Boolean.class, "BOOLEAN"); + + CLASS_MAPPINGS.put(Short.class, "SMALLINT"); + CLASS_MAPPINGS.put(Integer.class, "INTEGER"); + CLASS_MAPPINGS.put(Long.class, "BIGINT"); + + CLASS_MAPPINGS.put(Float.class, "REAL"); + CLASS_MAPPINGS.put(Double.class, "DOUBLE PRECISION"); + + CLASS_MAPPINGS.put(BigDecimal.class, "DECIMAL"); + + CLASS_MAPPINGS.put(java.sql.Date.class, "DATE"); + CLASS_MAPPINGS.put(java.util.Date.class, "DATE"); + CLASS_MAPPINGS.put(java.sql.Time.class, "TIME"); + CLASS_MAPPINGS.put(java.sql.Timestamp.class, "TIMESTAMP"); + } + + private static Map<Class, String> GEOM_CLASS_MAPPINGS = new HashMap<Class, String>(); + + //why don't we just stick this in with the non-geom class mappings? + static + { + // init the inverse map + Set keys = GEOM_TYPE_MAP.keySet(); + + for (Object key : keys) + { + String name = (String) key; + Class geomClass = GEOM_TYPE_MAP.get(name); + GEOM_CLASS_MAPPINGS.put(geomClass, name); + } + } + + /** + * Maximum string size for postgres + */ + private static final int MAX_ALLOWED_VALUE = 10485760; + + protected static final int BATCHSIZE = 25; + + /** + * Well Known Text writer (from JTS). + */ + protected static WKTWriter geometryWriter = new WKTWriter(); + protected PostgisDataStore targetDataStore; + + private Connection connection; + protected boolean schemaEnabled = true; public AbstractOracleToPostGISJobContext(String dataPath, DataStore targetDataStore) { @@ -39,26 +148,37 @@ public Connection getConnection() { + if (connection != null) return connection; + if (targetDataStore != null) { try { - return targetDataStore.getConnection(Transaction.AUTO_COMMIT); - } catch (IOException e) + connection = targetDataStore.getDataSource().getConnection(); + } catch (SQLException e) { getLogger().warn(e.getMessage(), e); + return null; } } - return null; + return connection; } + public void closeConnection() + { + if (connection == null) + { + JDBCUtils.close(connection, Transaction.AUTO_COMMIT, null); + connection = null; + } + } protected boolean isExistFeature(FeatureType featureType) { try { FeatureType existFeatureType = targetDataStore.getSchema(featureType.getTypeName()); - return existFeatureType != null && existFeatureType.equals(featureType); + return existFeatureType != null; // && existFeatureType.equals(featureType); } catch (SchemaNotFoundException e) { return false; @@ -68,4 +188,594 @@ return false; } } + + protected void deleteTable(Connection conn, String tableName) throws SQLException + { + Statement stmt = conn.createStatement(); + StringBuilder sb = new StringBuilder(); + sb.append("DELETE FROM \""); + sb.append(targetDataStore.getDatabaseSchemaName()); + sb.append("\".\""); + sb.append(tableName); + sb.append('\"'); + getLogger().info("Execute-" + sb.toString()); + stmt.execute(sb.toString()); + stmt.close(); + conn.commit(); + } + + protected void dropTable(Connection conn, String tableName) throws SQLException + { + Statement stmt = conn.createStatement(); + StringBuilder sb = new StringBuilder(); + sb.append("DROP TABLE \""); + sb.append(targetDataStore.getDatabaseSchemaName()); + sb.append("\".\""); + sb.append(tableName); + sb.append("\" CASCADE"); + getLogger().info("Execute-" + sb.toString()); + stmt.execute(sb.toString()); + stmt.close(); + conn.commit(); + } + + protected void dropGeometryColumn(Connection conn, String tableName, String geomField) throws SQLException + { + Statement stmt = conn.createStatement(); + StringBuilder sb = new StringBuilder(); + sb.append("SELECT DropGeometryColumn('','"); + sb.append(tableName); + sb.append("','"); + sb.append(geomField); + sb.append("')"); + getLogger().info("Execute-" + sb.toString()); + stmt.execute(sb.toString()); + stmt.close(); + conn.commit(); + } + + public ArrayList<String> createSchemaTexts(FeatureType featureType) throws IOException + { + String tableName = featureType.getTypeName(); + + // String lcTableName = tableName.toLowerCase(); + ArrayList<String> result = new ArrayList<String>(); + + AttributeType[] attributeType = featureType.getAttributeTypes(); + String dbSchema = targetDataStore.getDatabaseSchemaName(); + + Connection con = getConnection(); + + boolean shouldExecute = !tablePresent(tableName, con); + + try + { + StringBuffer sql = new StringBuffer("CREATE TABLE "); + sql.append(encodeSchemaTableName(tableName)); + sql.append(" ("); + sql.append(makeSqlCreate(attributeType)); + sql.append(");"); + + String sqlStr = sql.toString(); + getLogger().info(sqlStr); + + if (shouldExecute) + { + result.add(sqlStr); + } + + //fix from pr: it may be that table existed and then was dropped + //without removing its geometry info from GEOMETRY_COLUMNS. + //To support this, try to delete before inserting. + //Preserving case for table names gives problems, + //so convert to lower case + + sql = new StringBuffer("DELETE FROM GEOMETRY_COLUMNS WHERE f_table_catalog=''"); + sql.append(" AND f_table_schema = '"); + sql.append(dbSchema); + sql.append("'"); + sql.append("AND f_table_name = '"); + sql.append(tableName); + sql.append("';"); + + //prints statement for later reuse + sqlStr = sql.toString(); + getLogger().info(sqlStr); + + if (shouldExecute) + { + result.add(sqlStr); + } + + //Ok, so Paolo Rizzi suggested that we get rid of our hand-adding + //of geometry column information and use AddGeometryColumn instead + //as it is better (this is in GEOT-379, he attached an extended + //datastore that does postgis fixes). But I am pretty positive + //the reason we are doing things this way is to preserve the order + //of FeatureTypes. I know this is fairly silly, from most + //information perspectives, but from another perspective it seems + //to make sense - if you were transfering a featureType from one + //data store to another then it should have the same order, right? + //And order is important in WFS. There are a few caveats though + //for one I don't even know if things work right. I imagine the + //proper constraints that a AddGeometryColumn operation does are + //not set in our hand version, for one. I would feel better about + //ignoring the order and just doing things as we like if we had + //views in place, if users could add the schema, and then be able + //to get it back in exactly the order they wanted. So for now + //let's leave things as is, and maybe talk about it in an irc. -ch + for (AttributeType anAttributeType : attributeType) + { + if (!(anAttributeType instanceof GeometryAttributeType)) + { + continue; + } + GeometryAttributeType geomAttribute = (GeometryAttributeType) anAttributeType; + String columnName = anAttributeType.getLocalName(); + + CoordinateReferenceSystem refSys = geomAttribute + .getCoordinateSystem(); + int SRID; + + if (refSys != null) + { + try + { + Set ident = refSys.getIdentifiers(); + if ((ident == null || ident.isEmpty()) && refSys == DefaultGeographicCRS.WGS84) + { + SRID = 4326; + } else + { + String code = ((NamedIdentifier) ident.toArray()[0]).getCode(); + SRID = Integer.parseInt(code); + } + } catch (Exception e) + { + getLogger().warn("SRID could not be determined"); + SRID = -1; + } + } else + { + SRID = -1; + } + + String typeName; + + //this construct seems unnecessary, since we already would + //pass over if this wasn't a geometry... + Class type = geomAttribute.getType(); + + if (geomAttribute instanceof GeometryAttributeType) + { + typeName = getGeometrySQLTypeName(type); + } else + { + typeName = CLASS_MAPPINGS.get(type); + } + + if (typeName != null) + { + //add a row to the geometry_columns table + sql = new StringBuffer("INSERT INTO GEOMETRY_COLUMNS VALUES ("); + sql.append("'','"); + sql.append(dbSchema); + sql.append("','"); + sql.append(tableName); + sql.append("','"); + sql.append(columnName); + sql.append("',2,"); + sql.append(SRID); + sql.append(",'"); + sql.append(typeName); + sql.append("');"); + + sqlStr = sql.toString(); + getLogger().info(sqlStr); + + if (shouldExecute) + { + result.add(sqlStr); + } + + //add geometry constaints to the table + if (SRID > -1) + { + sql = new StringBuffer("ALTER TABLE "); + sql.append(encodeSchemaTableName(tableName)); + sql.append(" ADD CONSTRAINT enforce_srid_"); + sql.append(columnName); + sql.append(" CHECK (SRID("); + sql.append(encodeSchemaColumnName(columnName)); + sql.append(") = "); + sql.append(SRID); + sql.append(");"); + sqlStr = sql.toString(); + getLogger().info(sqlStr); + if (shouldExecute) + { + result.add(sqlStr); + } + } + + sql = new StringBuffer("ALTER TABLE "); + sql.append(encodeSchemaTableName(tableName)); + sql.append(" ADD CONSTRAINT enforce_dims_"); + sql.append(columnName); + sql.append(" CHECK (ndims("); + sql.append(encodeSchemaColumnName(columnName)); + sql.append(") = 2);"); + sqlStr = sql.toString(); + getLogger().info(sqlStr); + if (shouldExecute) + { + result.add(sqlStr); + } + + if (!typeName.equals("GEOMETRY")) + { + sql = new StringBuffer("ALTER TABLE "); + sql.append(encodeSchemaTableName(tableName)); + sql.append(" ADD CONSTRAINT enforce_geotype_"); + sql.append(columnName); + sql.append(" CHECK (geometrytype("); + sql.append(encodeSchemaColumnName(columnName)); + sql.append(") = '"); + sql.append(typeName); + sql.append("'::text OR "); + sql.append(encodeSchemaColumnName(columnName)); + sql.append(" IS NULL);"); + sqlStr = sql.toString(); + getLogger().info(sqlStr); + if (shouldExecute) + { + result.add(sqlStr); + } + } + + } else + { + getLogger().warn("Error: " + geomAttribute.getLocalName() + " unknown type!!!"); + } + + //also build a spatial index on each geometry column. + sql = new StringBuffer("CREATE INDEX spatial_"); + sql.append(tableName); + sql.append("_"); + sql.append(anAttributeType.getLocalName().toLowerCase()); + sql.append(" ON "); + sql.append(encodeSchemaTableName(tableName)); + sql.append(" USING GIST ("); + sql.append(encodeSchemaColumnName(anAttributeType.getLocalName())); + sql.append(");"); + + sqlStr = sql.toString(); + getLogger().info(sqlStr); + + if (shouldExecute) + { + result.add(sqlStr); + } + } + + con.commit(); + + } catch (SQLException e) + { + try + { + if (con != null) + { + con.rollback(); + } + } catch (SQLException sqle) + { + throw new IOException(sqle.getMessage()); + } + + throw (IOException) new IOException(e.getMessage()).initCause(e); + } finally + { + } + + if (!shouldExecute) + { + throw new IOException("The table " + tableName + " already exists."); + } + + return result; + } + + private boolean tablePresent(String table, Connection conn) throws IOException + { + final int TABLE_NAME_COL = 3; + + try + { + conn = getConnection(); + + DatabaseMetaData meta = conn.getMetaData(); + String[] tableType = {"TABLE"}; + ResultSet tables = meta.getTables(null, + targetDataStore.getDatabaseSchemaName(), "%", tableType); + + while (tables.next()) + { + String tableName = tables.getString(TABLE_NAME_COL); + + if (allowTable(tableName) && (tableName != null) + && (tableName.equalsIgnoreCase(table))) + { + return (true); + } + } + + return false; + } catch (SQLException sqlException) + { + // JDBCUtils.close(conn, Transaction.AUTO_COMMIT, sqlException); + // conn = null; + + String message = "Error querying database for list of tables:" + + sqlException.getMessage(); + throw new DataSourceException(message, sqlException); + } finally + { + // JDBCUtils.close(conn, Transaction.AUTO_COMMIT, null); + } + } + + protected boolean allowTable(String tablename) + { + if (tablename.equals("geometry_columns")) + { + return false; + } else if (tablename.startsWith("spatial_ref_sys")) + { + return false; + } + + //others? + return true; + } + + + private StringBuffer makeSqlCreate(AttributeType[] attributeType) + throws IOException + { + StringBuffer buf = new StringBuffer(""); + + for (AttributeType anAttributeType : attributeType) + { + String typeName; + typeName = CLASS_MAPPINGS.get(anAttributeType.getBinding()); + if (typeName == null) + typeName = GEOM_CLASS_MAPPINGS.get(anAttributeType.getBinding()); + + if (typeName != null) + { + if (anAttributeType instanceof GeometryAttributeType) + { + typeName = "GEOMETRY"; + } else if (typeName.equals("VARCHAR")) + { + int length = -1; + Filter f = anAttributeType.getRestriction(); + if (f != null && f != Filter.EXCLUDE && f != Filter.INCLUDE && + (f instanceof PropertyIsLessThan || f instanceof PropertyIsLessThanOrEqualTo)) + { + try + { + BinaryComparisonOperator cf = (BinaryComparisonOperator) f; + if (cf.getExpression1() instanceof LengthFunction) + { + length = Integer.parseInt(((Literal) cf.getExpression2()).getValue().toString()); + } else + { + if (cf.getExpression2() instanceof LengthFunction) + { + length = Integer.parseInt(((Literal) cf.getExpression1()).getValue().toString()); + } + } + } catch (NumberFormatException e) + { + length = 256; + } + } else + { + length = 256; + } + + if (length < 1) + { + getLogger().warn("FeatureType did not specify string length; defaulted to 256"); + length = 256; + } else if (length > MAX_ALLOWED_VALUE) + { + length = MAX_ALLOWED_VALUE; + } + typeName = typeName + "(" + length + ")"; + } + + if (!anAttributeType.isNillable()) + { + typeName = typeName + " NOT NULL"; + } + + //TODO review!!! Is toString() always OK??? + Object defaultValue = anAttributeType.createDefaultValue(); + + if (defaultValue != null) + { + typeName = typeName + " DEFAULT '" + + defaultValue.toString() + "'"; + } + + buf.append(" \"").append(anAttributeType.getLocalName()).append("\" ").append(typeName).append(","); + + } else + { + String msg; + if (anAttributeType == null) + { + msg = "AttributeType was null!"; + } else + { + msg = "Type '" + anAttributeType.getBinding() + "' not supported!"; + } + throw (new IOException(msg)); + } + } + + return buf.deleteCharAt(buf.length() - 1); + } + + private String getGeometrySQLTypeName(Class type) + { + String res = GEOM_CLASS_MAPPINGS.get(type); + + if (res == null) + { + throw new RuntimeException("Unknown type name for class " + type + + " please update GEOMETRY_MAPPINGS"); + } + + return res; + } + + protected String getGeometryInsertText(Geometry geom, int srid) // throws IOException + { + if (geom == null) + { + return "null"; + } + + if (targetDataStore.isWKBEnabled()) + { + //String wkb = WKBEncoder.encodeGeometryHex(geom); + String wkb = WKBWriter.bytesToHex(new WKBWriter().write(geom)); + + if (targetDataStore.isByteaWKB()) + { + return "setSRID('" + wkb + "'::geometry," + srid + ")"; + } else + { + return "GeomFromWKB('" + wkb + "', " + srid + ")"; + } + } + + String geoText = geometryWriter.write(geom); + + return "GeometryFromText('" + geoText + "', " + srid + ")"; + } + + protected String makeInsertSql(Feature feature, int srid) // throws IOException + { + FeatureType featureType = feature.getFeatureType(); + + String tableName = encodeSchemaTableName(featureType.getTypeName()); + AttributeType[] attributeTypes = featureType.getAttributeTypes(); + + String attrValue; + + StringBuffer statementSQL = new StringBuffer("INSERT INTO " + tableName + " ("); + + // encode insertion for attributes, but remember to avoid auto-increment ones, + // they may be included in the feature type as well + for (AttributeType attributeType : attributeTypes) + { + String attName = attributeType.getLocalName(); + + if (feature.getAttribute(attName) != null) + { + String colName = encodeSchemaColumnName(attName); + statementSQL.append(colName).append(","); + } + } + + statementSQL.setCharAt(statementSQL.length() - 1, ')'); + statementSQL.append(" VALUES ("); + + Object[] attributes = feature.getAttributes(null); + + for (int i = 0; i < attributeTypes.length; i++) + { + attrValue = null; + + if (attributeTypes[i] instanceof GeometryAttributeType) + { + // String geomName = attributeTypes[i].getLocalName(); + // int srid = ftInfo.getSRID(geomName); + Geometry geometry = (Geometry) attributes[i]; + + if (geometry == null) + { + attrValue = "NULL"; + } else + { + attrValue = getGeometryInsertText(geometry, srid); + } + } else + { + if (attributes[i] != null) + { + attrValue = addQuotes(attributes[i]); + } + } + + if (attrValue != null) + { + statementSQL.append(attrValue).append(","); + } + } + + statementSQL.setCharAt(statementSQL.length() - 1, ')'); + + return (statementSQL.toString()); + } + + protected String addQuotes(Object value) + { + String retString; + + if (value != null) + { + if (value instanceof Number) + { + retString = value.toString(); + } else + { + retString = "'" + doubleQuote(value) + "'"; + } + } else + { + retString = "null"; + } + + return retString; + } + + String doubleQuote(Object obj) + { + return obj.toString().replaceAll("'", "''"); + } + + protected String encodeName(String tableName) + { + return tableName; + } + + protected String encodeColumnName(String colName) + { + return encodeName(colName); + } + + public String encodeSchemaTableName(String tableName) { + return schemaEnabled ? ("\"" + targetDataStore.getDatabaseSchemaName() + "\".\"" + tableName + "\"") + : ("\"" + tableName + "\""); + } + + public String encodeSchemaColumnName(String columnName) { + return "\"" + columnName + "\""; + } } diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/context/postgis/GeneralDgnConvertPostGISJobContext.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/context/postgis/GeneralDgnConvertPostGISJobContext.java index 44bad78..e04d2e4 100644 --- a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/context/postgis/GeneralDgnConvertPostGISJobContext.java +++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/context/postgis/GeneralDgnConvertPostGISJobContext.java @@ -9,6 +9,9 @@ import java.util.Iterator; import java.util.List; import java.util.TreeMap; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -18,12 +21,18 @@ import org.geotools.data.DataStore; import org.geotools.data.FeatureWriter; import org.geotools.data.Transaction; +import org.geotools.data.DefaultTransaction; +import org.geotools.data.DataSourceException; +import org.geotools.data.FeatureStore; import org.geotools.feature.Feature; 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.geotools.feature.FeatureCollection; +import org.geotools.feature.FeatureCollections; +import org.postgresql.util.PSQLException; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; @@ -49,23 +58,18 @@ static final LoggerFacade sLogger = new CommonsLoggingLogger(logger); static final GeometryFactory geometryFactory = new GeometryFactory(); - private String dataOut = null; + private HashMap<FeatureType, ArrayList<String>> txFeaturesContext = new HashMap<FeatureType, ArrayList<String>>(); - private HashMap<String, ArrayList<Feature>> featuresContext = new HashMap<String, ArrayList<Feature>>(); - private HashMap<String, FeatureWriter> featuresWriterContext = new HashMap<String, FeatureWriter>(); - - private PessimisticMapWrapper txFeaturesContext; private TreeMap<String, FeatureTypeBuilder> typeBuilders = new TreeMap<String, FeatureTypeBuilder>(); private TreeMap<String, FeatureType> featureTypes = new TreeMap<String, FeatureType>(); private TWD97GeometryConverterDecorator convertDecorator = null; private String featureBaseName = null; - private boolean withIndex = false; + private boolean dropTableMode = true; public GeneralDgnConvertPostGISJobContext(String dataPath, DataStore targetDataStore) { super(dataPath, targetDataStore); - txFeaturesContext = new PessimisticMapWrapper(featuresContext, sLogger); convertDecorator = new TWD97GeometryConverterDecorator(); } @@ -98,15 +102,18 @@ if (!txFeaturesContext.containsKey(feature.getFeatureType())) { - txFeaturesContext.put(feature.getFeatureType(), new ArrayList<Feature>()); + txFeaturesContext.put(feature.getFeatureType(), new ArrayList<String>()); } - ArrayList<Feature> arrayList = (ArrayList<Feature>) txFeaturesContext.get(feature.getFeatureType()); - arrayList.add(feature); + ArrayList<String> arrayList = txFeaturesContext.get(feature.getFeatureType()); + if (feature.getDefaultGeometry() != null && !feature.getDefaultGeometry().isEmpty()) + arrayList.add(makeInsertSql(feature, -1)); } else { logger.info("Unknown Element :" + element.getType() + ", lv=" + element.getLevelIndex()); } } + + private Transaction transaction; public void startTransaction() { @@ -123,69 +130,69 @@ logger.debug("Transaction is empty."); } - if (!featuresContext.isEmpty()) + if (!txFeaturesContext.isEmpty()) { updateDataStore(); } + + txFeaturesContext.clear(); } public void rollbackTransaction() { - //txFeaturesContext.rollbackTransaction(); - if (!featuresContext.isEmpty()) - { - updateDataStore(); - } + txFeaturesContext.clear(); } private void updateDataStore() { - Iterator it = featuresContext.keySet().iterator(); - + Iterator<FeatureType> it = txFeaturesContext.keySet().iterator(); + String currentStmt = null; try { while (it.hasNext()) { - FeatureType featureType = (FeatureType) it.next(); + FeatureType featureType = it.next(); logger.debug("Begin Save into PostGIS:" + featureType.getTypeName()); - FeatureWriter writer; - if (featuresWriterContext.containsKey(featureType.getTypeName())) + ArrayList<String> stmtTexts = txFeaturesContext.get(featureType); + Connection conn = getConnection(); + boolean autoCommit = conn.getAutoCommit(); + conn.setAutoCommit(true); + + for (String stmtText : stmtTexts) { - writer = featuresWriterContext.get(featureType.getTypeName()); - } else - { - if (!isExistFeature(featureType)) + currentStmt = stmtText; + Statement stmt = conn.createStatement(); + try { - targetDataStore.createSchema(featureType); - writer = targetDataStore.getFeatureWriter(featureType.getTypeName(), - Transaction.AUTO_COMMIT); - } else + stmt.execute(stmtText); + } catch (PSQLException e) { - writer = targetDataStore.getFeatureWriterAppend(featureType.getTypeName(), - Transaction.AUTO_COMMIT); + if (currentStmt != null) + { + logger.error("Execute:" + currentStmt); + } + logger.error(e.getServerErrorMessage()); + logger.error(e.getMessage(), e); + } finally { + stmt.close(); } - featuresWriterContext.put(featureType.getTypeName(), writer); + /* + if ((i % BATCHSIZE) != 0) + { + stmt.addBatch(stmtText); + } else { + stmt.addBatch(stmtText); + stmt.executeBatch(); + } + i++; + */ } - ArrayList<Feature> features = featuresContext.get(featureType); - Iterator itFeature = features.iterator(); - while (itFeature.hasNext()) - { - Feature feature = (Feature) itFeature.next(); - ((SimpleFeature) writer.next()).setAttributes(feature.getAttributes(null)); - } - //writer.close(); + conn.setAutoCommit(autoCommit); logger.debug("End Save into PostGIS:" + featureType.getTypeName()); } - featuresContext.clear(); - } catch (MalformedURLException e) - { - logger.error(e.getMessage(), e); - } catch (IllegalAttributeException e) - { - logger.error(e.getMessage(), e); - } catch (IOException e) + } catch (SQLException e) { logger.error(e.getMessage(), e); } @@ -193,13 +200,14 @@ public void closeFeatureWriter() throws IOException { - + /* for (FeatureWriter featureWriter : this.featuresWriterContext.values()) { featureWriter.close(); } this.featuresWriterContext.clear(); + */ } public FeatureType createPointFeatureElement(String featureName) throws SchemaException @@ -208,6 +216,7 @@ { FeatureTypeBuilder typeBuilder = FeatureTypeBuilderUtil.createNormalPointFeatureTypeBuilder(featureName); typeBuilders.put(featureName, typeBuilder); + clearFeatureData(typeBuilder); } return typeBuilders.get(featureName).getFeatureType(); } @@ -218,6 +227,7 @@ { FeatureTypeBuilder typeBuilder = FeatureTypeBuilderUtil.createNormalLineFeatureTypeBuilder(featureName); typeBuilders.put(featureName, typeBuilder); + clearFeatureData(typeBuilder); } return typeBuilders.get(featureName).getFeatureType(); } @@ -228,6 +238,7 @@ { FeatureTypeBuilder typeBuilder = FeatureTypeBuilderUtil.createNormalArcFeatureTypeBuilder(featureName); typeBuilders.put(featureName, typeBuilder); + clearFeatureData(typeBuilder); } return typeBuilders.get(featureName).getFeatureType(); } @@ -238,6 +249,7 @@ { FeatureTypeBuilder typeBuilder = FeatureTypeBuilderUtil.createNormalEllipseFeatureTypeBuilder(featureName); typeBuilders.put(featureName, typeBuilder); + clearFeatureData(typeBuilder); } return typeBuilders.get(featureName).getFeatureType(); } @@ -253,6 +265,7 @@ Geometry geom = convertDecorator.toGeometry(geometryFactory); double angle = textElement.getRotationAngle(); String content = textElement.getText(); + content = content.replace('\u0000', ' '); angle = BigDecimal.valueOf(angle).setScale(3, RoundingMode.HALF_UP).doubleValue(); if (geom != null) { @@ -285,7 +298,8 @@ { if (sb.length() != 0) sb.append("\n"); - sb.append(text); + String content = text.replace('\u0000', ' '); + sb.append(content); } if (geom != null) @@ -503,19 +517,73 @@ return null; } - - public boolean isWithIndex() - { - return withIndex; - } - - public void setWithIndex(boolean withIndex) - { - this.withIndex = withIndex; - } - public Log getLogger() { return logger; } + + public boolean isDropTableMode() + { + return dropTableMode; + } + + public void setDropTableMode(boolean dropTableMode) + { + this.dropTableMode = dropTableMode; + } + + protected void clearFeatureData(FeatureTypeBuilder typeBuilder) throws SchemaException + { + String featureName = typeBuilder.getName(); + if (isExistFeature(typeBuilder.getFeatureType())) + { + try + { + Connection conn = targetDataStore.getConnection(Transaction.AUTO_COMMIT); + if (dropTableMode) + { + dropGeometryColumn(conn, featureName, + typeBuilder.getFeatureType().getDefaultGeometry().getLocalName()); + dropTable(conn, featureName); + + ArrayList<String> schemaTexts = createSchemaTexts(typeBuilder.getFeatureType()); + for (String stmtText : schemaTexts) + { + Statement stmt = conn.createStatement(); + stmt.execute(stmtText); + stmt.close(); + } + } else { + deleteTable(conn, featureName); + } + conn.close(); + } catch (IOException e) + { + logger.warn(e.getMessage(), e); + } catch (SQLException e) + { + logger.warn(e.getMessage(), e); + } + } else + { + try + { + Connection conn = targetDataStore.getConnection(Transaction.AUTO_COMMIT); + ArrayList<String> schemaTexts = createSchemaTexts(typeBuilder.getFeatureType()); + for (String stmtText : schemaTexts) + { + Statement stmt = conn.createStatement(); + stmt.execute(stmtText); + stmt.close(); + } + conn.close(); + } catch (IOException e) + { + logger.warn(e.getMessage(), e); + } catch (SQLException e) + { + logger.warn(e.getMessage(), e); + } + } + } } diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/context/postgis/IndexDgnConvertPostGISJobContext.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/context/postgis/IndexDgnConvertPostGISJobContext.java index 7515934..0280990 100644 --- a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/context/postgis/IndexDgnConvertPostGISJobContext.java +++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/context/postgis/IndexDgnConvertPostGISJobContext.java @@ -3,7 +3,9 @@ import java.io.IOException; import java.math.BigDecimal; import java.math.RoundingMode; -import java.net.MalformedURLException; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -11,19 +13,16 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.commons.transaction.memory.PessimisticMapWrapper; import org.apache.commons.transaction.util.CommonsLoggingLogger; import org.apache.commons.transaction.util.LoggerFacade; import org.geotools.data.DataStore; -import org.geotools.data.FeatureWriter; import org.geotools.data.Transaction; -import org.geotools.data.DefaultTransaction; import org.geotools.feature.Feature; 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.postgresql.util.PSQLException; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Envelope; @@ -46,23 +45,19 @@ static final LoggerFacade sLogger = new CommonsLoggingLogger(logger); static final GeometryFactory geometryFactory = new GeometryFactory(); TWD97GeometryConverterDecorator convertDecorator = new TWD97GeometryConverterDecorator(); - public static final String SHPOUTPATH = "shpout"; - private String dataOut = null; + private HashMap<FeatureType, ArrayList<String>> txFeaturesContext = new HashMap<FeatureType, ArrayList<String>>(); - private HashMap<String, ArrayList<Feature>> featuresContext = new HashMap<String, ArrayList<Feature>>(); - private HashMap<String, FeatureWriter> featuresWriterContext = new HashMap<String, FeatureWriter>(); - - private PessimisticMapWrapper txFeaturesContext; private FeatureTypeBuilder typeBuilderPnt = null; private FeatureTypeBuilder typeBuilderRect = null; private FeatureType featureType = null; private FeatureType featureType2 = null; + private boolean dropTableMode = true; + public IndexDgnConvertPostGISJobContext(String dataPath, DataStore targetDataStore) { super(dataPath, targetDataStore); - txFeaturesContext = new PessimisticMapWrapper(featuresContext, sLogger); } public void putFeatureCollection(Element element) throws IllegalAttributeException, SchemaException @@ -82,10 +77,10 @@ if (!txFeaturesContext.containsKey(feature.getFeatureType())) { - txFeaturesContext.put(feature.getFeatureType(), new ArrayList()); + txFeaturesContext.put(feature.getFeatureType(), new ArrayList<String>()); } - ArrayList arrayList = (ArrayList) txFeaturesContext.get(feature.getFeatureType()); - arrayList.add(feature); + ArrayList<String> arrayList = txFeaturesContext.get(feature.getFeatureType()); + arrayList.add(makeInsertSql(feature, -1)); feature = createFeature2((TextElement) element); if (feature == null) @@ -97,18 +92,14 @@ if (!txFeaturesContext.containsKey(feature.getFeatureType())) { - txFeaturesContext.put(feature.getFeatureType(), new ArrayList()); + txFeaturesContext.put(feature.getFeatureType(), new ArrayList<String>()); } - arrayList = (ArrayList) txFeaturesContext.get(feature.getFeatureType()); - arrayList.add(feature); + arrayList = txFeaturesContext.get(feature.getFeatureType()); + arrayList.add(makeInsertSql(feature, -1)); } - - private Transaction transaction; public void startTransaction() { - if (transaction == null) - transaction = new DefaultTransaction(getClass().getName()); } public void commitTransaction() @@ -116,97 +107,91 @@ if (!txFeaturesContext.isEmpty()) { logger.debug("Transaction size = " + txFeaturesContext.size()); - //txFeaturesContext.commitTransaction(); } else { logger.debug("Transaction is empty."); } - if (!featuresContext.isEmpty()) + if (!txFeaturesContext.isEmpty()) { updateDataStore(); } - try - { - transaction.commit(); - transaction.close(); - } catch (IOException e) - { - logger.warn(e.getMessage(), e); - } finally - { - transaction = null; - } + txFeaturesContext.clear(); } public void rollbackTransaction() { - //txFeaturesContext.rollbackTransaction(); - if (!featuresContext.isEmpty()) - { - updateDataStore(); - } - - try - { - transaction.rollback(); - transaction.close(); - } catch (IOException e) - { - logger.warn(e.getMessage(), e); - } finally - { - transaction = null; - } + txFeaturesContext.clear(); } private void updateDataStore() { - Iterator it = featuresContext.keySet().iterator(); - + Iterator<FeatureType> it = txFeaturesContext.keySet().iterator(); + String currentStmt = null; try { while (it.hasNext()) { - FeatureType featureType = (FeatureType) it.next(); + FeatureType featureType = it.next(); logger.debug("Begin Save PostGIS:" + featureType.getTypeName()); - FeatureWriter writer; - if (featuresWriterContext.containsKey(featureType.getTypeName())) + ArrayList<String> stmtTexts = txFeaturesContext.get(featureType); + Connection conn = getConnection(); + boolean autoCommit = conn.getAutoCommit(); + conn.setAutoCommit(true); + // conn.setAutoCommit(false); + // Statement stmt = conn.createStatement(); + // int i = 0; + for (String stmtText : stmtTexts) { - writer = featuresWriterContext.get(featureType.getTypeName()); - } else - { - if (!isExistFeature(featureType)) + currentStmt = stmtText; + Statement stmt = conn.createStatement(); + try { - targetDataStore.createSchema(featureType); - writer = targetDataStore.getFeatureWriter(featureType.getTypeName(), Transaction.AUTO_COMMIT); - } else + stmt.execute(stmtText); + } catch (PSQLException e) { - writer = targetDataStore.getFeatureWriterAppend(featureType.getTypeName(), Transaction.AUTO_COMMIT); + if (currentStmt != null) + { + logger.error("Execute:" + currentStmt); + } + logger.error(e.getServerErrorMessage()); + logger.error(e.getMessage(), e); + } finally { + stmt.close(); } - featuresWriterContext.put(featureType.getTypeName(), writer); + /* + if ((i % BATCHSIZE) != 0) + { + stmt.addBatch(stmtText); + } else { + stmt.addBatch(stmtText); + stmt.executeBatch(); + } + i++; + */ } - - ArrayList<Feature> features = featuresContext.get(featureType); - for (Feature feature1 : features) + /* + if ((i % BATCHSIZE) != 0) { - ((SimpleFeature) writer.next()).setAttributes(feature1.getAttributes(null)); + stmt.executeBatch(); } - //writer.close(); - writer.write(); - + stmt.close(); + stmtTexts.clear(); + */ + conn.setAutoCommit(autoCommit); logger.debug("End Save PostGIS:" + featureType.getTypeName()); } - featuresContext.clear(); - } catch (MalformedURLException e) + } catch (PSQLException e) { + if (currentStmt != null) + { + logger.error("Execute:" + currentStmt); + } + logger.error(e.getServerErrorMessage()); logger.error(e.getMessage(), e); - } catch (IllegalAttributeException e) - { - logger.error(e.getMessage(), e); - } catch (IOException e) + } catch (SQLException e) { logger.error(e.getMessage(), e); } @@ -214,13 +199,14 @@ public void closeFeatureWriter() throws IOException { - + /* for (FeatureWriter featureWriter : this.featuresWriterContext.values()) { featureWriter.close(); } this.featuresWriterContext.clear(); + */ } public FeatureType createFeatureElement(String featureName) throws SchemaException @@ -228,6 +214,56 @@ if (typeBuilderRect == null) { typeBuilderRect = FeatureTypeBuilderUtil.createNormalIndexFeatureTypeBuilder(featureName); + if (isExistFeature(typeBuilderRect.getFeatureType())) + { + try + { + Connection conn = targetDataStore.getConnection(Transaction.AUTO_COMMIT); + if (dropTableMode) + { + dropGeometryColumn(conn, featureName, + typeBuilderRect.getFeatureType().getDefaultGeometry().getLocalName()); + dropTable(conn, featureName); + ArrayList<String> schemaTexts = createSchemaTexts(typeBuilderRect.getFeatureType()); + for (String stmtText : schemaTexts) + { + Statement stmt = conn.createStatement(); + stmt.execute(stmtText); + stmt.close(); + } + } else + { + deleteTable(conn, featureName); + } + conn.close(); + } catch (IOException e) + { + logger.warn(e.getMessage(), e); + } catch (SQLException e) + { + logger.warn(e.getMessage(), e); + } + } else + { + try + { + Connection conn = targetDataStore.getConnection(Transaction.AUTO_COMMIT); + ArrayList<String> schemaTexts = createSchemaTexts(typeBuilderRect.getFeatureType()); + for (String stmtText : schemaTexts) + { + Statement stmt = conn.createStatement(); + stmt.execute(stmtText); + stmt.close(); + } + conn.close(); + } catch (IOException e) + { + logger.warn(e.getMessage(), e); + } catch (SQLException e) + { + logger.warn(e.getMessage(), e); + } + } } return typeBuilderRect.getFeatureType(); } @@ -237,6 +273,57 @@ if (typeBuilderPnt == null) { typeBuilderPnt = FeatureTypeBuilderUtil.createNormalIndexTextFeatureTypeBuilder(featureName); + if (isExistFeature(typeBuilderPnt.getFeatureType())) + { + try + { + Connection conn = targetDataStore.getConnection(Transaction.AUTO_COMMIT); + if (dropTableMode) + { + dropGeometryColumn(conn, featureName, + typeBuilderPnt.getFeatureType().getDefaultGeometry().getLocalName()); + dropTable(conn, featureName); + + ArrayList<String> schemaTexts = createSchemaTexts(typeBuilderPnt.getFeatureType()); + for (String stmtText : schemaTexts) + { + Statement stmt = conn.createStatement(); + stmt.execute(stmtText); + stmt.close(); + } + } else + { + deleteTable(conn, featureName); + } + conn.close(); + } catch (IOException e) + { + logger.warn(e.getMessage(), e); + } catch (SQLException e) + { + logger.warn(e.getMessage(), e); + } + } else + { + try + { + Connection conn = targetDataStore.getConnection(Transaction.AUTO_COMMIT); + ArrayList<String> schemaTexts = createSchemaTexts(typeBuilderPnt.getFeatureType()); + for (String stmtText : schemaTexts) + { + Statement stmt = conn.createStatement(); + stmt.execute(stmtText); + stmt.close(); + } + conn.close(); + } catch (IOException e) + { + logger.warn(e.getMessage(), e); + } catch (SQLException e) + { + logger.warn(e.getMessage(), e); + } + } } return typeBuilderPnt.getFeatureType(); } @@ -350,4 +437,18 @@ { return logger; } + + public boolean isDropTableMode() + { + return dropTableMode; + } + + public void setDropTableMode(boolean dropTableMode) + { + this.dropTableMode = dropTableMode; + } + + public void clearOutputDatabase() + { + } } diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/util/FeatureTypeBuilderUtil.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/util/FeatureTypeBuilderUtil.java index 5936abc..2ac037c 100644 --- a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/util/FeatureTypeBuilderUtil.java +++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/util/FeatureTypeBuilderUtil.java @@ -4,30 +4,34 @@ import org.geotools.feature.FeatureTypeBuilder; import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.GeometryFactory; +import com.vividsolutions.jts.geom.Coordinate; public final class FeatureTypeBuilderUtil { + protected static GeometryFactory _geomFactory = new GeometryFactory(); + public static FeatureTypeBuilder createNormalPointFeatureTypeBuilder(String featureName) { FeatureTypeBuilder typeBuilder = FeatureTypeBuilder.newInstance(featureName); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("geom", Geometry.class, false)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("symcolor", String.class, false, 12)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("font", Short.class, false)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("just", Short.class, false)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("height", Float.class, false)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("width", Float.class, false)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("angle", Float.class, false)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("context", String.class, true, 254)); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("geom", Geometry.class, true)); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("symcolor", String.class, false, 12, "")); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("font", Short.class, false, 1, (short) 0)); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("just", Short.class, false, 1, (short) 0)); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("height", Float.class, false, 1, (float) 1.0)); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("width", Float.class, false, 1, (float) 1.0)); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("angle", Float.class, false, 1, (float) 0.0)); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("context", String.class, false, 254, "")); return typeBuilder; } public static FeatureTypeBuilder createNormalLineFeatureTypeBuilder(String featureName) { FeatureTypeBuilder typeBuilder = FeatureTypeBuilder.newInstance(featureName); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("geom", Geometry.class, false)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("symcolor", String.class, false, 12)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("symweight", Short.class, false)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("symstyle", Short.class, false)); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("geom", Geometry.class, true)); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("symcolor", String.class, false, 12, "")); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("symweight", Short.class, false, 1, (short) 0)); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("symstyle", Short.class, false, 1, (short) 0)); return typeBuilder; } @@ -60,15 +64,15 @@ public static FeatureTypeBuilder createNormalIndexFeatureTypeBuilder(String featureName) { FeatureTypeBuilder typeBuilder = FeatureTypeBuilder.newInstance(featureName); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("geom", Geometry.class, false)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("x1", Double.class, false)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("y1", Double.class, false)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("x2", Double.class, false)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("y2", Double.class, false)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("tpclid", String.class, false, 12)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("symcolor", String.class, false, 12)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("symweight", Short.class, false)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("symstyle", Short.class, false)); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("geom", Geometry.class, true)); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("x1", Double.class, false, 1, 0.0)); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("y1", Double.class, false, 1, 0.0)); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("x2", Double.class, false, 1, 0.0)); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("y2", Double.class, false, 1, 0.0)); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("tpclid", String.class, false, 12, "")); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("symcolor", String.class, false, 12, "")); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("symweight", Short.class, false, 1, (short) 0)); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("symstyle", Short.class, false, 1, (short) 0)); return typeBuilder; } @@ -76,15 +80,15 @@ { FeatureTypeBuilder typeBuilder = FeatureTypeBuilder.newInstance(featureName); typeBuilder = FeatureTypeBuilder.newInstance(featureName); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("geom", Geometry.class, false)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("symcolor", String.class, false, 12)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("symweight", Short.class, false)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("symstyle", Short.class, false)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("just", Short.class, false)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("height", Float.class, false)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("width", Float.class, false)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("angle", Float.class, false)); - typeBuilder.addType(AttributeTypeFactory.newAttributeType("tpclid", String.class, false, 12)); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("geom", Geometry.class, true)); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("symcolor", String.class, false, 12, "")); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("symweight", Short.class, false, 1, (short) 0)); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("symstyle", Short.class, false, 1, (short) 0)); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("just", Short.class, false, 1, (short) 0)); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("height", Float.class, false, 1, (float) 0.0)); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("width", Float.class, false, 1, (float) 0.0)); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("angle", Float.class, false, 1, (float) 0.0)); + typeBuilder.addType(AttributeTypeFactory.newAttributeType("tpclid", String.class, false, 12, "")); return typeBuilder; } -- Gitblit v0.0.0-SNAPSHOT