Skip to content

Commit

Permalink
Modernizes the progress listener for shapefiles
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexisDrogoul committed Apr 26, 2021
1 parent d1ba5bd commit 93941a9
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 75 deletions.
121 changes: 46 additions & 75 deletions msi.gama.core/src/msi/gama/util/file/GamaShapeFile.java
Expand Up @@ -10,6 +10,8 @@
********************************************************************************************************/
package msi.gama.util.file;

import static msi.gama.runtime.GAMA.reportError;
import static msi.gama.runtime.exceptions.GamaRuntimeException.warning;
import static org.apache.commons.lang.StringUtils.join;
import static org.apache.commons.lang.StringUtils.splitByWholeSeparatorPreserveAllTokens;

Expand All @@ -21,22 +23,18 @@
import java.util.LinkedHashMap;
import java.util.Map;

import org.geotools.data.FeatureReader;
import org.geotools.data.Query;
import org.geotools.data.FileDataStore;
import org.geotools.data.FileDataStoreFinder;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.data.store.ContentFeatureSource;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.opengis.feature.Feature;
import org.locationtech.jts.geom.Geometry;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.GeometryType;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.Polygon;

import msi.gama.common.geometry.Envelope3D;
import msi.gama.common.geometry.GeometryUtils;
import msi.gama.common.util.GISUtils;
Expand All @@ -47,7 +45,6 @@
import msi.gama.precompiler.GamlAnnotations.example;
import msi.gama.precompiler.GamlAnnotations.file;
import msi.gama.precompiler.IConcept;
import msi.gama.runtime.GAMA;
import msi.gama.runtime.IScope;
import msi.gama.runtime.exceptions.GamaRuntimeException;
import msi.gama.util.GamaListFactory;
Expand Down Expand Up @@ -101,9 +98,7 @@ public ShapeInfo(final IScope scope, final URL url, final long modificationStamp
env = source.getBounds();
if (crs1 == null) {
crs1 = GISUtils.manageGoogleCRS(url);
if (crs1 != null) {
env = new ReferencedEnvelope(env, crs1);
}
if (crs1 != null) { env = new ReferencedEnvelope(env, crs1); }
}

if (crs1 != null) {
Expand Down Expand Up @@ -137,9 +132,7 @@ public ShapeInfo(final IScope scope, final URL url, final long modificationStamp
height = env.getHeight();
itemNumber = number;
this.crs = crs1;
if (store != null) {
store.dispose();
}
if (store != null) { store.dispose(); }
}

}
Expand Down Expand Up @@ -190,9 +183,7 @@ public String getSuffix() {
@Override
public void appendSuffix(final StringBuilder sb) {
sb.append(itemNumber).append(" object");
if (itemNumber > 1) {
sb.append("s");
}
if (itemNumber > 1) { sb.append("s"); }
sb.append(SUFFIX_DEL);
sb.append(crs == null ? "Unknown CRS" : crs.getName().getCode());
sb.append(SUFFIX_DEL);
Expand Down Expand Up @@ -229,9 +220,7 @@ public String toPropertyString() {
} catch (final Exception e) {
// The toWKT()/parseWKT() pair has a problem
String srs = CRS.toSRS(crs);
if (srs == null && crs != null) {
srs = crs.getName().getCode();
}
if (srs == null && crs != null) { srs = crs.getName().getCode(); }
system = "Unknown projection " + srs;

}
Expand Down Expand Up @@ -309,7 +298,7 @@ public GamaShapeFile(final IScope scope, final String pathName, final String cod
*/
@Override
protected void fillBuffer(final IScope scope) throws GamaRuntimeException {
if (getBuffer() != null) { return; }
if (getBuffer() != null) return;
setBuffer(GamaListFactory.<IShape> create(Types.GEOMETRY));
readShapes(scope);
}
Expand Down Expand Up @@ -337,16 +326,12 @@ protected CoordinateReferenceSystem getOwnCRS(final IScope scope) {
final URL url = getFile(scope).toURI().toURL();
store = getDataStore(url);
CoordinateReferenceSystem crs = store.getFeatureSource().getInfo().getCRS();
if (crs == null) {
crs = GISUtils.manageGoogleCRS(url);
}
if (crs == null) { crs = GISUtils.manageGoogleCRS(url); }
return crs;
} catch (final IOException e) {
return null;
} finally {
if (store != null) {
store.dispose();
}
if (store != null) { store.dispose(); }
}
}

Expand All @@ -360,62 +345,50 @@ static ShapefileDataStore getDataStore(final URL url) {
}

protected void readShapes(final IScope scope) {
scope.getGui().getStatus(scope).beginSubStatus("Reading file " + getName(scope));
ShapefileDataStore store = null;
ProgressCounter counter = new ProgressCounter(scope, "Reading file " + getName(scope));
FileDataStore store = null;
final File file = getFile(scope);
final IList list = getBuffer();
int size = 0;
try {
store = getDataStore(file.toURI().toURL());
final ContentFeatureSource source = store.getFeatureSource();
store = FileDataStoreFinder.getDataStore(file);
final SimpleFeatureSource source = store.getFeatureSource();
final Envelope3D env = Envelope3D.of(source.getBounds());
size = source.getCount(Query.ALL);
int index = 0;
computeProjection(scope, env);
try (FeatureReader reader = store.getFeatureReader()) {
while (reader.hasNext()) {
index++;
if (index % 20 == 0) {
scope.getGui().getStatus(scope).setSubStatusCompletion(index / (double) size);
}
final Feature feature = reader.next();
Geometry g = (Geometry) feature.getDefaultGeometryProperty().getValue();
if (g != null && !g.isEmpty() /* Fix for Issue 725 && 677 */ ) {
if (!with3D && !g.isValid()) {
g = GeometryUtils.cleanGeometry(g);
}
g = gis.transform(g);
if (!with3D) {
g.apply(ZERO_Z);
g.geometryChanged();
}
g = multiPolygonManagement(g);
GamaGisGeometry gt = new GamaGisGeometry(g, feature);
if (gt.getInnerGeometry() != null)
list.add(gt);

} else if (g == null) {
// See Issue 725
GAMA.reportError(scope,
GamaRuntimeException
.warning("GamaShapeFile.fillBuffer; geometry could not be added as it is "
+ "nil: " + feature.getIdentifier(), scope),
false);
SimpleFeatureCollection collection = source.getFeatures();
collection.accepts(feature -> {
Geometry g = (Geometry) feature.getDefaultGeometryProperty().getValue();
System.out.println(g.getCoordinate());
}, counter);
collection.accepts(feature -> {
Geometry g = (Geometry) feature.getDefaultGeometryProperty().getValue();
if (g != null && !g.isEmpty() /* Fix for Issue 725 && 677 */ ) {
if (!with3D && !g.isValid()) { g = GeometryUtils.cleanGeometry(g); }
g = gis.transform(g);
if (!with3D) {
g.apply(ZERO_Z);
g.geometryChanged();
}
g = multiPolygonManagement(g);
GamaGisGeometry gt = new GamaGisGeometry(g, feature);
if (gt.getInnerGeometry() != null) { list.add(gt); }
} else if (g == null) {
// See Issue 725
reportError(scope,
warning("geometry could not be added as it is " + "nil: " + feature.getIdentifier(),
scope),
false);
}
}
}, counter);

} catch (final IOException e) {
throw GamaRuntimeException.create(e, scope);
} finally {
if (store != null) {
store.dispose();
}
scope.getGui().getStatus(scope).endSubStatus("Reading file " + getName(scope));
}
if (size > list.size()) {
GAMA.reportError(scope, GamaRuntimeException.warning("Problem with file " + getFile(scope) + ": only "
+ list.size() + " of the " + size + " geometries could be added", scope), false);
if (store != null) { store.dispose(); }
}
// if (size > list.size()) {
// reportError(scope, warning("Problem with file " + getFile(scope) + ": only " + list.size() + " of the "
// + size + " geometries could be added", scope), false);
// }
}

@Override
Expand All @@ -429,9 +402,7 @@ public Envelope3D computeEnvelope(final IScope scope) {
} catch (final IOException e) {
return Envelope3D.EMPTY;
} finally {
if (store != null) {
store.dispose();
}
if (store != null) { store.dispose(); }
}
}
return gis.getProjectedEnvelope();
Expand Down
81 changes: 81 additions & 0 deletions msi.gama.core/src/msi/gama/util/file/ProgressCounter.java
@@ -0,0 +1,81 @@
package msi.gama.util.file;

import org.geotools.util.SimpleInternationalString;
import org.opengis.util.InternationalString;
import org.opengis.util.ProgressListener;

import msi.gama.common.interfaces.IStatusDisplayer;
import msi.gama.runtime.GAMA;
import msi.gama.runtime.IScope;
import msi.gama.runtime.exceptions.GamaRuntimeException;

class ProgressCounter implements ProgressListener {

final IScope scope;
final String name;
float progress;

ProgressCounter(final IScope scope, final String name) {
this.scope = scope;
this.name = name;
}

IStatusDisplayer getDisplayer() {
return scope.getGui().getStatus(scope);
}

@Override
public void complete() {
getDisplayer().setSubStatusCompletion(1d);
}

@Override
public void dispose() {
getDisplayer().endSubStatus(name.toString());
}

@Override
public void exceptionOccurred(final Throwable arg0) {
GAMA.reportAndThrowIfNeeded(scope, GamaRuntimeException.create(arg0, scope), true);
}

@Override
public float getProgress() {
return progress;
}

@Override
public InternationalString getTask() {
return new SimpleInternationalString(name);
}

@Override
public boolean isCanceled() {
return scope.interrupted();
}

@Override
public void progress(final float p) {
progress = p;
getDisplayer().setSubStatusCompletion(progress);
}

@Override
public void setCanceled(final boolean cancel) {
getDisplayer().endSubStatus(name.toString());
}

@Override
public void setTask(final InternationalString n) {}

@Override
public void started() {
getDisplayer().beginSubStatus(name.toString());
}

@Override
public void warningOccurred(final String source, final String location, final String warning) {
GAMA.reportAndThrowIfNeeded(scope, GamaRuntimeException.warning(warning, scope), false);
}

}

0 comments on commit 93941a9

Please sign in to comment.