/*
* Copyright (C) 2014 Alec Dhuse
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package co.foldingmap.mapImportExport;
import co.foldingmap.map.vector.VectorLayer;
import co.foldingmap.map.vector.NodeMap;
import co.foldingmap.map.vector.CoordinateList;
import co.foldingmap.map.vector.VectorObject;
import co.foldingmap.map.vector.Coordinate;
import co.foldingmap.map.vector.LineString;
import co.foldingmap.map.vector.MapPoint;
import co.foldingmap.map.vector.Polygon;
import co.scarletshark.geojson.*;
import co.foldingmap.GUISupport.ProgressIndicator;
import co.foldingmap.Logger;
import co.foldingmap.dataStructures.PropertyValuePair;
import co.foldingmap.map.DigitalMap;
import co.foldingmap.map.Layer;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
/**
*
* @author Alec
*/
public class JsonImporter implements FormatImporter {
public JsonImporter() {
}
/**
* Converts and array of JsonCoordinates to Coordinates used by map package.
*
* @param nodeMap
* @param jCoordinates
* @return
*/
public static CoordinateList<Coordinate> convertGeoJsonCoordinates(NodeMap nodeMap, JsonCoordinate[] jCoordinates) {
Coordinate coordinate;
CoordinateList<Coordinate> cList = new CoordinateList<Coordinate>();
for (JsonCoordinate jCoordinate: jCoordinates) {
coordinate = new Coordinate((float) jCoordinate.getAltitude(), (float) jCoordinate.getLatitude(), (float) jCoordinate.getLongitude());
cList.add(coordinate);
nodeMap.put(coordinate);
}
return cList;
}
/**
* Converts a GeoJsonObject to a VectorObject.
* GeoJsonObjects are created from the JsonParse class.
*
* @param mapData
* @param geoObject
* @return
*/
public static VectorObject convertGeoJsonObject(NodeMap nodeMap, GeoJsonObject geoObject) {
CoordinateList<Coordinate> cList;
VectorObject returnObject;
cList = convertGeoJsonCoordinates(nodeMap, geoObject.getCoordinates());
if (geoObject instanceof JsonLineString) {
returnObject = new LineString("JSON LineString", "(Unspecified Linestring)", cList);
} else if (geoObject instanceof JsonPoint) {
returnObject = new MapPoint("JSON Point", "(Unspecified Point)", "", cList);
} else if (geoObject instanceof JsonPolygon) {
returnObject = new Polygon("JSON Polygon", "(Unspecified Polygon)", cList);
} else {
returnObject = null;
}
return returnObject;
}
/**
* Converts a JsonPair with a valueType of STRING to a PropertyValuePair.
* If valueType is not a STRING, then a null is returned.
*
* @param pair
* @return
*/
public static PropertyValuePair convertJsonPair(JsonPair pair) {
PropertyValuePair newPair;
if (pair.getValue().getValueType().equals(JsonValue.STRING)) {
newPair = new PropertyValuePair(pair.getName(), pair.getValueAsString());
} else if (pair.getValue().getValueType().equals(JsonValue.BOOLEAN)) {
newPair = new PropertyValuePair(pair.getName(), pair.getValue().getValue().toString());
} else if (pair.getValue().getValueType().equals(JsonValue.NUMBER)) {
newPair = new PropertyValuePair(pair.getName(), pair.getValue().getValue().toString());
} else if (pair.getValue().getValueType().equals(JsonValue.NULL)) {
newPair = new PropertyValuePair(pair.getName(), "null");
} else {
newPair = null;
}
return newPair;
}
/**
* Creates a new VectorLayer in the given DigitalMap with the imported
* GeoJSON data.
*
* @param file The file containing the GeoJSON data.
* @param mapData The Map to import the data to.
*/
public static void importGeoJSON(File file, DigitalMap mapData) {
VectorLayer layer;
try {
layer = new VectorLayer("JSON Import");
mapData.addLayer(layer, 0);
importGeoJSON(file, mapData.getCoordinateSet(), layer);
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in JsonImporter.importGeoJSON(File, DigitalMap) - " + e);
}
}
/**
* Imports GeoJSON into a given VectorLayer.
*
* @param file The file containing the GeoJSON data.
* @param nodeMap The Map to import the data to.
* @param importLayer The Layer to add the GeoJSON imported objects to.
*/
public static void importGeoJSON(File file, NodeMap nodeMap, VectorLayer importLayer) {
ArrayList<PropertyValuePair> pvpPairs;
JsonObject currentObject, propertiesObject, rootObject;
JsonPair featurePair;
String name;
VectorObject vObject;
try {
rootObject = JsonParser.parseFile(file);
featurePair = rootObject.getPairByName("features");
//mapData.addLayer(importLayer, 0);
if (featurePair != null) {
for (Object obj: featurePair.getValueAsArray()) {
currentObject = (JsonObject) obj;
name = null;
pvpPairs = new ArrayList<PropertyValuePair>();
vObject = null;
for (JsonPair jPair: currentObject.getPairs()) {
if (jPair.getName().equalsIgnoreCase("id") && name == null) {
name = jPair.getValueAsString();
} else if (jPair.getName().equalsIgnoreCase("type")) {
} else if (jPair.getName().equalsIgnoreCase("properties")) {
propertiesObject = jPair.getValueAsObject();
for (JsonPair propertiesPair: propertiesObject.getPairs()) {
PropertyValuePair pvp = convertJsonPair(propertiesPair);
if (pvp != null) {
if (pvp.getProperty().equalsIgnoreCase("name")) {
name = pvp.getValue();
} else {
pvpPairs.add(pvp);
}
}
}
} else if (jPair.getName().equalsIgnoreCase("geometry")) {
GeoJsonObject geoObject = (GeoJsonObject) jPair.getValue().getValue();
if (geoObject != null)
vObject = convertGeoJsonObject(nodeMap, geoObject);
}
}
if (vObject != null) {
vObject.addCustomDataFields(pvpPairs);
importLayer.addObject(vObject);
if (name != null)
vObject.setName(name);
}
}
} else {
Logger.log(Logger.ERR, "Error in JsonImporter.importGeoJSON(File, NodeMap, VectorLayer) - Couldn't find Feature Pair.");
}
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in JsonImporter.importGeoJSON(File, NodeMap, VectorLayer) - " + e);
}
}
/**
* Imports objects from a given map file and adds objects from the map to
* the given VectorLayer.
*
* @param mapFile The file containing the map to import.
* @param nodeMap The NodeMap to add new Coordinates to.
* @param layer The Layer to add imported objects to.
* @param progressIndicator Optional, to display the progress of the import.
*/
@Override
public void importToLayer(File mapFile, NodeMap nodeMap, Layer layer, ProgressIndicator progressIndicator) throws IOException {
if (layer instanceof VectorLayer) {
VectorLayer vecLayer = (VectorLayer) layer;
vecLayer.getObjectList().clear();
importGeoJSON(mapFile, nodeMap, vecLayer);
} else {
Logger.log(Logger.ERR, "Error in JsonImporterImporter.importToLayer(File, NodeMap, Layer, ProgressIndicator) - Supplied Layer must be a VectorLayer.");
}
}
@Override
public DigitalMap importAsMap(File mapFile, ProgressIndicator progressIndicator) throws IOException {
DigitalMap mapData;
VectorLayer newLayer;
mapData = new DigitalMap();
newLayer = new VectorLayer("GeoJSON Layer");
mapData.addLayer(newLayer);
importGeoJSON(mapFile, mapData.getCoordinateSet(), newLayer);
return mapData;
}
}