/* * FMEGMLReader.java * * Created on June 17, 2002, 1:46 PM */ /* * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI * for visualizing and manipulating spatial features with geometry and attributes. * * Copyright (C) 2003 Vivid Solutions * * 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 2 * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jump.io; import com.vividsolutions.jump.feature.FeatureCollection; import java.io.BufferedReader; import java.io.InputStreamReader; /** * A driver that reads GML files following the FME default schema. * <p> * <h3>DataProperties for the driver</h3> * * <table border=1 width=100%> * <tr><th>Parameter</th><th>Meaning</th></tr> * <tr><td>File <i>or</i> DefaultValue</td><td>File name for the input FME .xml file</td></tr> * <tr><td>CompressedFile</td><td>File name (a .zip or .gz) with a .jml/.xml/.gml inside (specified by File)</td></tr> * </table> * <p> * This is implemented using the more general {@link GMLReader}. * It makes a {@link GMLInputTemplate} to pass to the GMLReader by examining * the schema specified in the input file. */ // TODO : I18N public class FMEGMLReader implements JUMPReader { /** Creates new FMEGMLReader */ public FMEGMLReader() { } /** * Main method - reads in FMEGML file specified in the DriverProperties ('InputFile' or 'DefaultValue') * * @param dp {@link DriverProperties} to specify the file to read ('InputFile' or 'DefaultValue') */ public FeatureCollection read(DriverProperties dp) throws IllegalParametersException, Exception { FeatureCollection result; java.io.Reader r; GMLInputTemplate inputTemplate; GMLReader gmlReader = new GMLReader(); String inputfname; boolean isCompressed; isCompressed = (dp.getProperty("CompressedFile") != null); //dp.relabel("InputFMEGMLFile","File"); inputfname = dp.getProperty("DefaultValue"); if (inputfname == null) { inputfname = dp.getProperty("File"); } if (inputfname == null) { throw new IllegalParametersException( "call to FMEReader.read() has DataProperties w/o a InputFile specified"); } if (isCompressed) { r = new BufferedReader(new InputStreamReader( CompressedFile.openFile(inputfname, dp.getProperty("CompressedFile")))); } else { r = new BufferedReader(new java.io.FileReader(inputfname)); } try { try { inputTemplate = getGMLInputTemplate(r, inputfname); } finally { r.close(); } } finally { r.close(); } if (isCompressed) { r = new BufferedReader(new InputStreamReader( CompressedFile.openFile(inputfname, dp.getProperty("CompressedFile")))); } else { r = new BufferedReader(new java.io.FileReader(inputfname)); } try { gmlReader.setInputTemplate(inputTemplate); try { result = gmlReader.read(r, inputfname); } finally { r.close(); } } finally { r.close(); } return result; } /** * Parse the input file and make a GMLInputTemplate out of it * * @param fname just used in error message * @param r Java Reader */ public GMLInputTemplate getGMLInputTemplate(java.io.Reader r, String fname) throws java.io.IOException, ParseException { GMLInputTemplate result; java.io.LineNumberReader reader = new java.io.LineNumberReader(r); int lineNo = 0; boolean foundStartTag = false; boolean foundEndTag = false; String s; String columns; String columnName; String columnType; String columnDef; String templateText; int start; int end; String propertyNamePrefix; while ((foundStartTag == false) && (lineNo < 10)) { s = reader.readLine(); if (s == null) { throw new ParseException( "Couldn't find a <schemaFeatures> tag in the input FME GML file. This isn't a valid FME GML file."); } lineNo++; if (s.indexOf("<schemaFeatures>") > -1) { foundStartTag = true; } } if (!(foundStartTag)) { throw new ParseException("Read first 10 lines of " + fname + " and couldn't find a <schemaFeatures> tag. This isn't a valid FME GML file."); } columns = ""; while ((foundEndTag == false)) { s = reader.readLine(); if (s.indexOf("</schemaFeatures>") > -1) { foundEndTag = true; } if ((s.indexOf("<property fme:name") != -1) || (s.indexOf("<property name") != -1)) { //column definition //handle 2 fme variants - <property fme:name="name">...</property> and <property name="name">..</property> propertyNamePrefix = ""; if (s.indexOf("<property fme:name") != -1) { propertyNamePrefix = "fme:"; } //get column name start = s.indexOf("\""); end = s.indexOf("\"", start + 1); if ((start == -1) || (end == -1)) { throw new ParseException("Parsing file " + fname + " couldn't get column name on line # " + reader.getLineNumber() + " - " + s); } columnName = s.substring(start + 1, end); start = s.indexOf(">"); end = s.indexOf("<", start + 1); if ((start == -1) || (end == -1)) { throw new ParseException("Parsing file " + fname + " couldn't get column type on line # " + reader.getLineNumber() + " - " + s); } columnType = FMEtypeToJCSType(s.substring(start + 1, end)); columnDef = " <column>\n <name>" + columnName + "</name>\n <type>" + columnType + "</type>\n"; columnDef = columnDef + " <valueElement elementName=\"property\" attributeName=\"" + propertyNamePrefix + "name\" attributeValue=\"" + columnName + "\" />\n"; columnDef = columnDef + " <valueLocation position=\"body\" />\n"; columnDef = columnDef + " </column>\n"; columns = columns + columnDef; } } //add <featuretype>...</featuretype> 'column' columnDef = " <column>\n <name>featuretype</name>\n"; columnDef = columnDef + " <type>STRING</type>\n"; columnDef = columnDef + " <valueElement elementName=\"featureType\"/>\n"; columnDef = columnDef + " <valueLocation position=\"body\"/>\n"; columnDef = columnDef + " </column>\n"; columns = columns + columnDef; templateText = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"; templateText = templateText + "<JCSGMLInputTemplate>\n"; templateText = templateText + " <CollectionElement>dataFeatures</CollectionElement>\n"; templateText = templateText + " <FeatureElement>Feature</FeatureElement>\n"; templateText = templateText + " <GeometryElement>gml:PointProperty</GeometryElement>\n"; templateText = templateText + " <GeometryElement>gml:PolygonProperty</GeometryElement>\n"; templateText = templateText + " <GeometryElement>gml:LineStringProperty</GeometryElement>\n"; templateText = templateText + " <GeometryElement>gml:MultiPointProperty</GeometryElement>\n"; templateText = templateText + " <GeometryElement>gml:MultiPolygonProperty</GeometryElement>\n"; templateText = templateText + " <GeometryElement>gml:MultiLineStringProperty</GeometryElement>\n"; templateText = templateText + " <GeometryElement>gml:MultiGeometryProperty</GeometryElement>\n"; templateText = templateText + " <ColumnDefinitions>\n"; templateText = templateText + columns; templateText = templateText + " </ColumnDefinitions>\n"; templateText = templateText + "</JCSGMLInputTemplate>\n"; // System.out.println(templateText); java.io.StringReader sr = new java.io.StringReader(templateText); result = new GMLInputTemplate(); result.load(sr, "Auto created FME GML input template"); sr.close(); return result; } /** * converts the name of an FME type to a JCS type (STRING,DOUBLE, INTEGER) * * @param fmeType type that fme reports (ie. fme_char, fme_decimal, long) */ String FMEtypeToJCSType(String fmeType) { if (fmeType.indexOf("fme_char") > -1) { return "STRING"; } if (fmeType.indexOf("fme_decimal") > -1) { int loc; loc = fmeType.indexOf(","); if ((loc == -1) || (loc == (fmeType.length() - 1))) { return "STRING"; //bad } if (fmeType.substring(loc + 1, loc + 2).equalsIgnoreCase("0")) { return "INTEGER"; } return "DOUBLE"; } if (fmeType.indexOf("long") > -1) { return "DOUBLE"; // strange but true! } return "STRING"; //Note that there is no FME "date" type. FME's Shapefile=>GML conversion converts //dates to strings. [Jon Aquino] } }