MapProcessor.java

package org.wikidata.analyzer.Processor;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.wikidata.wdtk.datamodel.implementation.PropertyIdValueImpl;
import org.wikidata.wdtk.datamodel.interfaces.*;

import java.io.*;
import java.util.*;

/**
 * MapProcessor for wikidata-analysis
 *
 * @author Addshore
 */
public class MapProcessor extends WikidataAnalyzerProcessor {

    private JSONObject geoDataOut = new JSONObject();
    private JSONObject graphOut = new JSONObject();

    private PropertyIdValue coordinateLocation = PropertyIdValueImpl.create("P625", "http://www.wikidata.org/entity/");

    // This list is filled in the constructor
    private List<String> graphRelations = new ArrayList<>();

    public MapProcessor() {
        this.populateGraphRelations();
    }

    public boolean tearDown() {
        boolean success = true;

        System.out.println("Writing map wdlabel.json");
        File mapLabelFile = new File(outputDir.getAbsolutePath() + File.separator + "wdlabel.json");
        try {
            BufferedWriter mapLabelWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(mapLabelFile)));
            this.geoDataOut.writeJSONString(mapLabelWriter);
            mapLabelWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
            success = false;
        }

        System.out.println("Writing map graph.json");
        File mapGraphFile = new File(outputDir.getAbsolutePath() + File.separator + "graph.json");
        try {
            BufferedWriter mapGraphWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(mapGraphFile)));
            this.graphOut.writeJSONString(mapGraphWriter);
            mapGraphWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
            success = false;
        }

        return success;
    }

    private void populateGraphRelations() {
        // Fill the list of graphRelations
        // The previous script actually generated graph data for ALL properties
        this.graphRelations.add("P17");// Country
        this.graphRelations.add("P36");// Capital
        this.graphRelations.add("P47");// Shared border with
        this.graphRelations.add("P138");// Named after
        this.graphRelations.add("P150");// Subdivision
        this.graphRelations.add("P190");// Twin cities
        this.graphRelations.add("P197");// Adjacent station
        this.graphRelations.add("P403");// Mouth of watercourse
    }

    @Override
    public void processItemDocument(ItemDocument item) {
        boolean itemHasCoordinateValue = false;

        for (Iterator<Statement> statements = item.getAllStatements(); statements.hasNext(); ) {
            Statement statement = statements.next();
            if (statement.getClaim().getMainSnak().getPropertyId().equals(this.coordinateLocation)) {
                Snak snak = statement.getClaim().getMainSnak();
                if (snak instanceof ValueSnak) {
                    itemHasCoordinateValue = true;
                    GlobeCoordinatesValue value = (GlobeCoordinatesValue) ((ValueSnak) snak).getValue();
                    JSONObject geoData = new JSONObject();
                    geoData.put("x", value.getLatitude());
                    geoData.put("y", value.getLongitude());
                    MonolingualTextValue label = item.getLabels().get("en");
                    if (label == null) {
                        // TODO fallback of label
                        geoData.put("label", "-");
                    } else {
                        geoData.put("label", label.getText());
                    }
                    this.geoDataOut.put(item.getItemId().getId(), geoData);
                }
                break;
            }
        }

        if (itemHasCoordinateValue) {
            for (StatementGroup statementGroup : item.getStatementGroups()) {
                String statementGroupPropertyString = statementGroup.getProperty().getId();
                if (this.graphRelations.contains(statementGroupPropertyString)) {
                    // TODO rather than doing the below if in this loop, it could be done once in the constructor
                    if (!this.graphOut.containsKey(statementGroupPropertyString)) {
                        this.graphOut.put(statementGroupPropertyString, new JSONObject());
                    }
                    JSONArray graphData = new JSONArray();
                    for (Statement statement : statementGroup.getStatements()) {
                        Snak snak = statement.getClaim().getMainSnak();
                        if (snak instanceof ValueSnak) {
                            ItemIdValue value = (ItemIdValue) ((ValueSnak) snak).getValue();
                            graphData.add(value.getId());
                        }
                    }
                    ((JSONObject) this.graphOut.get(statementGroupPropertyString)).put(item.getItemId().getId(), graphData);
                }
            }
        }
    }

    @Override
    public void processPropertyDocument(PropertyDocument property) {
    }

}