package org.wikibrain.spatial.matcher; import com.typesafe.config.Config; import com.vividsolutions.jts.geom.Geometry; import org.apache.commons.cli.*; import org.geotools.data.simple.SimpleFeatureIterator; import org.opengis.feature.simple.SimpleFeature; import org.wikibrain.conf.ConfigurationException; import org.wikibrain.conf.DefaultOptionBuilder; import org.wikibrain.core.WikiBrainException; import org.wikibrain.core.cmd.Env; import org.wikibrain.core.cmd.EnvBuilder; import org.wikibrain.core.dao.DaoException; import org.wikibrain.core.dao.LocalPageDao; import org.wikibrain.core.dao.MetaInfoDao; import org.wikibrain.core.dao.UniversalPageDao; import org.wikibrain.core.lang.Language; import org.wikibrain.core.model.NameSpace; import org.wikibrain.spatial.dao.SpatialDataDao; import org.wikibrain.spatial.loader.SpatialDataFolder; import org.wikibrain.spatial.WikiBrainShapeFile; import java.io.File; import java.io.IOException; import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Shilad Sen */ public class MappedShapefileLoader { private static final Logger LOG = LoggerFactory.getLogger(MappedShapefileLoader.class); private final Env env; private final LocalPageDao pageDao; private final SpatialDataFolder folder; private final SpatialDataDao spatialDao; private final MetaInfoDao metaDao; private final UniversalPageDao conceptDao; private final Language lang; public MappedShapefileLoader(Env env) throws ConfigurationException, WikiBrainException { this.env = env; this.lang = env.getLanguages().getBestAvailableEnglishLang(false); this.pageDao = env.getConfigurator().get(LocalPageDao.class); this.conceptDao = env.getConfigurator().get(UniversalPageDao.class); this.metaDao = env.getConfigurator().get(MetaInfoDao.class); this.spatialDao = env.getConfigurator().get(SpatialDataDao.class); this.folder = new SpatialDataFolder( new File(env.getConfiguration().get().getString("spatial.dir"))); } public void removeLayer(String refSys, String layerGroup) throws DaoException { this.spatialDao.removeLayer(refSys, layerGroup); } public void load(String refSys, String layerGroup, String dataset) throws IOException, DaoException { Config c = getConfig(refSys, layerGroup, dataset); WikiBrainShapeFile shapefile = folder.getShapeFile(refSys, layerGroup, dataset, c.getString("encoding")); Map<String, String> mapping = shapefile.readMapping(); List<String> keyFields = c.getStringList("key"); // Read in and uppercase feature names List<String> featureNames = shapefile.getFeatureNames(); for (int i = 0; i < featureNames.size(); i++) { featureNames.set(i, featureNames.get(i).toUpperCase()); } int missingTitles = 0; int missingConcepts = 0; int missingKeys = 0; int numRows = 0; int numMatches = 0; SimpleFeatureIterator iter = shapefile.getFeatureIter(); while (iter.hasNext()) { if (++numRows % 1000 == 0) { LOG.info(String.format("for %s, matched %d of %d rows (no key = %d, no title = %d, no concept = %d)", shapefile.getFile(), numMatches, numRows, missingKeys, missingTitles, missingConcepts)); } SimpleFeature row = iter.next(); String key = makeKey(keyFields, featureNames, row); if (!mapping.containsKey(key)) { missingKeys++; } String title = mapping.get(key); int pageId = pageDao.getIdByTitle(title, lang, NameSpace.ARTICLE); if (pageId < 0) { missingTitles++; continue; } int conceptId = conceptDao.getUnivPageId(lang, pageId); if (conceptId < 0) { missingConcepts++; continue; } numMatches++; Geometry geometry = (Geometry) row.getDefaultGeometry(); spatialDao.saveGeometry(conceptId, layerGroup, refSys, geometry); metaDao.incrementRecords(Geometry.class); } iter.close(); LOG.info(String.format("for %s, matched %d of %d rows (no key = %d, no title = %d, no concept = %d)", shapefile.getFile(), numMatches, numRows, missingKeys, missingTitles, missingConcepts)); } private String makeKey(List<String> keyFields, List<String> featureNames, SimpleFeature row) { String key = ""; for (String f : keyFields) { int i = featureNames.indexOf(f); if (i < 0) { throw new IllegalArgumentException("Wikibrain match key requires feature " + f + " not found in dbf"); } if (key.length() > 0) { key += "|"; } key += row.getAttribute(i).toString(); } return key; } public void begin() throws DaoException { spatialDao.beginSaveGeometries(); } public void end() throws DaoException { spatialDao.endSaveGeometries(); } private Config getConfig(String refSys, String layerGroup, String dataset) { return env.getConfiguration().getConfig("spatial.datasets", refSys, layerGroup, dataset); } public static void main(String args[]) throws ConfigurationException, DaoException, IOException, WikiBrainException { Options options = new Options(); options.addOption("d", false, "Delete existing data for specified layer group before starting."); options.addOption("n", true, "Dataset name."); options.addOption("r", true, "Reference system"); options.addOption( new DefaultOptionBuilder() .withDescription("Layer group") .isRequired() .hasArg() .create("y")); options.addOption( new DefaultOptionBuilder() .withDescription("Dataset name") .isRequired() .hasArg() .create("n")); EnvBuilder.addStandardOptions(options); CommandLineParser parser = new PosixParser(); CommandLine cmd; try { cmd = parser.parse(options, args); } catch (ParseException e) { System.err.println("Invalid option usage: " + e.getMessage()); new HelpFormatter().printHelp("MatchedShapeFileLoader", options); return; } String refSys = cmd.getOptionValue("r", "earth"); String layer = cmd.getOptionValue("y"); String datasetName = cmd.getOptionValue("n"); Env env = new EnvBuilder(cmd).build(); MappedShapefileLoader loader = new MappedShapefileLoader(env); if (cmd.hasOption("d")) { loader.removeLayer(refSys, layer); } loader.begin(); loader.load(refSys, layer, datasetName); loader.end(); } }