/* Copyright (c) 2013-2014 Boundless and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/edl-v10.html
*
* Contributors:
* Victor Olaya (Boundless) - initial implementation
*/
package org.locationtech.geogig.osm.cli.commands;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import org.geotools.data.DataStore;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.data.simple.SimpleFeatureStore;
import org.locationtech.geogig.cli.CLICommand;
import org.locationtech.geogig.cli.CommandFailedException;
import org.locationtech.geogig.cli.GeogigCLI;
import org.locationtech.geogig.cli.InvalidParameterException;
import org.locationtech.geogig.cli.annotation.ReadOnly;
import org.locationtech.geogig.geotools.cli.porcelain.AbstractSLCommand;
import org.locationtech.geogig.geotools.plumbing.ExportOp;
import org.locationtech.geogig.geotools.plumbing.GeoToolsOpException;
import org.locationtech.geogig.osm.internal.Mapping;
import org.locationtech.geogig.osm.internal.MappingRule;
import org.opengis.feature.Feature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.GeometryDescriptor;
import org.opengis.filter.Filter;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.vividsolutions.jts.awt.PointShapeFactory.Point;
/**
* Exports OSM into a SpatiaLite database, using a data mapping
*
* @see ExportOp
*/
@ReadOnly
@Parameters(commandNames = "export-sl", commandDescription = "Export OSM data to a Spatialite database, using a data mapping")
public class OSMExportSL extends AbstractSLCommand implements CLICommand {
@Parameter(names = { "--overwrite", "-o" }, description = "Overwrite output tables")
public boolean overwrite;
@Parameter(names = { "--mapping" }, description = "The file that contains the data mapping to use")
public String mappingFile;
/**
* Executes the export command using the provided options.
*/
@Override
protected void runInternal(GeogigCLI cli) throws IOException {
Preconditions.checkNotNull(mappingFile != null, "A data mapping file must be specified");
final Mapping mapping = Mapping.fromFile(mappingFile);
List<MappingRule> rules = mapping.getRules();
checkParameter(!rules.isEmpty(), "No rules are defined in the specified mapping");
for (MappingRule rule : rules) {
exportRule(rule, cli);
}
}
private void exportRule(final MappingRule rule, final GeogigCLI cli) throws IOException {
Function<Feature, Optional<Feature>> function = new Function<Feature, Optional<Feature>>() {
@Override
public Optional<Feature> apply(Feature feature) {
Optional<Feature> mapped = rule.apply(feature);
return mapped;
}
};
SimpleFeatureType outputFeatureType = rule.getFeatureType();
String path = getOriginTreesFromOutputFeatureType(outputFeatureType);
DataStore dataStore = getDataStore();
try {
final String tableName = ensureTableExists(outputFeatureType, dataStore);
final SimpleFeatureSource source = dataStore.getFeatureSource(tableName);
if (!(source instanceof SimpleFeatureStore)) {
throw new CommandFailedException("Could not create feature store.");
}
final SimpleFeatureStore store = (SimpleFeatureStore) source;
if (overwrite) {
try {
store.removeFeatures(Filter.INCLUDE);
} catch (IOException e) {
throw new CommandFailedException("Error truncating table " + tableName, e);
}
}
ExportOp op = cli.getGeogig().command(ExportOp.class).setFeatureStore(store)
.setPath(path).setFeatureTypeConversionFunction(function);
try {
op.setProgressListener(cli.getProgressListener()).call();
cli.getConsole().println("OSM data exported successfully to " + tableName);
} catch (IllegalArgumentException iae) {
throw new InvalidParameterException(iae.getMessage(), iae);
} catch (GeoToolsOpException e) {
throw new CommandFailedException("Could not export. Error:" + e.statusCode.name(),
e);
}
} finally {
dataStore.dispose();
}
}
private String ensureTableExists(SimpleFeatureType outputFeatureType, DataStore dataStore)
throws IOException {
final String tableName = outputFeatureType.getName().getLocalPart();
if (Arrays.asList(dataStore.getTypeNames()).contains(tableName)) {
if (!overwrite) {
throw new CommandFailedException(
"The selected table already exists. Use -o to overwrite");
}
} else {
try {
dataStore.createSchema(outputFeatureType);
} catch (IOException e) {
throw new CommandFailedException("Cannot create new table " + tableName);
}
}
return tableName;
}
private String getOriginTreesFromOutputFeatureType(SimpleFeatureType featureType) {
GeometryDescriptor descriptor = featureType.getGeometryDescriptor();
Class<?> clazz = descriptor.getType().getBinding();
if (clazz.equals(Point.class)) {
return "node";
} else {
return "way";
}
}
}