/*******************************************************************************
* Copyright (c) 2010 Stefan A. Tzeggai.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors:
* Stefan A. Tzeggai - initial API and implementation
******************************************************************************/
package org.geopublishing.atlasViewer.dp;
import java.awt.Font;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.log4j.Logger;
import org.geopublishing.atlasViewer.AtlasCancelException;
import org.geopublishing.atlasViewer.AtlasConfig;
import org.geopublishing.atlasViewer.GpCoreUtil;
import org.geopublishing.atlasViewer.dp.layer.DpLayer;
import org.geopublishing.atlasViewer.dp.layer.DpLayerRaster;
import org.geopublishing.atlasViewer.dp.layer.DpLayerRaster_Reader;
import org.geopublishing.atlasViewer.dp.layer.DpLayerVectorFeatureSource;
import org.geopublishing.atlasViewer.dp.layer.DpLayerVectorFeatureSourceShapefile;
import org.geopublishing.atlasViewer.dp.layer.LayerStyle;
import org.geopublishing.atlasViewer.dp.media.DpMediaPDF;
import org.geopublishing.atlasViewer.dp.media.DpMediaPICTURE;
import org.geopublishing.atlasViewer.dp.media.DpMediaVideo;
import org.geopublishing.atlasViewer.exceptions.AtlasException;
import org.geopublishing.atlasViewer.exceptions.AtlasFatalException;
import org.geopublishing.atlasViewer.exceptions.AtlasImportException;
import org.geopublishing.atlasViewer.exceptions.AtlasRecoverableException;
import org.geopublishing.atlasViewer.internal.AMLUtil;
import org.geopublishing.atlasViewer.map.Map;
import org.geopublishing.atlasViewer.map.MapPool;
import org.geopublishing.atlasViewer.map.MapRef;
import org.geopublishing.atlasViewer.swing.AVSwingUtil;
import org.geopublishing.atlasViewer.swing.AtlasViewerGUI;
import org.geopublishing.geopublisher.AtlasConfigEditable;
import org.geotools.feature.NameImpl;
import org.geotools.filter.text.cql2.CQLException;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import rachel.ResourceManager;
import rachel.loader.ResourceLoaderManager;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;
import de.schmitzm.geotools.LogoPosition;
import de.schmitzm.geotools.data.amd.AttributeMetadataImpl;
import de.schmitzm.geotools.data.amd.AttributeMetadataMap;
import de.schmitzm.geotools.data.rld.RasterLegendData;
import de.schmitzm.geotools.feature.FeatureUtil;
import de.schmitzm.geotools.gui.GridPanelFormatter;
import de.schmitzm.geotools.gui.ScalePanel.ScaleUnits;
import de.schmitzm.geotools.io.GeoImportUtil;
import de.schmitzm.i18n.Translation;
import de.schmitzm.jfree.chart.style.ChartStyle;
import de.schmitzm.jfree.chart.style.ChartStyleUtil;
import de.schmitzm.jfree.feature.style.FeatureChartStyle;
import de.schmitzm.jfree.feature.style.FeatureChartUtil;
import de.schmitzm.lang.LangUtil;
import de.schmitzm.swing.swingworker.AtlasStatusDialogInterface;
public class AMLImport {
private static final Logger LOGGER = Logger.getLogger(AMLImport.class);
private static AtlasStatusDialogInterface statusDialog;
/**
* If set to <code>true</code> by {@link #checkUpgrades(Node)},
* {@link AMLImport} will try to convert the filters automatically OR throw
* them away if conversion not possible.
**/
private static boolean upgradeFromPreGP13 = false;
/**
* If set to <code>true</code> empty Strings will be added as NODATA Values
* for every String attribute.
**/
private static boolean upgradeFromPreGP14 = false;
/**
* If set to <code>true</code> all HTML files are checked for wrong color
* HEX statement.
**/
protected static boolean upgradeFromPreGP17 = false;
static void info(String msg) {
if (statusDialog != null)
statusDialog.setDescription(msg);
}
/**
* Report a warning to the GUI status dialog, if a status dialog is
* available. Otherwise logs the warning.
*
* @param topic
* @param msg
*/
static void warn(String topic, String msg) {
if (statusDialog != null)
statusDialog.warningOccurred(topic, null, msg);
else
LOGGER.warn(topic + ":" + msg);
}
/**
* Parses Atlas XML file and returns a DOM document. If validating is true,
* the contents is validated against the XSD specified in the file.
*/
public DocumentBuilder getDocumentBuilder() throws SAXException,
IOException, ParserConfigurationException {
// Create a builder factory
final DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
factory.setNamespaceAware(true);
factory.setValidating(false);
final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";
// factory.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
// Create the builder and parse the file
final DocumentBuilder documentBuilder = factory.newDocumentBuilder();
documentBuilder.setErrorHandler(new ErrorHandler() {
public void error(final SAXParseException exception)
throws SAXException {
LOGGER.error("ErrorHandler.error", exception);
throw exception;
}
public void fatalError(final SAXParseException exception)
throws SAXException {
LOGGER.error("ErrorHandler.fataError", exception);
throw exception;
}
public void warning(final SAXParseException exception)
throws SAXException {
LOGGER.warn("ErrorHandler.warning", exception);
}
});
factory.isValidating();
return documentBuilder;
}
/**
* Creates a {@link AtlasConfig} from AtlasML
*
* The {@link ResourceManager} is responsible to deliver the
* <code>ad/atlas.xml</code> and has to be set up before!
*
* @param statusDialog
*
* @param atlasConfig
* needs be have a {@link ResourceLoaderManager} set up, so that
* atlas.xml can be found!
*/
public void parseAtlasConfig(AtlasStatusDialogInterface statusDialog,
final AtlasConfig atlasConfig, boolean validate)
throws IOException, AtlasException {
AMLImport.statusDialog = statusDialog;
final InputStream atlasXmlAsStream = atlasConfig
.getResourceAsStream(AtlasConfig.ATLASDATA_DIRNAME + "/"
+ AtlasConfig.ATLAS_XML_FILENAME);
if (atlasXmlAsStream == null) {
throw new AtlasFatalException(
GpCoreUtil.R("AmlImport.error.cant_find_atlas.xml"));
}
/**
* If validation is requested, we first check for the reachability of
* the AtlasML.xsd. The atlas.xml defines
* http://localhost:7272/skrueger/atlas/resource/AtlasML.xsd as the XSD
* location. But the port of the running Webserver might actually be
* different. So we first check whether the XSD can be found before the
* parser fails.
* http://localhost:7272/skrueger/atlas/resource/AtlasML.xsd
*/
try {
DocumentBuilder db = getDocumentBuilder();
Document xml = db.parse(atlasXmlAsStream);
parseAtlasConfig(atlasConfig, xml);
} catch (final SAXException ex) {
LOGGER.error("Validation failed with a SAXException..");
// TODO Sometimes we start the software when another webserver is
// running and providing the Schema. But when we reach here, the
// second webserver has been closed and the Schema is not available
// anymore. Maybe we should just start a webserver here
throw new AtlasImportException(ex);
} catch (ParserConfigurationException e) {
throw new AtlasImportException(e);
}
}
/**
* Parse the given atlas.gpa into an {@link AtlasConfig}. It will also
*
* @param atlasConfigEditable
* @param atlasDir
* a {@link File} pointing to either <code>atlas.gpa</code> or
* the folder containing an <code>atlas.gpa</code>
*/
public AtlasConfigEditable parseAtlasConfig(
AtlasStatusDialogInterface statusDialog, File atlasDir)
throws AtlasException {
if (!atlasDir.isDirectory())
atlasDir = atlasDir.getParentFile();
AMLImport.statusDialog = statusDialog;
AtlasConfigEditable atlasConfig = new AtlasConfigEditable(atlasDir);
try {
Document xml;
DocumentBuilder builder = getDocumentBuilder();
File atlasXmlFile = new File(atlasDir,
AtlasConfig.ATLASDATA_DIRNAME + "/"
+ AtlasConfig.ATLAS_XML_FILENAME);
xml = builder.parse(atlasXmlFile);
parseAtlasConfig(atlasConfig, xml);
return atlasConfig;
} catch (final Exception ex) {
throw new AtlasImportException(ex);
}
}
/**
* Parse/fill the given {@link AtlasConfig} instance from
* {@link org.w3c.dom.Document}. This method does also look for a file with
* a default CRS definition and extra fonts.
*
* @throws AtlasException
*/
public final void parseAtlasConfig(final AtlasConfig ac, final Document xml)
throws AtlasException {
readDefaultCRS(ac);
NodeList nodes;
// LOGGER.debug("Parsing DOM to AtlasConfig...");
// Checking options for gphoster
nodes = xml
.getElementsByTagNameNS(AMLUtil.AMLURI, AMLUtil.TAG_GPHOSTER);
if (nodes.getLength() != 0) {
Node gpHosterNode = nodes.item(0);
if (gpHosterNode.getAttributes().getNamedItem(AMLUtil.ATT_AUTH) != null) {
ac.setGpHosterAuth((Boolean.parseBoolean(gpHosterNode
.getAttributes().getNamedItem(AMLUtil.ATT_AUTH)
.getTextContent())));
}
}
// Checking the GP version this atlas.xml has been created with
nodes = xml.getElementsByTagNameNS(AMLUtil.AMLURI, "atlas");
Node atlasNode = nodes.item(0);
checkUpgrades(atlasNode);
// Read the jnlpBaseUrl attribute (since 1.6)
if (atlasNode.getAttributes().getNamedItem(AMLUtil.ATT_jnlpBaseUrl) != null) {
ac.setJnlpBaseUrl(atlasNode.getAttributes()
.getNamedItem(AMLUtil.ATT_jnlpBaseUrl).getTextContent());
}
// Read the atlasBaseName attribute (since 1.7)
final Node atlasBasenameXMLItem = atlasNode.getAttributes()
.getNamedItem(AMLUtil.ATT_atlasBasename);
if (atlasBasenameXMLItem != null) {
ac.setBaseName(atlasNode.getAttributes()
.getNamedItem(AMLUtil.ATT_atlasBasename).getTextContent());
} else {
String burl = ac.getJnlpBaseUrl();
if (burl != null) {
// In v1.6 the basename was stored in the last part of the URL
ac.setBaseName(burl.substring(
burl.substring(0, burl.length() - 1).lastIndexOf("/") + 1,
burl.length() - 1));
}
}
// Read the mapLogoPosition attribute (since 1.7)
if (atlasNode.getAttributes().getNamedItem(AMLUtil.ATT_maplogoPosition) != null) {
ac.setMaplogoPosition(LogoPosition.valueOf(atlasNode
.getAttributes().getNamedItem(AMLUtil.ATT_maplogoPosition)
.getTextContent()));
}
// parsing name, desc, creator and copyright
nodes = xml.getElementsByTagNameNS(AMLUtil.AMLURI, "name");
ac.setTitle(AMLImport.parseTranslation(ac.getLanguages(), nodes.item(0)));
nodes = xml.getElementsByTagNameNS(AMLUtil.AMLURI, "desc");
ac.setDesc(AMLImport.parseTranslation(ac.getLanguages(), nodes.item(0)));
nodes = xml.getElementsByTagNameNS(AMLUtil.AMLURI, "creator");
ac.setCreator(AMLImport.parseTranslation(ac.getLanguages(),
nodes.item(0)));
nodes = xml.getElementsByTagNameNS(AMLUtil.AMLURI, "copyright");
ac.setCopyright(AMLImport.parseTranslation(ac.getLanguages(),
nodes.item(0)));
// aml:atlasversion
ac.setAtlasversion(Float.valueOf(xml
.getElementsByTagNameNS(AMLUtil.AMLURI, "atlasversion").item(0)
.getFirstChild().getNodeValue()));
// aml:supportedLanguages
// aml:language lang="de"
// aml:language lang="en"
final Node supportedLanguagesNode = xml.getElementsByTagNameNS(
AMLUtil.AMLURI, "supportedLanguages").item(0);
nodes = supportedLanguagesNode.getChildNodes();
for (int i = 0; i < nodes.getLength(); i++) {
final Node languageNode = nodes.item(i);
if (languageNode.getLocalName() == null)
continue;
final String langCode = languageNode.getAttributes()
.getNamedItem("lang").getNodeValue();
// LOGGER.debug("aml:supportedLanguages: adding " + langCode);
ac.getLanguages().add(langCode);
}
// LOGGER.debug("Starting to parse rasters...");
// "normal" aml:rasterLayer
final NodeList rasterLayers = xml.getElementsByTagNameNS(
AMLUtil.AMLURI, "rasterLayer");
for (int i = 0; i < rasterLayers.getLength(); i++) {
final Node node = rasterLayers.item(i);
final DpLayerRaster<?, ChartStyle> raster = AMLImport
.parseDatapoolLayerRaster(node, ac);
ac.getDataPool().add(raster);
}
// LOGGER.debug("Starting to parse pyramid layers...");
// aml:rasterPyramidLayer
// final NodeList rasterPyramidLayers = xml.getElementsByTagNameNS(
// AMLUtil.AMLURI, "pyramidRasterLayer");
// for (int i = 0; i < rasterPyramidLayers.getLength(); i++) {
// final Node node = rasterPyramidLayers.item(i);
// final DpLayerRasterPyramid pyramid = AMLImport
// .parseDatapoolLayerRasterPyramid(node, ac);
// ac.getDataPool().add(pyramid);
// }
// LOGGER.debug("Starting to parse vector layers...");
// aml:vectorLayer
final NodeList vectorLayer = xml.getElementsByTagNameNS(AMLUtil.AMLURI,
"vectorLayer");
for (int i = 0; i < vectorLayer.getLength(); i++) {
final Node node = vectorLayer.item(i);
final DpLayerVectorFeatureSource vector = AMLImport
.parseDatapoolLayerVector(node, ac);
ac.getDataPool().add(vector);
// LOGGER.info("Importing vector " + vector.getTitle()
// + " via the new FeatureSource format!");
}
// LOGGER.debug("Starting to parse video layers...");
// aml:videoMedia
final NodeList videoMedia = xml.getElementsByTagNameNS(AMLUtil.AMLURI,
"videoMedia");
for (int i = 0; i < videoMedia.getLength(); i++) {
final Node node = videoMedia.item(i);
final DpMediaVideo vector = AMLImport.parseDatapoolMediaVideo(node,
ac);
ac.getDataPool().add(vector);
}
// LOGGER.debug("Starting to parse PDF layers...");
// aml:pdfMedia
final NodeList pdfMedia = xml.getElementsByTagNameNS(AMLUtil.AMLURI,
"pdfMedia");
for (int i = 0; i < pdfMedia.getLength(); i++) {
final Node node = pdfMedia.item(i);
final DpMediaPDF pdf = AMLImport.parseDatapoolPdfVideo(node, ac);
ac.getDataPool().add(pdf);
}
// LOGGER.debug("Starting to parse Picture layers...");
// aml:pictureMedia
final NodeList pictureMedia = xml.getElementsByTagNameNS(AMLUtil.AMLURI,
"pictureMedia");
for (int i = 0; i < pictureMedia.getLength(); i++) {
final Node node = pictureMedia.item(i);
final DpMediaPICTURE picture = AMLImport.parseDatapoolPicture(node, ac);
ac.getDataPool().add(picture);
}
// LOGGER.debug("Starting to parse maps...");
// aml:mapPool
final Node rootMapPoolNode = xml.getElementsByTagNameNS(AMLUtil.AMLURI,
"mapPool").item(0);
if (rootMapPoolNode != null) {
ac.setMapPool(AMLImport.parseMapPool(rootMapPoolNode, ac));
Node startMapAttrib = rootMapPoolNode.getAttributes().getNamedItem(
"startMap");
if (startMapAttrib != null) {
ac.getMapPool().setStartMapID(startMapAttrib.getNodeValue());
}
} else
LOGGER.info("No <aml:group> defined in the atlas.xml, but group is optional");
final Node rootGroupNode = xml.getElementsByTagNameNS(AMLUtil.AMLURI,
"group").item(0);
if (rootGroupNode != null) {
final Group firstGroup = AMLImport.parseGroup(rootGroupNode, ac);
// LOGGER.debug("Setting first group = "
// + firstGroup.getTitle().toOneLine());
ac.setRootGroup(firstGroup);
} else
LOGGER.info("No <aml:group> defined in the atlas.xml, but group is optional");
// Check if any extra fonts are defined
final Node rootFontsNode = xml.getElementsByTagNameNS(AMLUtil.AMLURI,
AMLUtil.TAG_FONTS).item(0);
if (rootFontsNode != null) {
parseFonts(ac, rootFontsNode);
}
ac.registerFonts();
}
protected void parseFonts(AtlasConfig ac, Node rootFontsNode) {
try {
final NodeList childNodes = rootFontsNode.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node childNode = childNodes.item(i);
if (!AMLUtil.TAG_FONT.equals(childNode.getLocalName()))
continue;
String relFontPath = childNode.getAttributes()
.getNamedItem(AMLUtil.ATT_FONT_FILENAME)
.getTextContent();
String resourceLocation = AtlasConfig.ATLASDATA_DIRNAME + "/"
+ AtlasConfig.FONTS_DIRNAME + "/" + relFontPath;
InputStream is = ac.getResourceAsStream(resourceLocation);
if (is == null) {
warn("Fonts", "The font " + relFontPath
+ " could not be found at " + resourceLocation);
} else
try {
Font font = Font.createFont(Font.TRUETYPE_FONT, is);
ac.getFonts().add(font);
LOGGER.info("Registered a new TTF font: "
+ font.getName());
} catch (Exception e) {
LOGGER.error("Couldn't load or register font "
+ relFontPath, e);
}
}
} catch (Exception e) {
LOGGER.error("Failed to parseFonts", e);
}
}
/**
* Checking the version of the atlas.xml against the version of this GP. If
* upgrade changes are necessary, the needed flags are set here.
*
* @param maj
* @param min
* @param build
*/
private static void checkUpgrades(Node atlasNode) {
Node nodeMajVersion = atlasNode.getAttributes().getNamedItem(
AMLUtil.ATT_majVersion);
Node nodeMinVersion = atlasNode.getAttributes().getNamedItem(
AMLUtil.ATT_minVersion);
// if no version information is defined in atlas.xml, we assume it's
// 1.2 b1, because versioning has been introduced in 1.3
int maj = nodeMajVersion == null ? 1 : Integer.valueOf(nodeMajVersion
.getNodeValue().toString());
int min = nodeMinVersion == null ? 2 : Integer.valueOf(nodeMinVersion
.getNodeValue().toString());
// Check if the filters have to be converted from MartinFilters to ECQL
double majMin = new Double(maj) + new Double(min) / 10.;
if (majMin < 1.3) {
upgradeFromPreGP13 = true;
LOGGER.info("atlas.xml has been created with a version prior to 1.3. Filters will be converted to CQL!");
}
if (majMin < 1.4) {
upgradeFromPreGP14 = true;
LOGGER.info("atlas.xml has been created with a version prior to 1.4. \"\" NODATA values for Strings will be added automatically.");
}
if (majMin < 1.7) {
upgradeFromPreGP17 = true;
LOGGER.info("atlas.xml has been created with a version prior to 1.7. HTML files are check/corrected for wrong color HEX values");
}
}
/**
* Looks for a file called {@link AtlasConfig#DEFAULTCRS_FILENAME} in
* ad-folder containing a default CRS definition in the atlas. If found,
* it's applied to
* {@link GeoImportUtil#setDefaultCRS(org.opengis.referencing.crs.CoordinateReferenceSystem)}
*/
public static void readDefaultCRS(AtlasConfig atlasConfig) {
String resourceLocation = AtlasConfig.ATLASDATA_DIRNAME + "/"
+ AtlasConfig.DEFAULTCRS_FILENAME;
URL defaultCrsUrl = atlasConfig.getResource(resourceLocation);
if (defaultCrsUrl == null) {
String warnMessage = resourceLocation
+ " not found. Using standard "
+ GeoImportUtil.getDefaultCRS().getName();
LOGGER.debug(warnMessage);
warn("default crs", warnMessage);
return;
}
/*
* The file exists, read it now
*/
try {
CoordinateReferenceSystem defaultCRS = GeoImportUtil
.readProjectionFile(defaultCrsUrl);
GeoImportUtil.setDefaultCRS(defaultCRS); // TODO Default CRS must be
// part of
// AtlasCOnfig!!!
} catch (IOException e) {
LOGGER.error(
"Error reading " + AtlasConfig.DEFAULTCRS_FILENAME
+ ". Fallback to"
+ GeoImportUtil.getDefaultCRS().getName(), e);
warn("Default CRS", "Error reading "
+ AtlasConfig.DEFAULTCRS_FILENAME);
// ExceptionDialog.show(owner, e, null,"Error reading "
// + AtlasConfig.DEFAULTCRS_FILENAME);
}
LOGGER.info("Default CRS: " + GeoImportUtil.getDefaultCRS().getName());
}
/**
* Parse a aml:PdfMedia tag to a {@link DpMediaPDF} instance
*
* @param node
* @param ac
* @return
* @throws AtlasRecoverableException
*/
private static DpMediaPDF parseDatapoolPdfVideo(Node node, AtlasConfig ac)
throws AtlasRecoverableException {
if (ac == null) {
throw new IllegalArgumentException(
"ac= null in parseMediaPdfVideo(Node node, Atlasconfig ac)");
}
final DpMediaPDF dpe = new DpMediaPDF(ac);
dpe.setId(node.getAttributes().getNamedItem("id").getNodeValue());
// ****************************************************************************
// The exportable attribute is optional and defaults to false
// ****************************************************************************
try {
dpe.setExportable(Boolean.valueOf(node.getAttributes()
.getNamedItem("exportable").getNodeValue()));
} catch (Exception e) {
dpe.setExportable(false);
}
final NodeList childNodes = node.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
final Node n = childNodes.item(i);
final String name = n.getLocalName();
// Cancel if it's an attribute
if (!n.hasChildNodes())
continue;
if (name.equals("filename")) {
final String value = n.getFirstChild().getNodeValue();
dpe.setFilename(value);
} else if (name.equals("name")) {
dpe.setTitle(AMLImport.parseTranslation(ac.getLanguages(), n));
} else if (name.equals("dataDirname")) {
final String value = n.getFirstChild().getNodeValue();
dpe.setDataDirname(value);
} else if (name.equals("desc")) {
dpe.setDesc(AMLImport.parseTranslation(ac.getLanguages(), n));
} else if (name.equals("keywords")) {
dpe.setKeywords(AMLImport.parseTranslation(ac.getLanguages(), n));
}
}
return dpe;
}
/**
* Parse a aml:PdfMedia tag to a {@link DpMediaPDF} instance
*
* @param node
* @param ac
* @return
* @throws AtlasRecoverableException
*/
private static DpMediaPICTURE parseDatapoolPicture(Node node, AtlasConfig ac)
throws AtlasRecoverableException {
if (ac == null) {
throw new IllegalArgumentException(
"ac= null in parseMediaPicture(Node node, Atlasconfig ac)");
}
final DpMediaPICTURE dpe = new DpMediaPICTURE(ac);
dpe.setId(node.getAttributes().getNamedItem("id").getNodeValue());
// ****************************************************************************
// The exportable attribute is optional and defaults to false
// ****************************************************************************
try {
dpe.setExportable(Boolean.valueOf(node.getAttributes()
.getNamedItem("exportable").getNodeValue()));
} catch (Exception e) {
dpe.setExportable(false);
}
final NodeList childNodes = node.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
final Node n = childNodes.item(i);
final String name = n.getLocalName();
// Cancel if it's an attribute
if (!n.hasChildNodes())
continue;
if (name.equals("filename")) {
final String value = n.getFirstChild().getNodeValue();
dpe.setFilename(value);
} else if (name.equals("name")) {
dpe.setTitle(AMLImport.parseTranslation(ac.getLanguages(), n));
} else if (name.equals("dataDirname")) {
final String value = n.getFirstChild().getNodeValue();
dpe.setDataDirname(value);
} else if (name.equals("desc")) {
dpe.setDesc(AMLImport.parseTranslation(ac.getLanguages(), n));
} else if (name.equals("keywords")) {
dpe.setKeywords(AMLImport.parseTranslation(ac.getLanguages(), n));
}
}
return dpe;
}
/**
* Parses the node that is of aml:descType
*
* @param node
* {@link Node} to parse
*
* @throws AtlasRecoverableException
*
* @author <a href="mailto:skpublic@wikisquare.de">Stefan Alfons Tzeggai</a>
* @author <a href="mailto:schmitzm@bonn.edu">Martin Schmitz</a> (University
* of Bonn/Germany)
*/
public final static Translation parseTranslation(
final List<String> languages, final Node node)
throws AtlasRecoverableException {
Translation trans = new Translation();
if (node != null) // we usually expect that
{
final NodeList childNodes = node.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
final Node translation = childNodes.item(i);
final String name = translation.getLocalName();
if (name == null)
continue;
// lang attribute
String lang = translation.getAttributes().getNamedItem("lang")
.getNodeValue();
// MS-01.sn: if "lang" attribute is missing, set default is sets
// set the default, if no language code is set
if (lang == null)
lang = Translation.DEFAULT_KEY;
// MS-01.en
final Node textNode = translation.getFirstChild();
if (textNode == null) {
// Empty Text => don't expect a textnode
trans.put(lang, "");
} else {
trans.put(lang, textNode.getNodeValue());
// trans.put(lang, textNode.getTextContent()); ging bei
// martin nicht..
}
}
if (trans.size() == 0) {
// ****************************************************************************
// MS-01.so if no <translation> is given, the value of the node
// should
// be used as a default translation
// martin
// MS-01.en
// ****************************************************************************
LOGGER.debug("Wir denken, dass kein <translation> angegeben wurde, und setzen '"
+ node.getFirstChild().getNodeValue()
+ "' als default.");
trans = new Translation(languages, node.getFirstChild()
.getNodeValue());
// trans = new Translation( node.getNodeValue() );
}
}
return trans;
}
/**
* Parses an AtlasML branch and fills values
*
* @throws AtlasException
* @throws AtlasException
* @throws AtlasException
*/
public final static DpMediaVideo parseDatapoolMediaVideo(final Node node,
final AtlasConfig ac) throws AtlasException {
if (ac == null)
throw new IllegalArgumentException(
"ac= null in parseMediaMediaVideo(Node node, Atlasconfig ac)");
final DpMediaVideo dpe = new DpMediaVideo(ac);
dpe.setId(node.getAttributes().getNamedItem("id").getNodeValue());
// ****************************************************************************
// The exportable attribute is optional and defaults to false
// ****************************************************************************
try {
dpe.setExportable(Boolean.valueOf(node.getAttributes()
.getNamedItem("exportable").getNodeValue()));
} catch (Exception e) {
dpe.setExportable(false);
}
final NodeList childNodes = node.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
final Node n = childNodes.item(i);
final String name = n.getLocalName();
// Cancel if it's an attribute
if (!n.hasChildNodes())
continue;
if (name.equals("filename")) {
final String value = n.getFirstChild().getNodeValue();
dpe.setFilename(value);
} else if (name.equals("name")) {
dpe.setTitle(AMLImport.parseTranslation(ac.getLanguages(), n));
} else if (name.equals("dataDirname")) {
final String value = n.getFirstChild().getNodeValue();
dpe.setDataDirname(value);
} else if (name.equals("desc")) {
dpe.setDesc(AMLImport.parseTranslation(ac.getLanguages(), n));
} else if (name.equals("keywords")) {
dpe.setKeywords(AMLImport.parseTranslation(ac.getLanguages(), n));
}
}
return dpe;
}
/**
* Parses an AtlasML branch and fills values
*
* @throws AtlasRecoverableException
*/
public final static DpLayerRaster<?, ChartStyle> parseDatapoolLayerRaster(
final Node node, final AtlasConfig ac)
throws AtlasRecoverableException {
String id = node.getAttributes().getNamedItem("id").getNodeValue();
final DpLayerRaster<?, ChartStyle> dpe;
// if (ac.getProperties().getBoolean(Keys.rasterReader, true)) {
LOGGER.info("Using new raster reader for " + id);
dpe = new DpLayerRaster_Reader(ac);
dpe.setId(id);
// ****************************************************************************
// The exportable attribute is optional and defaults to false
// ****************************************************************************
try {
dpe.setExportable(Boolean.valueOf(node.getAttributes()
.getNamedItem("exportable").getNodeValue()));
} catch (Exception e) {
dpe.setExportable(false);
}
// ****************************************************************************
// The nodata attribute is optional and defaults to null
// ****************************************************************************
try {
final String nodeValueString = node.getAttributes()
.getNamedItem(AMLUtil.ATT_NODATA).getNodeValue();
dpe.setNodataValue(Double.valueOf(nodeValueString));
} catch (Exception e) {
dpe.setNodataValue(null);
}
final NodeList childNodes = node.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
final Node n = childNodes.item(i);
final String name = n.getLocalName();
// Cancel if it's an attribute
if (!n.hasChildNodes())
continue;
if (name.equals("filename")) {
final String value = n.getFirstChild().getNodeValue();
dpe.setFilename(value);
} else {
if (name.equals("name")) {
final Translation transname = AMLImport.parseTranslation(
ac.getLanguages(), n);
dpe.setTitle(transname);
} else if (name.equals("dataDirname")) {
final String value = n.getFirstChild().getNodeValue();
dpe.setDataDirname(value);
// dpe.setDataDirectory(new File(ac.getDataDir(), value));
} else if (name.equals("desc")) {
dpe.setDesc(parseTranslation(ac.getLanguages(), n));
} else if (name.equals("rasterLegendData")) {
dpe.setLegendMetaData(parseRasterLegendData(ac, n));
} else if (name.equals("keywords")) {
dpe.setKeywords(parseTranslation(ac.getLanguages(), n));
} else if (name.equals(AMLUtil.TAG_ADDITIONAL_STYLE)) {
dpe.addLayerStyle(parseLayerStyle(ac, n, dpe));
} else if (name.equals("band")) {
dpe.setBandNames(parseTranslation(ac.getLanguages(), n));
}
}
}
return dpe;
}
/**
* Parses the {@link RasterLegendData} from AtlasML
*
* @param n
* Node that is called "rasterLagendData"
* @return {@link RasterLegendData}, maybe without entries, but never null.
*
* @author <a href="mailto:skpublic@wikisquare.de">Stefan Alfons Tzeggai</a>
* @throws AtlasRecoverableException
*/
private static RasterLegendData parseRasterLegendData(AtlasConfig ac,
Node node) throws AtlasRecoverableException {
RasterLegendData rld = new RasterLegendData(false);
rld.setPaintGaps(Boolean.valueOf(node.getAttributes()
.getNamedItem(AMLUtil.ATT_paintGaps).getNodeValue()));
final NodeList childNodes = node.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
final Node n = childNodes.item(i);
final String name = n.getLocalName();
// Cancel if it's an attribute
if (!n.hasChildNodes())
continue;
if (name.equals("rasterLegendItem")) {
final Node paintGapsAttrib = n.getAttributes().getNamedItem(
"value");
Double value = Double.valueOf(paintGapsAttrib.getNodeValue());
// first and only item should be the label
final Node labeln = n.getChildNodes().item(1);
Translation label = parseTranslation(ac.getLanguages(), labeln);
rld.put(value, label);
}
}
return rld;
}
//
// /**
// * Parses an AtlasML branch and fills values
// *
// * @throws AtlasRecoverableException
// */
// public final static DpLayerRasterPyramid parseDatapoolLayerRasterPyramid(
// final Node node, final AtlasConfig ac)
// throws AtlasRecoverableException {
// if (ac == null)
// throw new IllegalArgumentException("ac == null");
// final DpLayerRasterPyramid dpe = new DpLayerRasterPyramid(ac);
//
// dpe.setId(node.getAttributes().getNamedItem("id").getNodeValue());
// final NodeList childNodes = node.getChildNodes();
// for (int i = 0; i < childNodes.getLength(); i++) {
// final Node n = childNodes.item(i);
// final String name = n.getLocalName();
// // Cancel if it's an attribute
// if (!n.hasChildNodes())
// continue;
//
// if (name.equals("filename")) {
// final String value = n.getFirstChild().getNodeValue();
// dpe.setFilename(value);
// } else {
// if (name.equals("name")) {
// final Translation transname = AMLImport.parseTranslation(
// ac.getLanguages(), n);
//
// dpe.setTitle(transname);
// } else if (name.equals("dataDirname")) {
// final String value = n.getFirstChild().getNodeValue();
// dpe.setDataDirname(value);
// } else if (name.equals("desc")) {
// dpe.setDesc(AMLImport.parseTranslation(ac.getLanguages(), n));
// } else if (name.equals("rasterLegendData")) {
// dpe.setLegendMetaData(parseRasterLegendData(ac, n));
// } else if (name.equals("keywords")) {
// dpe.setKeywords(AMLImport.parseTranslation(
// ac.getLanguages(), n));
// } else if (name.equals("transparentColor")) {
// final String colorStr = n.getFirstChild().getNodeValue();
// dpe.setInputTransparentColor(SwingUtil.parseColor(colorStr));
// }
// }
// }
// return dpe;
// }
/**
* Parses a aml:group tag
*
* @param node
* sml:group-node
* @param ac
* {@link AtlasConfig} to get the {@link DataPool} to map the
* datapoolRef-IDs
*/
public final static Group parseGroup(final Node node, final AtlasConfig ac)
throws AtlasRecoverableException {
final Group group = new Group(ac);
// LOGGER.debug("Parsing a new group...");
/**
* Is this group supposed to be the special Help or File menu?
*/
if (node.getAttributes() != null) {
Node isFileRaw = node.getAttributes().getNamedItem("isFileMenu");
if (isFileRaw != null && isFileRaw.getNodeValue() != null
&& isFileRaw.getNodeValue().equals("true")) {
group.setFileMenu(true);
}
Node isHelpRaw = node.getAttributes().getNamedItem("isHelpMenu");
if (isHelpRaw != null && isHelpRaw.getNodeValue() != null
&& isHelpRaw.getNodeValue().equals("true")) {
group.setHelpMenu(true);
}
}
final NodeList childNodes = node.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
final Node childNode = childNodes.item(i);
final String tagName = childNode.getLocalName();
// Cancel if it's an attribute
if (tagName == null)
continue;
if (tagName.equals("name")) {
group.setTitle(parseTranslation(ac.getLanguages(), childNode));
} else if (tagName.equals("desc")) {
group.setDesc(parseTranslation(ac.getLanguages(), childNode));
} else if (tagName.equals("keywords")) {
group.setKeywords(parseTranslation(ac.getLanguages(), childNode));
} else if (tagName.equals("datapoolRef")) {
final String id = childNode.getAttributes().getNamedItem("id")
.getNodeValue();
final DpEntry testDpe = ac.getDataPool().get(id);
if (testDpe == null) {
warn("menu structure",
"<datapoolRef> target-ID can't be found in the Datapool. id="
+ id + "\n Ignoring."); // i8n
} else {
// LOGGER.debug(" Adding datapoolRef " + testDpe
// + " to group " + group);
group.add(new DpRef<DpEntry<? extends ChartStyle>>(testDpe));
}
} else if (tagName.equals("mapRef")) {
final String id = childNode.getAttributes().getNamedItem("id")
.getNodeValue();
final Map testMap = ac.getMapPool().get(id);
if (testMap == null) {
warn("menu structure",
"<mapRef> target-ID can't be found in the Datapool. id="
+ id + "\n Ignoring."); // i8n
} else {
// LOGGER.debug("Adding mapRef " + testMap + " to group "
// + group);
group.add(new MapRef(testMap, ac.getMapPool()));
}
} else if (tagName.equals("group")) {
group.add(parseGroup(childNode, ac));
}
}
return group;
}
/**
* Parses an AtlasML branch and fills values to create an
* {@link DpLayerVectorFeatureSource} object.
*
* @throws AtlasRecoverableException
*
* TODO Hier muss eine URL hin! Bisher geht nur
* {@link DpLayerVectorFeatureSourceShapefile}
* @throws AtlasCancelException
*/
public final static DpLayerVectorFeatureSource parseDatapoolLayerVector(
final Node node, final AtlasConfig ac)
throws AtlasRecoverableException {
if (ac == null)
throw new IllegalArgumentException("ac == null");
// TODO If we have Shapefiles and WFS Sources, this will need a factory
// here...
// TODO ATM we only expect Shapefiles here!
final DpLayerVectorFeatureSource dplvfs = new DpLayerVectorFeatureSourceShapefile(
ac);
try {
dplvfs.setId(node.getAttributes().getNamedItem("id").getNodeValue());
// LOGGER.info("ID = "+dplvfs.getId());
/***********************************************************************
* The "showStylerInLegend" attribute is optional and defaults to
* true
***********************************************************************/
try {
dplvfs.setStylerInLegend(Boolean.valueOf(node.getAttributes()
.getNamedItem("showStylerInLegend").getNodeValue()));
} catch (Exception e) {
dplvfs.setStylerInLegend(true);
}
/***********************************************************************
* The "showTableInLegend" attribute is optional and defaults to
* true
***********************************************************************/
try {
dplvfs.setTableInLegend(Boolean.valueOf(node.getAttributes()
.getNamedItem("showTableInLegend").getNodeValue()));
} catch (Exception e) {
dplvfs.setTableInLegend(true);
}
/***********************************************************************
* The "showFilterInLegend" attribute is optional and defaults to
* false
***********************************************************************/
try {
dplvfs.setFilterInLegend(Boolean.valueOf(node.getAttributes()
.getNamedItem("showFilterInLegend").getNodeValue()));
} catch (Exception e) {
dplvfs.setFilterInLegend(true);
}
/***********************************************************************
* The "exportable" attribute is optional and defaults to false
***********************************************************************/
try {
dplvfs.setExportable(Boolean.valueOf(node.getAttributes()
.getNamedItem("exportable").getNodeValue()));
} catch (Exception e) {
dplvfs.setExportable(false);
}
final NodeList childNodes = node.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
final Node n = childNodes.item(i);
// Cancel if it's an attribute
// if (!n.hasChildNodes())
// continue;
final String name = n.getLocalName();
if (name == null)
continue;
if (name.equals("filename")) {
final String value = n.getFirstChild().getNodeValue();
dplvfs.setFilename(value);
} else if (name.equals("name")) {
final Translation transname = parseTranslation(
ac.getLanguages(), n);
// info("parsing vector " + transname);
dplvfs.setTitle(transname);
} else if (name.equals("dataDirname")) {
final String value = n.getFirstChild().getNodeValue();
dplvfs.setDataDirname(value);
} else if (name.equals("desc")) {
dplvfs.setDesc(parseTranslation(ac.getLanguages(), n));
} else if (name.equals("keywords")) {
dplvfs.setKeywords(parseTranslation(ac.getLanguages(), n));
} else if (name.equals(AMLUtil.TAG_attributeMetadata)) {
try {
final AttributeMetadataImpl attribute = parseAttributeMetadata(
dplvfs, ac, n);
if (attribute != null) {
dplvfs.getAttributeMetaDataMap().put(
attribute.getName(), attribute);
}
} catch (AtlasRecoverableException e) {
String m = "Parsing attribute descriptions";
LOGGER.warn(m, e);
warn(m, e.getMessage());
} catch (RuntimeException e) {
if (AtlasViewerGUI.isRunning()) {
// warn("layer nich verfügbar aber das ist nicht schlimm",
// e.getMessage());
} else
throw e;
}
} else if (name.equals(AMLUtil.TAG_ADDITIONAL_STYLE)) {
dplvfs.addLayerStyle(parseLayerStyle(ac, n, dplvfs));
} else if (name.equals("filterRule")) {
String filterString = n.getFirstChild().getNodeValue();
if (upgradeFromPreGP13 && filterString != null
&& !filterString.isEmpty()) {
try {
String convertedFilterString = AMLUtil
.upgradeMartinFilter2ECQL(filterString);
dplvfs.setFilterRule(convertedFilterString);
} catch (CQLException filterParserEx) {
LOGGER.error(
"Converting filter "
+ filterString
+ " to CQL failed! Setting filter to no-filter",
filterParserEx);
warn(dplvfs.getTitle().toString(),
"Failed to convert old filter\n "
+ filterString
+ "\n to the new ECQL filter language. This setting is lost.");
dplvfs.setFilterRule("");
}
} else {
dplvfs.setFilterRule(filterString);
}
} else if (name.equals("chart")
&& AVSwingUtil.getUrl(dplvfs, statusDialog) != null) {
try {
dplvfs.getCharts().add(
parseFeatureChartStyle(ac, n, dplvfs));
} catch (Exception e) {
// Broken URL or file doesn't exist
LOGGER.warn("Could not load chartStyle: ", e);
}
}
}
} catch (Exception e) {
String m = "Layer " + dplvfs.getId() + "/"
+ dplvfs.getBaseFilename()
+ " has been ignored due to errors:";
LOGGER.error(m, e);
warn(m, e.getMessage());
return null;
}
return dplvfs;
}
/**
* Parses the metainformation in the XML and creates a
* {@link FeatureChartStyle} from the referenced charts/blabla.xml file.
*
* @param dplvfs
* may not be <code>null</code>.
*/
private static FeatureChartStyle parseFeatureChartStyle(AtlasConfig ac,
Node node, final DpLayerVectorFeatureSource dplvfs)
throws IOException {
final String filenameValue = node.getAttributes()
.getNamedItem("filename").getNodeValue();
// URL url = dplvfs.getUrl();
URL url = AVSwingUtil.getUrl(dplvfs, statusDialog);
String urlStr = url.toString();
// LOGGER.debug("urlstr ="+urlStr);
String substring = urlStr.substring(0, urlStr.lastIndexOf("/") + 1);
// LOGGER.debug("sub "+substring);
urlStr = substring + "charts/" + filenameValue;
URL chartStyleURL = new URL(urlStr);
FeatureChartStyle featureChartStyle = (FeatureChartStyle) ChartStyleUtil
.readStyleFromXML(chartStyleURL,
FeatureChartUtil.FEATURE_CHART_STYLE_FACTORY);
// log.debug("after loading\n"+" "+featureChartStyle);
AttributeMetadataMap attributeMetaDataMap = dplvfs
.getAttributeMetaDataMap();
// Check if the attributes still exist or whether their
// uppercase/lowercase mode changed
if (FeatureChartUtil.correctAttributeNames(featureChartStyle,
dplvfs.getSchema())) {
// How to handle chartstyles that had attributes removed?
}
FeatureChartUtil.passNoDataValues(attributeMetaDataMap,
featureChartStyle);
// log.debug("after correcting\n"+" "+featureChartStyle);
return featureChartStyle;
}
/**
* Parses a <layerStyle> tag
*
* @author <a href="mailto:skpublic@wikisquare.de">Stefan Alfons Tzeggai</a>
*/
private static LayerStyle parseLayerStyle(AtlasConfig ac, Node node,
DpLayer<?, ? extends ChartStyle> dpLayer)
throws AtlasRecoverableException {
final String filename = node.getAttributes().getNamedItem("filename")
.getNodeValue();
final NodeList childNodes = node.getChildNodes();
Translation name = null;
Translation desc = null;
for (int i = 0; i < childNodes.getLength(); i++) {
if (childNodes.item(i).getLocalName() == null)
continue;
if (childNodes.item(i).getLocalName().equals("title")) {
name = parseTranslation(ac.getLanguages(), childNodes.item(i));
} else if (childNodes.item(i).getLocalName().equals("desc")) {
desc = parseTranslation(ac.getLanguages(), childNodes.item(i));
}
}
return new LayerStyle(filename, name, desc, dpLayer);
}
/**
* Parses a node that is of type < aml : dataAttribute > to a
* {@link AttributeMetadataImpl}
*
* @param dplvfs
* only used to map old colIdx => new attribute Names
*
* @return {@link AttributeMetadataImpl} or <code>null</code>, if the
* attribute doesn't exist anymore.
* @throws AtlasRecoverableException
* @throws AtlasCancelException
*/
public static AttributeMetadataImpl parseAttributeMetadata(
DpLayerVectorFeatureSource dplvfs, AtlasConfig ac, final Node node)
throws AtlasRecoverableException, AtlasCancelException {
// Trigger caching the layer with a status-download-wait-GUI in case we
// are running on JavaWebStart
// LOGGER.debug("getting the GeoObject with a StatusDialog "
// + statusDialog + " to parseAttributeMetadata for "
// + dplvfs.getTitle().toString());
dplvfs.getGeoObject(statusDialog);
String localname;
String nameSpace;
Integer weight = 0;
Double functionX = 1.;
Double functionA = 0.;
try {
nameSpace = node.getAttributes()
.getNamedItem(AMLUtil.ATT_namespace).getNodeValue();
localname = node.getAttributes()
.getNamedItem(AMLUtil.ATT_localname).getNodeValue();
weight = Integer.valueOf(node.getAttributes()
.getNamedItem(AMLUtil.ATT_weight).getNodeValue());
functionX = Double.valueOf(node.getAttributes()
.getNamedItem(AMLUtil.ATT_functionX).getNodeValue());
functionA = Double.valueOf(node.getAttributes()
.getNamedItem(AMLUtil.ATT_functionA).getNodeValue());
} catch (Exception e) {
LOGGER.warn(
"Exception parseAttributeMetadata on first try. Starting second try using the Geoobject next..",
e);
functionX = 1.;
functionA = 0.;
try {
final Integer col = Integer.valueOf(node.getAttributes()
.getNamedItem("col").getNodeValue());
AttributeDescriptor attributeDescriptor = dplvfs
.getFeatureSource().getSchema()
.getAttributeDescriptors().get(col);
nameSpace = attributeDescriptor.getName().getNamespaceURI();
localname = attributeDescriptor.getName().getLocalPart();
weight = col;
} catch (Exception ee) {
LOGGER.warn(dplvfs.getId()
+ " is broken. Can not import old colIdx-based attributeMetadata");
warn(dplvfs.getTitle().toString(),
dplvfs.getId()
+ " is broken. Can not import old colIdx-based attributeMetadata");
return null;
}
}
final String visibleValue = node.getAttributes()
.getNamedItem("visible").getNodeValue();
final boolean visible = Boolean.valueOf(visibleValue);
String unit = "";
if (node.getAttributes().getNamedItem("unit") != null) {
unit = node.getAttributes().getNamedItem("unit").getNodeValue();
}
// The NameImpl may not be constructed with a "" as namespace, but a
// null!
// NameImpl nameImpl = new NameImpl(nameSpace != null ? nameSpace
// .isEmpty() ? null : nameSpace : null, localname);
NameImpl correctedAttName = FeatureUtil.findBestMatchingAttribute(
dplvfs.getSchema(), localname);
if (correctedAttName == null)
throw new AtlasRecoverableException(
"Couldn't find any existing attribute in "
+ dplvfs.getFilename()
+ " that the described attribute '"
+ localname
+ "' could belong to. Maybe the attribute has been deleted? The meatdata is thrown away.");
// Creating the object
AttributeMetadataImpl attributeMetadata = new AttributeMetadataImpl(
correctedAttName, visible, unit);
attributeMetadata.setWeight(weight);
attributeMetadata.setFunctionA(functionA);
attributeMetadata.setFunctionX(functionX);
// Parsing the childres
final NodeList childNodes = node.getChildNodes();
// If the nodataValue tag is not found, this is probalby an atlas
// created with GP < 1.4. default NODATA values will be added
// automatically.
boolean nodataTagFound = false;
for (int i = 0; i < childNodes.getLength(); i++) {
if (childNodes.item(i).getLocalName() == null)
continue;
if (childNodes.item(i).getLocalName().equals("name")) {
attributeMetadata.setTitle(parseTranslation(ac.getLanguages(),
childNodes.item(i)));
} else if (childNodes.item(i).getLocalName().equals("desc")) {
attributeMetadata.setDesc(parseTranslation(ac.getLanguages(),
childNodes.item(i)));
} else if (childNodes.item(i).getLocalName()
.equals(AMLUtil.TAG_nodataValue)) {
// NODATA values
nodataTagFound = true;
Node item = childNodes.item(i);
if (item != null) {
String textNodataValue = item.getTextContent();
interpretAndAddNodataValue(dplvfs, correctedAttName,
attributeMetadata, textNodataValue);
}
}
}
if (nodataTagFound == false && upgradeFromPreGP14) {
interpretAndAddNodataValue(dplvfs, correctedAttName,
attributeMetadata, "");
}
return attributeMetadata;
}
private static void interpretAndAddNodataValue(
DpLayerVectorFeatureSource dplvfs, NameImpl correctedAttName,
AttributeMetadataImpl attributeMetadata, String textValue) {
// Depending on the schema we have to transform the String
// to Number.
AttributeDescriptor attDesc = dplvfs.getSchema().getDescriptor(
correctedAttName);
Class<?> binding = attDesc.getType().getBinding();
if (attDesc != null && Number.class.isAssignableFrom(binding)) {
// Add the NODATA value parsed accoring to the binding
try {
Number noDataValue = LangUtil.parseNumberAs(textValue, binding);
attributeMetadata.getNodataValues().add(noDataValue);
} catch (Exception e) {
LOGGER.warn("NODATA value '" + textValue
+ "' can't be parsed as numeric. Ignoring..", e);
// attributeMetadata.getNodataValues().add(textValue);
}
} else {
// Add the NODATA value as a String
attributeMetadata.getNodataValues().add(textValue);
}
}
/**
* Parses a node that is of type < aml:maps > to a {@link MapPool} object
*
* @throws AtlasRecoverableException
*/
public final static Map parseMap(final Node node, final AtlasConfig ac)
throws AtlasRecoverableException {
// LOGGER.debug("Parsing a new Map...");
// Reading the map's ID
final Map map = new Map(node.getAttributes().getNamedItem("id")
.getNodeValue(), ac);
// Whether any maxMapExtend should be applied in Geopublisher's
// MapComposer
if (node.getAttributes().getNamedItem(
AMLUtil.ATT_PREVIEW_MAX_MAPEXTEND_IN_GP) != null) {
map.setPreviewMapExtendInGeopublisher(Boolean.valueOf(node
.getAttributes()
.getNamedItem(AMLUtil.ATT_PREVIEW_MAX_MAPEXTEND_IN_GP)
.getNodeValue()));
} else {
// Default is false
map.setPreviewMapExtendInGeopublisher(false);
}
// Reading the map's legend left/right ratio
if (node.getAttributes().getNamedItem("leftRightRatio") != null) {
Double leftRightRatio = Double.valueOf(node.getAttributes()
.getNamedItem("leftRightRatio").getNodeValue());
map.setLeftRightRatio(leftRightRatio);
} else {
// 0 => auto mode
map.setLeftRightRatio(0.);
}
// Shall the map scale be shown?
if (node.getAttributes().getNamedItem(AMLUtil.ATT_MAP_SCALE_VISIBLE) != null) {
map.setScaleVisible(Boolean
.valueOf(node.getAttributes()
.getNamedItem(AMLUtil.ATT_MAP_SCALE_VISIBLE)
.getNodeValue()));
}
// Shall the map scale be shown?
if (node.getAttributes().getNamedItem(AMLUtil.ATT_MAP_SCALE_UNITS) != null) {
map.setScaleUnits(ScaleUnits.valueOf(node.getAttributes()
.getNamedItem(AMLUtil.ATT_MAP_SCALE_UNITS).getNodeValue()));
}
// Shall the map show horizontal and vertical gridPanels?
if (node.getAttributes().getNamedItem("gridPanelVisible") != null) {
map.setGridPanelVisible(Boolean.valueOf(node.getAttributes()
.getNamedItem("gridPanelVisible").getNodeValue()));
}
// Which formatter shall be used?
if (node.getAttributes().getNamedItem("gridPanelFormatter") != null) {
map.setGridPanelFormatter(GridPanelFormatter.getFormatterByID(node
.getAttributes().getNamedItem("gridPanelFormatter")
.getNodeValue()));
}
// Which CRS shall be used? If non is defined, use
// GeoImportUtil.getDefaultCRS()
{
URL gridCrsURl = ac.getResLoMan().getResourceAsUrl(
AtlasConfig.ATLASDATA_DIRNAME + "/"
+ AtlasConfig.HTML_DIRNAME + "/" + map.getId()
+ "/" + Map.GRIDPANEL_CRS_FILENAME);
if (gridCrsURl == null) {
map.setGridPanelCRS(GeoImportUtil.getDefaultCRS());
} else {
try {
map.setGridPanelCRS(GeoImportUtil
.readProjectionFile(gridCrsURl));
} catch (IOException e) {
LOGGER.warn("Unable to read " + gridCrsURl, e);
map.setGridPanelCRS(GeoImportUtil.getDefaultCRS());
}
}
}
final NodeList childNodes = node.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
final Node childNode = childNodes.item(i);
final String tagName = childNode.getLocalName();
// Cancel if it's an attribute
if (tagName == null)
continue;
if (tagName.equals("name")) {
map.setTitle(parseTranslation(ac.getLanguages(), childNode));
} else if (tagName.equals("desc")) {
map.setDesc(parseTranslation(ac.getLanguages(), childNode));
} else if (tagName.equals("keywords")) {
map.setKeywords(parseTranslation(ac.getLanguages(), childNode));
} else if (tagName.equals("startViewEnvelope")) {
final String value = childNode.getFirstChild().getNodeValue();
String[] pairs = LangUtil.removeWhitespacesToEmpty(value)
.split(" ");
final double cornersV[][] = new double[2][2];
String pair[];
for (int iii = 0; iii < 2; iii++) {
pair = pairs[iii].split(",");
cornersV[iii][0] = Double.parseDouble(pair[0]);
cornersV[iii][1] = Double.parseDouble(pair[1]);
}
// TODO defaultMapArea has to store the crs!?! Map should store
// it's crs?!
map.setDefaultMapArea(new ReferencedEnvelope(cornersV[0][0],
cornersV[1][0], cornersV[0][1], cornersV[1][1], null));
} else if (tagName.equals("maxExtend")) {
final String value = childNode.getFirstChild().getNodeValue();
String[] pairs = LangUtil.removeWhitespacesToEmpty(value)
.split(" ");
final double cornersV[][] = new double[2][2];
String pair[];
for (int iii = 0; iii < 2; iii++) {
pair = pairs[iii].split(",");
cornersV[iii][0] = Double.parseDouble(pair[0]);
cornersV[iii][1] = Double.parseDouble(pair[1]);
}
map.setMaxExtend(new Envelope(new Coordinate(cornersV[0][0],
cornersV[0][1]), new Coordinate(cornersV[1][0],
cornersV[1][1])));
} else if (tagName.equals("datapoolRef")) {
final String id = childNode.getAttributes().getNamedItem("id")
.getNodeValue();
final DpEntry<? extends ChartStyle> testDpe = ac.getDataPool()
.get(id);
if (testDpe == null) {
warn("map:" + map.getTitle().toString(),
"<datapoolRef> attribute id can't be found in the Datapool. id="
+ id);
} else {
// LOGGER.debug(" Adding datapoolRef " + testDpe +
// " to Map "
// + map);
final DpRef<DpEntry<? extends ChartStyle>> dpRef = new DpRef<DpEntry<? extends ChartStyle>>(
testDpe);
// Checking for the optional attribute
// <code>hideInLegend</code>
Node namedItem = childNode.getAttributes().getNamedItem(
"hideInLegend");
if (namedItem != null) {
final String hideLayerInLegend = namedItem
.getNodeValue();
map.getHideInLegendMap().put(dpRef.getTargetId(),
Boolean.valueOf(hideLayerInLegend));
}
// Checking for the optional (default = false) attribute
// <code>minimizeInLegend</code>
namedItem = childNode.getAttributes().getNamedItem(
"minimizeInLegend");
if (namedItem != null) {
final String minimizeLayerInLegend = namedItem
.getNodeValue();
map.getMinimizedInLegendMap().put(dpRef.getTargetId(),
Boolean.valueOf(minimizeLayerInLegend));
}
// Checking for the optional attribute
// <code>hidden</code> that controls the status of the
// "eye symbol"
namedItem = childNode.getAttributes()
.getNamedItem("hidden");
if (namedItem != null) {
final String hidden = namedItem.getNodeValue();
map.setHiddenFor(dpRef.getTargetId(),
Boolean.valueOf(hidden));
}
// Checking for the optional attribute
// <code>selectable</code> that controls the status of the
// "eye symbol"
namedItem = childNode.getAttributes().getNamedItem(
"selectable");
if (namedItem != null) {
final String hidden = namedItem.getNodeValue();
map.setSelectableFor(dpRef.getTargetId(),
Boolean.valueOf(hidden));
}
map.add(dpRef);
}
} else if (tagName.equals(AMLUtil.TAG_ADDITIONAL_STYLES)) {
String layerID = childNode.getAttributes()
.getNamedItem("layerID").getNodeValue();
Node whichIsSelectedAttribute = childNode.getAttributes()
.getNamedItem("selectedStyleID");
ArrayList<String> styles = new ArrayList<String>();
String selectedStyleID = null;
if (whichIsSelectedAttribute != null) {
selectedStyleID = whichIsSelectedAttribute.getNodeValue();
map.setSelectedStyleID(layerID, selectedStyleID);
}
final NodeList additionalStyleschildNodes = childNode
.getChildNodes();
for (int ii = 0; ii < additionalStyleschildNodes.getLength(); ii++) {
final Node additionalStyleschildNode = additionalStyleschildNodes
.item(ii);
final String additionalStylestagName = additionalStyleschildNode
.getLocalName();
// Cancel if it's an attribute
if (additionalStylestagName == null)
continue;
if (additionalStylestagName.equals("styleid")) {
// Do one more check here. If the referenced
// LayerStyleID doesn't exist, omit it.
String styleId = additionalStyleschildNode
.getTextContent();
DpLayer<?, ? extends ChartStyle> dpl = (DpLayer<?, ? extends ChartStyle>) ac
.getDataPool().get(layerID);
boolean foundIt = false;
if (dpl != null)
for (LayerStyle layerStyle : dpl.getLayerStyles()) {
if (layerStyle.getID().equals(styleId)) {
styles.add(styleId);
foundIt = true;
break;
}
}
/**
* This warning only makes sense in GP.. in AV these
* layers might simple not have been exported.
*/
if (!AtlasViewerGUI.isRunning() && !foundIt) {
String msg = "Map '"
+ map.getTitle()
+ "' defines an additional style with ID='"
+ styleId
+ "' for layer '"
+ layerID
+ "', but it's not known to the layer. It's ignored.";
LOGGER.warn(msg);
warn("map:" + map.getTitle().toString(), msg);
}
}
}
map.getAdditionalStyles().put(layerID, styles);
} else if (tagName.equals("availableCharts")) {
String layerID = childNode.getAttributes()
.getNamedItem("layerID").getNodeValue();
ArrayList<String> availChartsIDs = new ArrayList<String>();
final NodeList additionalStyleschildNodes = childNode
.getChildNodes();
for (int ii = 0; ii < additionalStyleschildNodes.getLength(); ii++) {
final Node availableChartChildNode = additionalStyleschildNodes
.item(ii);
final String additionalStylestagName = availableChartChildNode
.getLocalName();
// Cancel if it's an attribute
if (additionalStylestagName == null)
continue;
if (additionalStylestagName.equals("chartID")) {
// Do one more check here. If the referenced
// ChartStyle-ID doesn't exist, omit it.
String styleId = availableChartChildNode
.getTextContent();
DpLayer<?, ChartStyle> dpl = (DpLayer<?, ChartStyle>) ac
.getDataPool().get(layerID);
boolean foundIt = false;
if (dpl != null)
for (ChartStyle chart : dpl.getCharts()) {
if (chart.getID().equals(styleId)) {
availChartsIDs.add(styleId);
foundIt = true;
break;
}
}
if (!AtlasViewerGUI.isRunning() && !foundIt) {
String msg = "Map '"
+ map.getTitle()
+ "' defines an available chart with ID='"
+ styleId
+ "' for layer '"
+ layerID
+ "', but it's not known to the layer. It's ignored.";
LOGGER.error(msg);
warn("map:" + map.getTitle().toString(), msg);
}
}
}
map.getAvailableCharts().put(layerID, availChartsIDs);
}
}
return map;
}
/**
* Parses a < aml:mapPool > element
*
* @author Stefan Alfons Tzeggai
* @throws AtlasRecoverableException
*/
public static MapPool parseMapPool(final Node node,
final AtlasConfig atlasConfig) throws AtlasRecoverableException {
final MapPool mapPool = new MapPool();
info("Parsing MapPool...");
final NodeList childNodes = node.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
final Node childNode = childNodes.item(i);
final String tagName = childNode.getLocalName();
// Cancel if it's an attribute
if (tagName == null)
continue;
if (tagName.equals("map")) {
final Map map = parseMap(childNode, atlasConfig);
mapPool.add(map);
}
}
return mapPool;
}
public AMLImport() {
}
}