/*
* 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.MapProjection;
import co.foldingmap.map.MercatorProjection;
import co.foldingmap.map.DigitalMap;
import co.foldingmap.map.Visibility;
import co.foldingmap.map.Layer;
import co.foldingmap.map.vector.LinearRing;
import co.foldingmap.map.vector.Region;
import co.foldingmap.map.vector.NetworkLayer;
import co.foldingmap.map.vector.MultiGeometry;
import co.foldingmap.map.vector.LatLonAltBox;
import co.foldingmap.map.vector.VectorLayer;
import co.foldingmap.map.vector.NodeMap;
import co.foldingmap.map.vector.CoordinateList;
import co.foldingmap.map.vector.VectorObjectList;
import co.foldingmap.map.vector.VectorObject;
import co.foldingmap.map.vector.LevelOfDetail;
import co.foldingmap.map.vector.LineString;
import co.foldingmap.map.vector.Polygon;
import co.foldingmap.map.vector.PhotoPoint;
import co.foldingmap.map.vector.Coordinate;
import co.foldingmap.map.vector.MapPoint;
import co.foldingmap.map.vector.InnerBoundary;
import co.foldingmap.map.tile.TileServerTileSource;
import co.foldingmap.map.tile.TileMath;
import co.foldingmap.map.tile.TileSource;
import co.foldingmap.map.tile.DirectoriesTileSource;
import co.foldingmap.map.tile.TileLayer;
import co.foldingmap.map.tile.MbTileSource;
import co.foldingmap.map.themes.PolygonStyle;
import co.foldingmap.map.themes.ColorRamp;
import co.foldingmap.map.themes.ColorHelper;
import co.foldingmap.map.themes.ThemeConstants;
import co.foldingmap.map.themes.MapTheme;
import co.foldingmap.map.themes.LabelStyle;
import co.foldingmap.map.themes.ColorStyle;
import co.foldingmap.map.themes.OutlineStyle;
import co.foldingmap.map.themes.IconStyle;
import co.foldingmap.map.themes.LineStyle;
import co.foldingmap.GUISupport.ProgressBarPanel;
import co.foldingmap.GUISupport.ProgressIndicator;
import co.foldingmap.Logger;
import co.foldingmap.map.vector.LatLonBox;
import co.foldingmap.map.visualization.HeatMap;
import co.foldingmap.map.visualization.HeatMapKey;
import co.foldingmap.xml.XMLParser;
import co.foldingmap.xml.XMLTag;
import java.awt.Color;
import java.awt.Font;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.StringTokenizer;
/**
* Class for loading FmXml files
*
* @author Alec
*/
public class FmXmlImporter implements FormatImporter {
/**
* Creates a new Visibility object from a Region.
* If the region does not contain a LevelOfDetail then a Visibility object with max = 25 and
* min = 0 is created.
*
* @param r
* @return
*/
public static Visibility convertRegionToVisibility(Region r) {
LevelOfDetail lod = r.getLevelOfDetail();
if (lod != null) {
float max = r.calculateVectorZoomLevelForLOD(lod.getMaxLodPixels());
float min = r.calculateVectorZoomLevelForLOD(lod.getMinLodPixels());
return new Visibility(TileMath.getTileMapZoom(max), TileMath.getTileMapZoom(min));
} else {
return new Visibility(25, 0);
}
}
/**
* Does a quick read of the head of the FmXML file to retrieve the bounds.
* The map is not loaded, this is used to check if a map needs to be loaded
* when linking files.
*
* @param mapFile
* @return
*/
public static LatLonBox getBounds(File mapFile) {
byte[] buffer = new byte[4096];
LatLonBox bounds = null;
try {
//Open the file and grab the first 4096 bytes
FileInputStream fs = new FileInputStream(mapFile);
fs.read(buffer);
//Cponvert to a string and get the lovation of the bounds tag.
String header = new String(buffer, "UTF-8");
int start = header.indexOf("<bounds>") + 8;
int end = header.indexOf("</bounds>");
//If the bounds tag exists parse it and get the map bounds.
if (start > 0 && end > 0) {
String boundsString = header.substring(start, end);
XMLTag boundsTag = new XMLTag("bounds", boundsString);
bounds = FmXmlImporter.getLatLonBox(boundsTag.getSubtag("LatLonBox"));
} else {
Logger.log(Logger.WARN, "FmXmlImporter.getBounds(File) - Map file does not contain bounds.");
}
} catch (IOException e) {
Logger.log(Logger.WARN, "FmXmlImporter.getBounds(File) - Error getting bounds of " + mapFile.getName());
}
return bounds;
}
/**
* Reads a ColorRamp FmXml tag and creates a ColorRamp object from it.
*
* @param id
* @param colorRampTag
* @return
*/
public static ColorRamp getColorRamp(String id, XMLTag colorRampTag) {
ColorRamp colorRamp = new ColorRamp(id);
for (XMLTag tag: colorRampTag.getSubtags()) {
if (tag.getTagName().equalsIgnoreCase("Default")) {
String defaultColor = colorRampTag.getSubtagContent("Default");
colorRamp.setDefaultColor(ColorHelper.parseHexStandard(defaultColor));
} else {
colorRamp.addEntry(tag.getTagValue(), ColorHelper.parseHexStandard(tag.getTagContent()));
}
}
return colorRamp;
}
/**
* Creates a CoordinateList from data in the given NodeMap and NodeIDs from the coordinate String.
*
* @param coordinateSet
* @param coordinateString
* @return
*/
public static CoordinateList<Coordinate> getCoordinateList(NodeMap coordinateSet,
String coordinateString) {
Coordinate coordinate;
CoordinateList<Coordinate> coordinates;
long nodeId;
String coordinateGroupString;
StringTokenizer coordinateGroupTokenizer;
try {
coordinateGroupTokenizer = new StringTokenizer(coordinateString);
coordinates = new CoordinateList<Coordinate>(coordinateGroupTokenizer.countTokens());
while (coordinateGroupTokenizer.hasMoreTokens()) {
coordinateGroupString = coordinateGroupTokenizer.nextToken();
if (!coordinateGroupString.contains(",")) {
//Single element, should be a reference to a node id
nodeId = Long.parseLong(coordinateGroupString);
coordinate = coordinateSet.get(nodeId);
if (coordinate != null) {
coordinates.add(coordinate);
} else {
System.err.println("Error node id: " + nodeId + " not found");
}
} else {
//Two elements, should be lon, lat
//Three elements should be lon, lat, alt
//Four elements, should be lon, lat, alt, timestmap
coordinate = new Coordinate(coordinateGroupString);
if (coordinate != null) {
//check to see if the coordinate already exists in the map
nodeId = coordinateSet.findKey(coordinate);
//nodeId = getKeyByValue(coordinateSet, coordinate);
if (nodeId > 0) {
//the coordinate already exists
coordinate = coordinateSet.get(nodeId);
if (coordinate != null) {
coordinate.setShared(true);
coordinates.add(coordinate);
} else {
System.err.println("Error node id: " + nodeId + "not found");
}
} else {
//generate new ID
nodeId = coordinateSet.size() - 1;
//Make sure the new ID does not already exist
while (coordinateSet.get(nodeId) != null)
nodeId++;
coordinateSet.put(nodeId, coordinate);
coordinates.add(coordinate);
}
} else {
System.err.println("Error in FmXmlImporter - null coordinate");
} // null coordinate check
}
}
//System.err.println(coordinates.size());
return coordinates;
} catch (Exception e) {
System.err.println("Error in FmXmlImporter.getCoordinateList(NodeMap, String - " + e);
return new CoordinateList<Coordinate>(1);
}
}
/**
* Reads gxTags to create a HashMap of customDataFields.
*
* @param dataTag
* @return
*/
public static HashMap<String,String> getCustomDataFields(XMLTag dataTag) {
ArrayList<XMLTag> dataSubTabs;
HashMap<String,String> customDataFields;
String key, value, tagName;
dataSubTabs = dataTag.getSubtags();
customDataFields = new HashMap<String,String>();
try {
for (int i = 0; i < dataSubTabs.size(); i++) {
tagName = dataSubTabs.get(i).getTagName();
if (tagName.length() > 3 && tagName.substring(0,4).equalsIgnoreCase("pair")) {
key = dataSubTabs.get(i).getTagValue();
value = dataSubTabs.get(i).getTagContent();
} else {
//for legacy compatibility
key = dataSubTabs.get(i).getTagContent();
value = dataSubTabs.get(i+1).getTagContent();
i++;
}
customDataFields.put(key, value);
}
} catch (Exception e) {
System.err.println("Error in FmXmlImporter.getCustomDataFields(ArrayList) - " + e);
}
return customDataFields;
}
/**
* Returns a HeatMap form fmXml
*
* @param openedMap
* @param layerTag
* @return
*/
public static HeatMap getHeatMapLayer(DigitalMap openedMap, XMLTag layerTag) {
try {
ArrayList<Color> colors;
ArrayList<String> objectRefs, variables;
HeatMap heatMap;
HeatMapKey heatMapKey;
int positionRef;
String layerDescription, layerName;
String style, orientation, position;
String[] temp;
StringTokenizer st;
XMLTag fields, descriptionTag, keyTag, mappings;
XMLTag objects, orientationTag;
objectRefs = new ArrayList<String>();
variables = new ArrayList<String>();
descriptionTag = layerTag.getSubtag("Description");
layerName = layerTag.getSubtagContent("Name");
fields = layerTag.getSubtag("fields");
mappings = layerTag.getSubtag("mappings");
layerDescription = removeCDataTag(layerTag.getSubtagContent("Description"));
objects = layerTag.getSubtag("objects");
keyTag = layerTag.getSubtag("key");
style = layerTag.getSubtagContent("Style");
colors = new ArrayList<Color>();
positionRef = -1;
if (keyTag != null) {
position = keyTag.getSubtagContent("Position");
orientationTag = keyTag.getSubtag("Orientation");
if (position.equalsIgnoreCase("None")) {
positionRef = HeatMapKey.NONE;
} else if (position.equalsIgnoreCase("Bottom-Left")) {
positionRef = HeatMapKey.BOTTOM_LEFT;
} else if (position.equalsIgnoreCase("Bottom-Right")) {
positionRef = HeatMapKey.BOTTOM_RIGHT;
} else if (position.equalsIgnoreCase("Top-Left")) {
positionRef = HeatMapKey.TOP_LEFT;
} else if (position.equalsIgnoreCase("Top-Right")) {
positionRef = HeatMapKey.TOP_RIGHT;
}
for (XMLTag tag: keyTag.getSubtagsByName("color")) {
colors.add(ColorHelper.parseHexStandard(tag.getTagContent()));
}
if (orientationTag != null) {
orientation = orientationTag.getTagContent();
} else {
orientation = HeatMapKey.HORIZONTAL;
}
} else {
orientation = HeatMapKey.HORIZONTAL;
}
//parse Variables/Fields
st = new StringTokenizer(fields.getTagContent(), ",");
while(st.hasMoreTokens())
variables.add(st.nextToken().replace(",", ""));
//description uses HTML
if (layerDescription.equals("") && (descriptionTag != null))
layerDescription = descriptionTag.getSubtagsAsString();
st = new StringTokenizer(objects.getTagContent(), ",");
while (st.hasMoreTokens())
objectRefs.add(st.nextToken().replace(",", ""));
temp = new String[variables.size()];
heatMapKey = new HeatMapKey(new ArrayList<String>(), colors, positionRef, orientation);
heatMap = new HeatMap(layerName, objectRefs, style, variables.toArray(temp), 500, heatMapKey);
heatMap.setLayerDescription(layerDescription);
return heatMap;
} catch (Exception e) {
System.err.println("Error in FmXmlImport.getHeatMapLayer(XMLTag) - " + e);
return null;
}
}
/**
* Returns an IconStyle given it's XML code.
*
* @param styleTag
* @return
*/
public static IconStyle getIconStyle(XMLTag styleTag) {
try {
boolean hasHeading, hasIcon, hasLabel, hasLOD, hasOutline, hasScale, hasVis;
boolean outline;
Color fillColor, outlineColor;
float heading, scale;
IconStyle newIconStyle;
int colorMode;
LabelStyle labelStyle;
String colorModeString, icon, styleID, styleTagName;
XMLTag iconTag, iconStyleTag;
styleTagName = styleTag.getTagName();
styleID = styleTagName.substring(styleTagName.indexOf("id=\"") + 4, styleTagName.length() - 1);
iconStyleTag = styleTag.getSubtag("IconStyle");
fillColor = ColorHelper.parseHexStandard(iconStyleTag.getSubtagContent("color"));
colorModeString = iconStyleTag.getSubtagContent("colorMode");
hasScale = iconStyleTag.containsSubTag("scale");
hasHeading = iconStyleTag.containsSubTag("heading");
hasOutline = iconStyleTag.containsSubTag("outline");
hasIcon = iconStyleTag.containsSubTag("Icon");
hasLabel = iconStyleTag.containsSubTag("LabelStyle");
hasVis = iconStyleTag.containsSubTag("Visibility");
if (colorModeString.equalsIgnoreCase("normal")) {
colorMode = ColorStyle.NORMAL;
} else {
colorMode = ColorStyle.RANDOM;
}
newIconStyle = new IconStyle(styleID, fillColor);
if (iconStyleTag.containsSubTag("Visibility")) {
Visibility vis = getVisibility(iconStyleTag.getSubtag("Visibility"));
newIconStyle.setVisibility(vis);
}
if (hasScale) {
scale = Float.parseFloat(iconStyleTag.getSubtagContent("scale"));
newIconStyle.setScale(scale);
}
if (hasHeading) {
heading = Float.parseFloat(iconStyleTag.getSubtagContent("heading"));
newIconStyle.setHeading(heading);
}
if (hasOutline) {
outline = Boolean.parseBoolean(iconStyleTag.getSubtagContent("outline"));
if (outline) {
outlineColor = ColorHelper.parseHexStandard(iconStyleTag.getSubtagContent("outlineColor"));
newIconStyle.setOutlineColor(outlineColor);
}
}
newIconStyle.setColorMode(colorMode);
if (hasIcon) {
iconTag = iconStyleTag.getSubtag("Icon");
icon = iconTag.getSubtagContent("href");
newIconStyle.setImageFileName(icon);
}
if (hasVis) {
Visibility vis = getVisibility(iconStyleTag.getSubtag("Visibility"));
newIconStyle.setVisibility(vis);
}
if (hasLabel) {
labelStyle = getLabelStyle(iconStyleTag.getSubtag("LabelStyle"));
newIconStyle.setLabel(labelStyle);
}
return newIconStyle;
} catch (Exception e) {
System.err.println("Error in FmXmlImport.getIconStyle(XMLTag) - " + e);
return null;
}
}
/**
* Creates an InnerBoundary when given an InnerBoundary FmXml tag.
*
* @param layer - Layer to add object to.
* @param nodeMap - The NodeMap which this object references coordinates.
* @param ibTag
* @return
*/
public static InnerBoundary getInnerBoundary(NodeMap nodeMap, VectorLayer layer, XMLTag ibTag) {
CoordinateList<Coordinate> coordinates;
InnerBoundary ib;
String coordinateString;
XMLTag linearRingTag;
linearRingTag = ibTag.getSubtag("LinearRing");
coordinateString = linearRingTag.getSubtagContent("coordinates");
coordinates = getCoordinateList(nodeMap, coordinateString);
ib = new InnerBoundary(coordinates);
return ib;
}
/**
* Reads in the KML for LabelStyle and returns an object.
*
* @param labelTag
* @return
*/
public static LabelStyle getLabelStyle(XMLTag labelTag) {
Color fillColor, outlineColor;
Font labelFont;
int fontIntStyle, fontSize;
LabelStyle labelStyle;
String fontFamily, fontStyle;
XMLTag fontTag;
fillColor = ColorHelper.parseHexStandard(labelTag.getSubtagContent("color"));
outlineColor = ColorHelper.parseHexStandard(labelTag.getSubtagContent("outlineColor"));
fontTag = labelTag.getSubtag("font");
fontFamily = fontTag.getSubtagContent("family");
fontStyle = fontTag.getSubtagContent("style");
fontSize = Integer.parseInt(fontTag.getSubtagContent("size"));
if (fontStyle.equalsIgnoreCase("Bold")) {
fontIntStyle = Font.BOLD;
} else if (fontStyle.equalsIgnoreCase("Italic")) {
fontIntStyle = Font.ITALIC;
} else if (fontStyle.equalsIgnoreCase("Plain")) {
fontIntStyle = Font.PLAIN;
} else {
fontIntStyle = Font.PLAIN;
}
labelFont = new Font(fontFamily, fontIntStyle, fontSize);
labelStyle = new LabelStyle(fillColor, outlineColor, labelFont);
return labelStyle;
}
/**
* Creates a LatLonAltBox object from the XML LatLonAltBox.
*
* @param tag
* @return
*/
public static LatLonAltBox getLatLonAltBox(XMLTag tag) {
boolean hasMaxAltitude, hasMinAltitude;
float north, south, east, west, minAlt, maxAlt;
LatLonAltBox latLonAltBox;
hasMaxAltitude = tag.containsSubTag("maxAltitude");
hasMinAltitude = tag.containsSubTag("minAltitude");
north = Float.parseFloat(tag.getSubtagContent("north"));
south = Float.parseFloat(tag.getSubtagContent("south"));
east = Float.parseFloat(tag.getSubtagContent("east"));
west = Float.parseFloat(tag.getSubtagContent("west"));
if (hasMinAltitude) {
minAlt = Float.parseFloat(tag.getSubtagContent("minAltitude"));
} else {
minAlt = -1;
}
if (hasMaxAltitude) {
maxAlt = Float.parseFloat(tag.getSubtagContent("maxAltitude"));
} else {
maxAlt = -1;
}
latLonAltBox = new LatLonAltBox(north, south, east, west,minAlt, maxAlt);
return latLonAltBox;
}
/**
* Creates a LatLonBox object from the XML LatLonBox.
*
* @param tag
* @return
*/
public static LatLonBox getLatLonBox(XMLTag tag) {
float north, south, east, west;
LatLonBox latLonBox;
north = Float.parseFloat(tag.getSubtagContent("north"));
south = Float.parseFloat(tag.getSubtagContent("south"));
east = Float.parseFloat(tag.getSubtagContent("east"));
west = Float.parseFloat(tag.getSubtagContent("west"));
latLonBox = new LatLonBox(north, south, east, west);
return latLonBox;
}
/**
* Reads in XML for LevelOfDetail and returns a LevelOfDetail object.
*
* @param lodTag - FmXml tag containing the LevelOfDetail tag.
* @return
*/
public static LevelOfDetail getLevelOfDetail(XMLTag lodTag) {
float minLodPixels, maxLodPixels;
float minFadeExtent, maxFadeExtent;
LevelOfDetail lod;
if (lodTag.containsSubTag("minLodPixels")) {
minLodPixels = Float.parseFloat(lodTag.getSubtagContent("minLodPixels"));
} else {
minLodPixels = -1;
}
if (lodTag.containsSubTag("maxLodPixels")) {
maxLodPixels = Float.parseFloat(lodTag.getSubtagContent("maxLodPixels"));
} else {
maxLodPixels = -1;
}
if (lodTag.containsSubTag("minFadeExtent")) {
minFadeExtent = Float.parseFloat(lodTag.getSubtagContent("minFadeExtent"));
} else {
minFadeExtent = -1;
}
if (lodTag.containsSubTag("maxFadeExtent")) {
maxFadeExtent = Float.parseFloat(lodTag.getSubtagContent("maxFadeExtent"));
} else {
maxFadeExtent = -1;
}
lod = new LevelOfDetail(maxLodPixels, minLodPixels, maxFadeExtent, minFadeExtent);
return lod;
}
/**
* Reads in FmXml for a LinearRing and returns a LinearRing object.
*
* @param layer - Layer to add object to.
* @param placemarkTag - Tag containing the FmXML tag to be imported.
* @param coordinateSet - The NodeMap which this object references coordinates.
* @return
*/
public static LinearRing getLinearRing(VectorLayer layer,
XMLTag placemarkTag,
NodeMap coordinateSet) {
try {
boolean hasClassProperty;
boolean hasData, hasRef, hasRegion, hasTimestamps;
CoordinateList<Coordinate> coordinates;
HashMap<String,String> customDataFields;
LinearRing newRing;
String objectClass, coordinateString, description;
String objectName, id, timestamps;
XMLTag dataTag, ringTag;
description = removeCDataTag(placemarkTag.getSubtagContent("description"));
id = placemarkTag.getPropertyValue("id");
hasData = placemarkTag.containsSubTag("data");
hasRef = placemarkTag.containsSubTag("Ref");
hasRegion = placemarkTag.containsSubTag("Region");
coordinateString = placemarkTag.getSubtagContent("coordinates");
coordinates = getCoordinateList(coordinateSet, coordinateString);
hasTimestamps = placemarkTag.containsSubTag("gx:Timestamps");
hasClassProperty = (placemarkTag.getPropertyValue("class").length() > 0);
if (hasClassProperty) {
objectClass = placemarkTag.getPropertyValue("class");
objectName = id;
} else {
objectClass = id;
objectName = placemarkTag.getSubtagContent("name");
}
if (objectClass.startsWith("#")) objectClass = objectClass.substring(1);
newRing = new LinearRing(objectName, objectClass, coordinates);
newRing.setDescription(description);
if (hasRef)
newRing.setReference(Long.parseLong(placemarkTag.getSubtagContent("Ref")));
if (hasRegion) {
Region region = getRegion(placemarkTag.getSubtag("Region"));
Visibility vis = convertRegionToVisibility(region);
newRing.setVisibility(vis);
}
if (placemarkTag.containsSubTag("Visibility")) {
Visibility vis = getVisibility(placemarkTag.getSubtag("Visibility"));
newRing.setVisibility(vis);
}
if (hasTimestamps) {
timestamps = placemarkTag.getSubtagContent("gx:Timestamps");
newRing.setTimestamps(timestamps);
}
if (hasData) {
dataTag = placemarkTag.getSubtag("data");
customDataFields = getCustomDataFields(dataTag);
newRing.setCustomDataFields(customDataFields);
}
//Add the new object as a Parent for the Coordinates it uses.
coordinates.setParentObject(newRing);
return newRing;
} catch (Exception e) {
System.err.println("Error in FmXmlImporter.getLinearRing(VectorLayer, XMLTag) - " + e);
return null;
}
}
/**
* Reads FmXml for LineString and returns a LineString Object.
*
* @param layer - Layer to add object to.
* @param placemarkTag - Tag containing the FmXML tag to be imported.
* @param coordinateSet - The NodeMap which this object references coordinates.
* @return
*/
public static LineString getLineString(VectorLayer layer,
XMLTag placemarkTag,
NodeMap coordinateSet) {
try {
boolean hasClassProperty;
boolean hasData, hasRef, hasRegion, hasTimestamps;
CoordinateList<Coordinate> coordinates;
HashMap<String,String> customDataFields;
LineString newLine;
String coordinateString, description;
String objectClass, objectName, id, timestamps;
XMLTag dataTag, linestringTag;
description = removeCDataTag(placemarkTag.getSubtagContent("description"));
id = placemarkTag.getPropertyValue("id");
hasData = placemarkTag.containsSubTag("data");
hasRef = placemarkTag.containsSubTag("Ref");
hasRegion = placemarkTag.containsSubTag("Region");
coordinateString = placemarkTag.getSubtagContent("coordinates");
coordinates = getCoordinateList(coordinateSet, coordinateString);
hasTimestamps = placemarkTag.containsSubTag("gx:Timestamps");
hasClassProperty = (placemarkTag.getPropertyValue("class").length() > 0);
if (hasClassProperty) {
objectClass = placemarkTag.getPropertyValue("class");
objectName = id;
} else {
objectClass = id;
objectName = placemarkTag.getSubtagContent("name");
}
if (objectClass.startsWith("#")) objectClass = objectClass.substring(1);
newLine = new LineString(objectName, objectClass, coordinates);
newLine.setDescription(description);
if (hasRef)
newLine.setReference(Long.parseLong(placemarkTag.getSubtagContent("Ref")));
if (hasRegion) {
Region region = getRegion(placemarkTag.getSubtag("Region"));
Visibility vis = convertRegionToVisibility(region);
newLine.setVisibility(vis);
}
if (placemarkTag.containsSubTag("Visibility")) {
Visibility vis = getVisibility(placemarkTag.getSubtag("Visibility"));
newLine.setVisibility(vis);
}
if (hasTimestamps) {
timestamps = placemarkTag.getSubtagContent("gx:Timestamps");
newLine.setTimestamps(timestamps);
}
if (hasData) {
dataTag = placemarkTag.getSubtag("data");
customDataFields = getCustomDataFields(dataTag);
newLine.setCustomDataFields(customDataFields);
}
//Add the new object as a Parent for the Coordinates it uses.
coordinates.setParentObject(newLine);
if (coordinates.size() > 0) {
return newLine;
} else {
Logger.log(Logger.ERR, "Error in FmXmlImporter.getLineString(VectorLayer, XMLTag) - No Coordinate Data For Object: " + objectName);
return null;
}
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in FmXmlImporter.getLineString(VectorLayer, XMLTag) - " + e);
return null;
}
}
/**
* Reads in LineStyle XML and returns a LineStyle Object.
*
* @param styleTag
* @return
*/
public static LineStyle getLineStyle(XMLTag styleTag) {
try {
boolean hasStroke, hasVis, scaleWidth;
Color fillColor, outlineColor, selectedFillColor, selectedOutlineColor;
float lineWidth;
int outline;
LineStyle lineStyle;
String lineStroke, styleID, styleTagName;
XMLTag lineStyleTag;
styleTagName = styleTag.getTagName();
styleID = styleTagName.substring(styleTagName.indexOf("id=\"") + 4, styleTagName.length() - 1);
lineStyleTag = styleTag.getSubtag("LineStyle");
fillColor = ColorHelper.parseHexStandard(lineStyleTag.getSubtagContent("color"));
lineWidth = Float.parseFloat(lineStyleTag.getSubtagContent("width"));
outline = Integer.parseInt(lineStyleTag.getSubtagContent("outline"));
hasStroke = lineStyleTag.containsSubTag("lineStroke");
hasVis = styleTag.containsSubTag("Visibility");
if (hasStroke) {
lineStroke = lineStyleTag.getSubtagContent("lineStroke");
} else {
lineStroke = LineStyle.SOLID;
}
if (lineStyleTag.containsSubTag("scaleWidth")) {
scaleWidth = Boolean.parseBoolean(lineStyleTag.getSubtagContent("scaleWidth"));
} else {
scaleWidth = true;
}
lineStyle = new LineStyle(styleID, fillColor, lineWidth, lineStroke, scaleWidth);
if (hasVis) {
Visibility vis = getVisibility(styleTag.getSubtag("Visibility"));
lineStyle.setVisibility(vis);
}
if (lineStyleTag.containsSubTag("selectedFillColor")) {
selectedFillColor = ColorHelper.parseHexStandard(lineStyleTag.getSubtagContent("selectedFillColor"));
lineStyle.setSelectedFillColor(selectedFillColor);
}
if (outline == 1) {
if (lineStyleTag.containsSubTag("gx:outlineColor")) {
outlineColor = ColorHelper.parseHexStandard(lineStyleTag.getSubtagContent("gx:outlineColor"));
} else if (lineStyleTag.containsSubTag("outlineColor")) {
outlineColor = ColorHelper.parseHexStandard(lineStyleTag.getSubtagContent("outlineColor"));
} else {
outlineColor = new Color(68, 68, 68, 128);
}
if (lineStyleTag.containsSubTag("selectedOutlineColor")) {
selectedOutlineColor = ColorHelper.parseHexStandard(lineStyleTag.getSubtagContent("selectedOutlineColor"));
lineStyle.setSelectedOutlineColor(selectedOutlineColor);
}
lineStyle.setOutlineColor(outlineColor);
lineStyle.setOutline(true);
} else {
lineStyle.setOutline(false);
}
return lineStyle;
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in FmXmlImport.getLineStyle(XMLTag) - " + e);
return null;
}
}
/**
* Reads in FmXml for MapPoint and returns a MapPoint object.
*
* @param layer - Layer to add object to.
* @param placemarkTag - Tag containing the FmXML tag to be imported.
* @param coordinateSet - The NodeMap which this object references coordinates.
* @return
*/
public static MapPoint getMapPoint(VectorLayer layer,
XMLTag placemarkTag,
NodeMap coordinateSet) {
try {
boolean hasClassProperty;
boolean hasData, hasRef, hasRegion, hasTimestamps;
CoordinateList<Coordinate> coordinates;
HashMap<String,String> customDataFields;
MapPoint newPoint;
String coordinateString, description;
String objectClass, objectName, id, timestamps;
XMLTag dataTag, pointTag;
description = removeCDataTag(placemarkTag.getSubtagContent("description"));
id = placemarkTag.getPropertyValue("id");
hasData = placemarkTag.containsSubTag("data");
hasRef = placemarkTag.containsSubTag("Ref");
hasRegion = placemarkTag.containsSubTag("Region");
coordinateString = placemarkTag.getSubtagContent("coordinates");
coordinates = getCoordinateList(coordinateSet, coordinateString);
hasTimestamps = placemarkTag.containsSubTag("gx:Timestamps");
hasClassProperty = (placemarkTag.getPropertyValue("class").length() > 0);
if (hasClassProperty) {
objectClass = placemarkTag.getPropertyValue("class");
objectName = id;
} else {
objectClass = id;
objectName = placemarkTag.getSubtagContent("name");
}
if (objectClass.startsWith("#")) objectClass = objectClass.substring(1);
newPoint = new MapPoint(objectName, objectClass, description, coordinates);
if (hasRegion) {
Region region = getRegion(placemarkTag.getSubtag("Region"));
Visibility vis = convertRegionToVisibility(region);
newPoint.setVisibility(vis);
}
if (placemarkTag.containsSubTag("Visibility")) {
Visibility vis = getVisibility(placemarkTag.getSubtag("Visibility"));
newPoint.setVisibility(vis);
}
if (hasRef)
newPoint.setReference(Long.parseLong(placemarkTag.getSubtagContent("Ref")));
if (hasTimestamps) {
timestamps = placemarkTag.getSubtagContent("gx:Timestamps");
newPoint.setTimestamps(timestamps);
}
if (hasData) {
dataTag = placemarkTag.getSubtag("data");
customDataFields = getCustomDataFields(dataTag);
newPoint.setCustomDataFields(customDataFields);
}
//Add the new object as a Parent for the Coordinates it uses.
coordinates.setParentObject(newPoint);
if (coordinates.size() > 0) {
return newPoint;
} else {
Logger.log(Logger.ERR, "Error in FmXmlImporter.getMapPoint(VectorLayer, XMLTag) - No Coordinate Data For Object: " + objectName);
return null;
}
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in FmXmlImporter.getMapPoint(VectorLayer, XMLTag) - " + e);
return null;
}
}
/**
* Reads in FmXml for MultiGeometry and returns a MultiGeometry object.
*
* @param layer
* @param multiGeoTag
* @param coordinateSet
* @return
*/
public static MultiGeometry getMultiGeometry(VectorLayer layer,
XMLTag multiGeoTag,
NodeMap coordinateSet) {
ArrayList<XMLTag> objectTags;
boolean hasClassProperty, hasData, hasRef;
HashMap<String,String> customDataFields;
VectorObjectList<VectorObject> objects;
MultiGeometry newMulti;
String description, objectClass, objectName;
XMLTag dataTag;
try {
hasClassProperty = (multiGeoTag.getPropertyValue("class").length() > 0);
hasData = multiGeoTag.containsSubTag("data");
hasRef = multiGeoTag.containsSubTag("Ref");
description = removeCDataTag(multiGeoTag.getSubtagContent("description"));
objectTags = multiGeoTag.getSubtag("elements").getSubtags();
objects = getObjectsFromPlaceMarks(layer, objectTags, coordinateSet);
if (hasClassProperty) {
objectClass = multiGeoTag.getPropertyValue("class");
objectName = multiGeoTag.getPropertyValue("id");
} else {
objectClass = "";
objectName = multiGeoTag.getSubtagContent("name");
}
if (objectClass.startsWith("#")) objectClass = objectClass.substring(1);
newMulti = new MultiGeometry(objectName, objects);
if (description != null)
newMulti.setDescription(description);
if (multiGeoTag.containsSubTag("Visibility")) {
Visibility vis = getVisibility(multiGeoTag.getSubtag("Visibility"));
newMulti.setVisibility(vis);
}
if (hasData) {
dataTag = multiGeoTag.getSubtag("data");
customDataFields = getCustomDataFields(dataTag);
newMulti.setCustomDataFields(customDataFields);
}
return newMulti;
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in FmXmlImport.getMultiGeometry(VectorLayer, XMLTag) - " + e);
return null;
}
}
public static NetworkLayer getNetworkLayer(XMLTag layerTag) {
try {
boolean hasAddress, hasPointClass, hasRefreshInterval;
boolean hasRefreshMode, hasVisibility;
int refMode;
NetworkLayer networkLayer;
String address, description, layerName, refInterval;
String pointClass;
XMLTag descriptionTag;
hasAddress = layerTag.containsSubTag("href");
hasPointClass = layerTag.containsSubTag("PointClass");
hasRefreshInterval = layerTag.containsSubTag("RefreshInterval");
hasRefreshMode = layerTag.containsSubTag("RefreshMode");
hasVisibility = layerTag.containsSubTag("Visibility");
descriptionTag = layerTag.getSubtag("Description");
layerName = layerTag.getSubtagContent("Name");
if (hasAddress) {
address = layerTag.getSubtagContent("href");
} else {
address = "";
}
networkLayer = new NetworkLayer(layerName, address);
if (hasPointClass) {
pointClass = layerTag.getSubtagContent("PointClass");
networkLayer.setDefaultPointClass(pointClass);
}
if (hasRefreshInterval) {
refInterval = layerTag.getSubtagContent("RefreshInterval");
networkLayer.setRefreshInterval(Float.parseFloat(refInterval));
}
if (hasRefreshMode) {
networkLayer.setRefreshMode(layerTag.getSubtagContent("RefreshInterval"));
}
if (hasVisibility) {
Visibility vis = FmXmlImporter.getVisibility(layerTag.getSubtag("Visibility"));
networkLayer.setVisibility(vis.getMinTileZoomLevel(), vis.getMaxTileZoomLevel());
}
if (descriptionTag != null) {
description = removeCDataTag(descriptionTag.getTagContent());
networkLayer.setLayerDescription(description);
}
return networkLayer;
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in FmXml.getNetworkLayer(XMLTag) - " + e);
return null;
}
}
/**
* Creates MapObjects from FmXML code.
*
* @param layer
* @param coordinateSet - The NodeMap which this object references coordinates.
* @param placeMarkTags - An ArrayList containing PlaceMark XMLTags
* @return A collection of the new MapObjects created.
*/
public static VectorObjectList<VectorObject> getObjectsFromPlaceMarks(VectorLayer layer,
ArrayList<XMLTag> placeMarkTags,
NodeMap coordinateSet) {
try {
VectorObjectList<VectorObject> newObjects;
newObjects = new VectorObjectList<VectorObject>();
for (XMLTag currentPlaceMarkTag: placeMarkTags) {
newObjects.add(loadObject(layer, currentPlaceMarkTag, coordinateSet));
}
return newObjects;
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in FmXmlImpotrer.getObjectsFromPlaceMarks(VectorLayer, ArrayList<XMLTag>) - " + e);
return null;
}
}
/**
* Creates an OutlineStyle object from FmXML.
*
* @param outlineStyleTag - The XML tag for OutlineStyle.
* @return
*/
public static OutlineStyle getOutlineStyle(XMLTag outlineStyleTag) {
OutlineStyle outlineStyle;
String tagText;
//Create a default outline style
outlineStyle = new OutlineStyle();
try {
//Change the properties of the default style to match the XML code.
if (outlineStyleTag.containsSubTag("borderCondition"))
outlineStyle.setBorderCondition(outlineStyleTag.getSubtagContent("borderCondition"));
if (outlineStyleTag.containsSubTag("color")) {
tagText = outlineStyleTag.getSubtagContent("color");
outlineStyle.setColor(ColorHelper.parseHexStandard(tagText));
}
if (outlineStyleTag.containsSubTag("selectedColor")) {
tagText = outlineStyleTag.getSubtagContent("selectedColor");
outlineStyle.setSelectedColor(ColorHelper.parseHexStandard(tagText));
}
if (outlineStyleTag.containsSubTag("strokeStyle"))
outlineStyle.setStrokeStyle(outlineStyleTag.getSubtagContent("strokeStyle"));
if (outlineStyleTag.containsSubTag("width")) {
tagText = outlineStyleTag.getSubtagContent("width");
outlineStyle.setWidth(Float.parseFloat(tagText));
}
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in FmXmlImpotrer.getOutlineStyle(XMLTag) - " + e);
}
return outlineStyle;
}
/**
* Reads in FmXml for PhotoPoint and returns a PhotoPoint object.
*
* @param layer
* @param placemarkTag
* @param coordinateSet
* @return
*/
public static PhotoPoint getPhotoPoint(VectorLayer layer,
XMLTag placemarkTag,
NodeMap coordinateSet) {
try {
boolean hasClassProperty;
boolean hasData, hasRef, hasRegion, hasTimestamps;
CoordinateList<Coordinate> coordinates;
HashMap<String,String> customDataFields;
PhotoPoint newPoint;
String coordinateString, description;
String fileName, objectClass, objectName, id;
XMLTag dataTag, iconTag;
description = removeCDataTag(placemarkTag.getSubtagContent("description"));
id = placemarkTag.getPropertyValue("id");
hasData = placemarkTag.containsSubTag("data");
hasRef = placemarkTag.containsSubTag("Ref");
hasRegion = placemarkTag.containsSubTag("Region");
iconTag = placemarkTag.getSubtag("Icon");
coordinateString = placemarkTag.getSubtagContent("coordinates");
coordinates = getCoordinateList(coordinateSet, coordinateString);
hasTimestamps = placemarkTag.containsSubTag("gx:Timestamps");
hasClassProperty = (placemarkTag.getPropertyValue("class").length() > 0);
fileName = iconTag.getSubtagContent("href");
if (hasClassProperty) {
objectClass = placemarkTag.getPropertyValue("class");
objectName = id;
} else {
objectClass = id;
objectName = placemarkTag.getSubtagContent("name");
}
if (objectClass.startsWith("#")) objectClass = objectClass.substring(1);
newPoint = new PhotoPoint(objectName, coordinates.get(0), fileName);
newPoint.setClass(objectClass);
newPoint.setDescription(description);
if (hasRegion) {
Region region = getRegion(placemarkTag.getSubtag("Region"));
Visibility vis = convertRegionToVisibility(region);
newPoint.setVisibility(vis);
}
if (hasRef)
newPoint.setReference(Long.parseLong(placemarkTag.getSubtagContent("Ref")));
if (hasData) {
dataTag = placemarkTag.getSubtag("data");
customDataFields = getCustomDataFields(dataTag);
newPoint.setCustomDataFields(customDataFields);
}
//Add the new object as a Parent for the Coordinates it uses.
coordinates.setParentObject(newPoint);
if (coordinates.size() > 0) {
return newPoint;
} else {
Logger.log(Logger.ERR, "Error in FmXmlImporter.getPhotoPoint(VectorLayer, XMLTag) - No Coordinate Data For Object: " + objectName);
return null;
}
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in FmXmlImporter.getPhotoPoint(VectorLayer, XMLTag) - " + e);
return null;
}
}
/**
* Reads in FmXml for a Polygon and returns a Polygon Object.
*
* @param layer
* @param placemarkTag
* @param coordinateSet
* @return
*/
public static Polygon getPolygon(VectorLayer layer,
XMLTag placemarkTag,
NodeMap coordinateSet) {
try {
ArrayList<XMLTag> innerBoundaryTags;
boolean hasClassProperty;
boolean hasData, hasRef, hasRegion, hasTimestamps;
CoordinateList<Coordinate> coordinates;
HashMap<String,String> customDataFields;
Polygon newPolygon;
String coordinateString, description;
String objectClass, objectName, id, timestamps;
XMLTag dataTag, lineStringTag, outerBoundaryTag, polygonTag;
description = removeCDataTag(placemarkTag.getSubtagContent("description"));
id = placemarkTag.getPropertyValue("id");
hasData = placemarkTag.containsSubTag("data");
hasRegion = placemarkTag.containsSubTag("Region");
hasRef = placemarkTag.containsSubTag("Ref");
innerBoundaryTags = placemarkTag.getSubtagsByName("innerBoundaryIs");
hasTimestamps = placemarkTag.containsSubTag("gx:Timestamps");
hasClassProperty = (placemarkTag.getPropertyValue("class").length() > 0);
if (hasClassProperty) {
objectClass = placemarkTag.getPropertyValue("class");
objectName = id;
} else {
objectClass = id;
objectName = placemarkTag.getSubtagContent("name");
}
if (objectClass.startsWith("#")) objectClass = objectClass.substring(1);
if (placemarkTag.containsSubTag("outerBoundaryIs")) {
//Old legacy tag setup
outerBoundaryTag = placemarkTag.getSubtag("outerBoundaryIs");
lineStringTag = outerBoundaryTag.getSubtag("LinearRing");
coordinateString = lineStringTag.getSubtagContent("coordinates");
coordinates = getCoordinateList(coordinateSet, coordinateString);
} else if (placemarkTag.containsSubTag("outerBoundary")) {
//Net tag setup
outerBoundaryTag = placemarkTag.getSubtag("outerBoundary");
coordinateString = outerBoundaryTag.getSubtagContent("coordinates");
coordinates = getCoordinateList(coordinateSet, coordinateString);
} else {
coordinates = null;
}
if (coordinates != null) {
newPolygon = new Polygon(objectName, objectClass, coordinates);
newPolygon.setDescription(description);
if (hasRef)
newPolygon.setReference(Long.parseLong(placemarkTag.getSubtagContent("Ref")));
if (hasRegion) {
Region region = getRegion(placemarkTag.getSubtag("Region"));
Visibility vis = convertRegionToVisibility(region);
newPolygon.setVisibility(vis);
}
if (placemarkTag.containsSubTag("Visibility")) {
Visibility vis = getVisibility(placemarkTag.getSubtag("Visibility"));
newPolygon.setVisibility(vis);
}
if (hasTimestamps) {
timestamps = placemarkTag.getSubtagContent("gx:Timestamps");
newPolygon.setTimestamps(timestamps);
}
if (hasData) {
dataTag = placemarkTag.getSubtag("data");
customDataFields = getCustomDataFields(dataTag);
newPolygon.setCustomDataFields(customDataFields);
}
for(XMLTag ibTag: innerBoundaryTags)
newPolygon.addInnerBoundary(getInnerBoundary(coordinateSet, layer, ibTag));
//Add the new object as a Parent for the Coordinates it uses.
coordinates.setParentObject(newPolygon);
return newPolygon;
} else {
return null;
}
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in FmXmlImporter.getPolygon(VectorLayer, XMLTag) - " + e);
return null;
}
}
/**
* Reads PolygonStyle from XML and returns a PolygonStyle object.
*
* @param styleTag
* @return
*/
public static PolygonStyle getPolygonStyle(XMLTag styleTag) {
try {
boolean hasVis;
Color fillColor;
int colorMode, fill;
OutlineStyle outlineStyle;
PolygonStyle polygonStyle;
String colorModeString, featureType, styleID, styleTagName;
XMLTag outlineTag, polygonStyleTag;
styleTagName = styleTag.getTagName();
styleID = styleTagName.substring(styleTagName.indexOf("id=\"") + 4, styleTagName.length() - 1);
polygonStyleTag = styleTag.getSubtag("PolyStyle");
fillColor = ColorHelper.parseHexStandard(polygonStyleTag.getSubtagContent("color"));
colorModeString = polygonStyleTag.getSubtagContent("colorMode");
fill = Integer.parseInt(polygonStyleTag.getSubtagContent("fill"));
outlineTag = polygonStyleTag.getSubtag("outlines");
hasVis = polygonStyleTag.containsSubTag("Visibility");
if (colorModeString.equalsIgnoreCase("normal")) {
colorMode = ColorStyle.NORMAL;
} else {
colorMode = ColorStyle.RANDOM;
}
polygonStyle = new PolygonStyle(styleID, fillColor);
polygonStyle.setColorMode(colorMode);
if (hasVis) {
Visibility vis = getVisibility(polygonStyleTag.getSubtag("Visibility"));
polygonStyle.setVisibility(vis);
}
if (fill == 1) {
polygonStyle.setFill(true);
} else {
polygonStyle.setFill(false);
}
//Load Icon, if there is one.
if (polygonStyleTag.containsSubTag("Icon")) {
XMLTag iconTag = polygonStyleTag.getSubtag("Icon");
String href = iconTag.getSubtagContent("href");
polygonStyle.setImageFileName(href);
}
if (polygonStyleTag.containsSubTag("featureType")) {
featureType = polygonStyleTag.getSubtagContent("featureType");
} else {
featureType = ThemeConstants.UNKNOWN;
}
polygonStyle.setFeatureType(featureType);
//Read in OutlineStyles
if (outlineTag != null) {
if (outlineTag.containsSubTag("outlineStyle")) {
ArrayList<XMLTag> outlineStyleTags;
outlineStyleTags = outlineTag.getSubtagsByName("outlineStyle");
for (XMLTag tag: outlineStyleTags) {
outlineStyle = getOutlineStyle(tag);
polygonStyle.addOutlineStyle(outlineStyle);
}
polygonStyle.setOutline(true);
}
} else {
polygonStyle.setOutline(false);
}
return polygonStyle;
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in FmXmlImport.getPolygonStyle(XMLTag) - " + e);
return null;
}
}
/**
* Creates a Region object from FmXml code.
*
* @param regionTag
* @return
*/
public static Region getRegion(XMLTag regionTag) {
try {
boolean hasMaxAltitude, hasMinAltitude;
float north, south, east, west, minAlt, maxAlt;
LatLonAltBox latLonAltBox;
LevelOfDetail lod;
Region newRegion;
String regionName;
XMLTag latLonAltBoxTag, lodTag;
regionName = regionTag.getSubtagContent("Name");
latLonAltBoxTag = regionTag.getSubtag("LatLonAltBox");
lodTag = regionTag.getSubtag("Lod");
lod = getLevelOfDetail(lodTag);
hasMaxAltitude = latLonAltBoxTag.containsSubTag("maxAltitude");
hasMinAltitude = latLonAltBoxTag.containsSubTag("minAltitude");
north = Float.parseFloat(latLonAltBoxTag.getSubtagContent("north"));
south = Float.parseFloat(latLonAltBoxTag.getSubtagContent("south"));
east = Float.parseFloat(latLonAltBoxTag.getSubtagContent("east"));
west = Float.parseFloat(latLonAltBoxTag.getSubtagContent("west"));
if (hasMinAltitude) {
minAlt = Float.parseFloat(latLonAltBoxTag.getSubtagContent("minAltitude"));
} else {
minAlt = -1;
}
if (hasMaxAltitude) {
maxAlt = Float.parseFloat(latLonAltBoxTag.getSubtagContent("maxAltitude"));
} else {
maxAlt = -1;
}
latLonAltBox = new LatLonAltBox(north, south, east, west, minAlt, maxAlt);
newRegion = new Region(regionName, latLonAltBox, lod);
return newRegion;
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in FmXmlImporter.getRegion(XMLTag) - " + e);
return null;
}
}
/**
* Loads a ColorStyle from a given style XMLTag
*
* @param styleTag
* @return
*/
public static ColorStyle getStyle(XMLTag styleTag) {
ColorStyle style = null;
LabelStyle labelStyle;
XMLTag labelTag;
try {
if (styleTag.containsSubTag("IconStyle")) {
style = getIconStyle(styleTag);
} else if (styleTag.containsSubTag("LineStyle")) {
style = getLineStyle(styleTag);
} else if (styleTag.containsSubTag("PolyStyle")) {
style = getPolygonStyle(styleTag);
}
if (styleTag.containsSubTag("labelStyle")) {
labelTag = styleTag.getSubtag("labelStyle");
labelStyle = getLabelStyle(labelTag);
style.setLabel(labelStyle);
}
return style;
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in FmXmlImporter.getStyle(XmlTag) - " + e);
return null;
}
}
/**
* Creates a TileLayer object from the FmXML for TileLayer.
*
* @param layerTag
* @return
*/
public static TileLayer getTileLayer(XMLTag layerTag) {
try {
boolean visible;
String extension, layerDescription, layerName, tileLocation;
TileSource tileSource;
XMLTag descriptionTag, tileSourceTag;
descriptionTag = layerTag.getSubtag("Description");
layerName = layerTag.getSubtagContent("Name");
tileSourceTag = layerTag.getSubtag("TileSource");
tileLocation = tileSourceTag.getSubtagContent("href");
extension = tileLocation.substring(tileLocation.lastIndexOf("."));
if (descriptionTag != null) {
layerDescription = removeCDataTag(layerTag.getSubtagContent("Description"));
} else {
layerDescription = "";
}
if (layerTag.containsSubTag("visible")) {
visible = Boolean.parseBoolean(layerTag.getSubtagContent("visible"));
} else {
visible = true;
}
if (extension.toLowerCase().equalsIgnoreCase(".mbtiles")) {
tileSource = new MbTileSource(tileLocation);
} else if (tileLocation.toLowerCase().startsWith("http")) {
tileSource = new TileServerTileSource(tileLocation, layerName);
} else if (tileLocation.lastIndexOf(".com") > 0) {
tileSource = new TileServerTileSource(tileLocation, layerName);
} else {
tileSource = new DirectoriesTileSource(tileLocation);
}
return new TileLayer(layerName, layerDescription, visible, tileSource);
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in FmXmlImporter.getTileLayer(XmlTag) - " + e);
return null;
}
}
/**
* Loads a layer from a file.
*
* @param openedMap
* @param layerTag
* @param coordinateSet
* @return
*/
public static VectorLayer getVectorLayer(DigitalMap openedMap,
XMLTag layerTag,
NodeMap coordinateSet) {
try {
ArrayList<XMLTag> objects;
boolean layerLocked;
VectorObject newObject;
String layerDescription, layerName, timeSpanBegin, timeSpanEnd;
VectorLayer newLayer;
XMLTag tempTag, descriptionTag, timeSpanTag;
descriptionTag = layerTag.getSubtag("Description");
layerName = layerTag.getSubtagContent("Name");
layerDescription = removeCDataTag(layerTag.getSubtagContent("Description"));
layerLocked = Boolean.parseBoolean(layerTag.getSubtagContent("locked"));
objects = layerTag.getTagSubtags("objects");
timeSpanTag = layerTag.getSubtag("TimeSpan");
newLayer = new VectorLayer(layerName); //create new VectorLayer
newLayer.setParentMap(openedMap);
//description uses HTML
if (layerDescription.equals("") && (descriptionTag != null))
layerDescription = descriptionTag.getSubtagsAsString();
//load timespan
if (timeSpanTag != null) {
timeSpanBegin = timeSpanTag.getSubtagContent("begin");
timeSpanEnd = timeSpanTag.getSubtagContent("end");
newLayer.setTimeSpanBegin(timeSpanBegin);
newLayer.setTimeSpanEnd(timeSpanEnd);
}
newLayer.setLocked(layerLocked);
newLayer.setLayerDescription(layerDescription);
for (XMLTag currentTag: objects) {
newObject = loadObject(newLayer, currentTag, coordinateSet);
if (newObject != null)
newLayer.addObject(newObject);
}
return newLayer;
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in FmXmlImport.getVectorLayer(DigitalMap, XMLTag, NodeMap) - " + e);
return null;
}
}
/**
* Parses the FmXml for Visibility and returns a Visibility object.
*
* @param visTag
* @return
*/
public static Visibility getVisibility(XMLTag visTag) {
float max, min;
boolean hasMax = visTag.containsSubTag("maxTileZoom");
boolean hasMin = visTag.containsSubTag("minTileZoom");
if (hasMax) {
max = Float.parseFloat(visTag.getSubtagContent("maxTileZoom"));
} else {
max = 25;
}
if (hasMin) {
min = Float.parseFloat(visTag.getSubtagContent("minTileZoom"));
} else {
min = 0;
}
return new Visibility(max, min);
}
/**
* Reads in a FmXml PlaceMark and returns a VectorObject representing it.
*
* @param layer
* @param objectTag
* @param coordinateSet
* @return
*/
public static VectorObject loadObject(VectorLayer layer,
XMLTag objectTag,
NodeMap coordinateSet) {
VectorObject newObject;
try {
if (objectTag.nameStartsWith("MultiGeometry")) {
newObject = getMultiGeometry(layer, objectTag, coordinateSet);
} else if (objectTag.nameStartsWith("PhotoPoint")) {
newObject = getPhotoPoint(layer, objectTag, coordinateSet);
} else if (objectTag.nameStartsWith("Polygon")) {
newObject = getPolygon(layer, objectTag, coordinateSet);
} else if (objectTag.nameStartsWith("Point")) {
newObject = getMapPoint(layer, objectTag, coordinateSet);
} else if (objectTag.nameStartsWith("LineString")) {
newObject = getLineString(layer, objectTag, coordinateSet);
} else if (objectTag.nameStartsWith("LinearRing")) {
newObject = getLinearRing(layer, objectTag, coordinateSet);
} else {
newObject = null;
}
return newObject;
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in FmXmlImporter.loadObject(VectorLayer, XmlTag, NodeMap) - " + e);
return null;
}
}
/**
* Static shortcut to load a map.
*
* @param mapFile
* @param progressIndicator
* @return
*/
public static DigitalMap openFile(File mapFile, ProgressIndicator progressIndicator) {
FmXmlImporter importer = new FmXmlImporter();
return importer.importAsMap(mapFile, progressIndicator);
}
/**
* Loads a FmXml file
*
* @param mapFile
* @param progressIndicator
* @return
*/
@Override
public DigitalMap importAsMap(File mapFile, ProgressIndicator progressIndicator) {
ArrayList<XMLTag> nodes, styleTags;
ColorStyle currentStyle;
DigitalMap mainMap;
float alt, lat, lon;
NodeMap coordinateSet;
Layer currentLayer;
MapProjection mapProjection;
MapTheme mapTheme;
String currentTagName, mapDescription, mapName;
String projection, viewInfo;
StringTokenizer st;
XMLParser mapXMLParser;
XMLTag documentTag, layers, mapStyle;
mainMap = new DigitalMap();
mainMap.setMapFile(mapFile);
if (progressIndicator == null)
progressIndicator = new ProgressBarPanel();
try {
progressIndicator.setVisible(true);
progressIndicator.updateProgress("Reading Map Information", 5);
mapXMLParser = new XMLParser(new FileReader(mapFile));
documentTag = mapXMLParser.parseDocument();
mapName = documentTag.getSubtagContent("name");
mapDescription = documentTag.getSubtagContent("description");
viewInfo = documentTag.getSubtagContent("view");
layers = documentTag.getSubtag("layers");
st = new StringTokenizer(viewInfo, ",");
lon = Float.parseFloat(st.nextToken());
lat = Float.parseFloat(st.nextToken());
alt = TileMath.getVectorMapZoom((int) Float.parseFloat(st.nextToken()));
projection = documentTag.getSubtagContent("projection");
nodes = documentTag.getTagSubtags("nodes");
if (nodes.size() > 0) {
coordinateSet = new NodeMap((int) (nodes.size() * 1.5f));
} else {
coordinateSet = new NodeMap(1000);
}
if (projection.equalsIgnoreCase("Mercator")) {
mapProjection = new MercatorProjection(lat, lon, alt);
} else {
//default to Mercator
mapProjection = new MercatorProjection(lat, lon, alt);
}
mainMap = new DigitalMap(mapName, mapProjection);
if (nodes.size() > 0) {
//has node tags
progressIndicator.updateProgress("Reading Nodes", 10);
parseNodes(coordinateSet, nodes);
mainMap.setCoordinateSet(coordinateSet);
} else {
//does not have node tags, do nothing
}
//read in styles
progressIndicator.updateProgress("Reading Styles", 35);
mapTheme = new MapTheme("Map File Theme");
mainMap.setTheme(mapTheme, null, progressIndicator);
mainMap.getMapThemeManager().addTheme(mapTheme);
mapStyle = documentTag.getSubtag("mapstyle");
styleTags = mapStyle.getTags("Style");
for (XMLTag currentTag: styleTags) {
currentTagName = currentTag.getTagName();
if (currentTagName.startsWith("Style")) {
if (currentTag.getSubtag("BackColor") != null) {
Color backColor = ColorHelper.parseHexStandard(currentTag.getSubtagContent("BackColor"));
mapTheme.setBackgroundColor(backColor);
} else if (currentTag.containsSubTag("ColorRamp")) {
ColorRamp colorRamp;
colorRamp = getColorRamp(currentTag.getTagValue(), currentTag.getSubtag("ColorRamp"));
mapTheme.addColorRamp(colorRamp);
} else {
currentStyle = getStyle(currentTag);
if (currentStyle != null)
mapTheme.addStyleElement(currentStyle);
}
}
}
//read in layers
progressIndicator.updateProgress("Reading Layers", 75);
for (XMLTag layerTag: layers.getSubtags()) {
currentLayer = null;
if (layerTag.getTagName().equalsIgnoreCase("vectorlayer")) {
currentLayer = getVectorLayer(mainMap, layerTag, coordinateSet);
} else if (layerTag.getTagName().equalsIgnoreCase("heatmap")) {
currentLayer = getHeatMapLayer(mainMap, layerTag);
} else if (layerTag.getTagName().equalsIgnoreCase("networklayer")) {
currentLayer = getNetworkLayer(layerTag);
} else if (layerTag.getTagName().equalsIgnoreCase("tilelayer")) {
currentLayer = getTileLayer(layerTag);
}
if (currentLayer != null)
mainMap.addLayer(currentLayer);
}
if (!coordinateSet.isEmpty())
mainMap.setCoordinateSet(coordinateSet);
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in FmXmlImporter.openFile(File) - " + e);
}
mainMap.setMapFile(mapFile);
progressIndicator.updateProgress("Map Loaded", 98);
progressIndicator.finish();
return mainMap;
}
/**
* 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 {
throw new UnsupportedOperationException("Not supported yet.");
}
/**
* Parses Node tags and places them in the coordinateSet HashMap
*
* @param coordinateSet
* @param nodeTags
*/
public static void parseNodes(NodeMap coordinateSet,
ArrayList<XMLTag> nodeTags) {
Coordinate coordinate;
long nodeId;
try {
for (XMLTag tag: nodeTags) {
nodeId = Long.parseLong(tag.getTagValue());
coordinate = new Coordinate(tag.getTagContent());
if (nodeId > 0 && coordinate != null) {
//coordinate.setId(nodeId);
coordinateSet.put(nodeId, coordinate);
}
}
} catch (Exception e) {
Logger.log(Logger.ERR, "Error in FmXmlImporter.parseNodes(HashMap, ArrayList) - " + e);
}
}
/**
* Removes the CDataTag from the passed text.
*
* @param text
* @return
*/
public static String removeCDataTag(String text) {
String cleanText;
cleanText = text.replace("<![CDATA[", "");
cleanText = cleanText.replace("]]>", "");
return cleanText;
}
}