001: /*
002: * FMEGMLReader.java
003: *
004: * Created on June 17, 2002, 1:46 PM
005: */
006: /*
007: * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI
008: * for visualizing and manipulating spatial features with geometry and attributes.
009: *
010: * Copyright (C) 2003 Vivid Solutions
011: *
012: * This program is free software; you can redistribute it and/or
013: * modify it under the terms of the GNU General Public License
014: * as published by the Free Software Foundation; either version 2
015: * of the License, or (at your option) any later version.
016: *
017: * This program is distributed in the hope that it will be useful,
018: * but WITHOUT ANY WARRANTY; without even the implied warranty of
019: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
020: * GNU General Public License for more details.
021: *
022: * You should have received a copy of the GNU General Public License
023: * along with this program; if not, write to the Free Software
024: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
025: *
026: * For more information, contact:
027: *
028: * Vivid Solutions
029: * Suite #1A
030: * 2328 Government Street
031: * Victoria BC V8T 5G5
032: * Canada
033: *
034: * (250)385-6040
035: * www.vividsolutions.com
036: */
037: package com.vividsolutions.jump.io;
038:
039: import com.vividsolutions.jump.feature.FeatureCollection;
040:
041: import java.io.BufferedReader;
042: import java.io.InputStreamReader;
043:
044: /**
045: * A driver that reads GML files following the FME default schema.
046: * <p>
047: * <h3>DataProperties for the driver</h3>
048: *
049: * <table border=1 width=100%>
050: * <tr><th>Parameter</th><th>Meaning</th></tr>
051: * <tr><td>File <i>or</i> DefaultValue</td><td>File name for the input FME .xml file</td></tr>
052: * <tr><td>CompressedFile</td><td>File name (a .zip or .gz) with a .jml/.xml/.gml inside (specified by File)</td></tr>
053: * </table>
054: * <p>
055: * This is implemented using the more general {@link GMLReader}.
056: * It makes a {@link GMLInputTemplate} to pass to the GMLReader by examining
057: * the schema specified in the input file.
058: * @TODO :I18N
059: */
060: public class FMEGMLReader implements JUMPReader {
061: /** Creates new FMEGMLReader */
062: public FMEGMLReader() {
063: }
064:
065: /**
066: * Main method - reads in FMEGML file specified in the DriverProperties ('InputFile' or 'DefaultValue')
067: *
068: * @param dp {@link DriverProperties} to specify the file to read ('InputFile' or 'DefaultValue')
069: */
070: public FeatureCollection read(DriverProperties dp)
071: throws IllegalParametersException, Exception {
072: FeatureCollection result;
073: java.io.Reader r;
074: GMLInputTemplate inputTemplate;
075: GMLReader gmlReader = new GMLReader();
076: String inputfname;
077: boolean isCompressed;
078:
079: isCompressed = (dp.getProperty("CompressedFile") != null);
080:
081: //dp.relabel("InputFMEGMLFile","File");
082: inputfname = dp.getProperty("DefaultValue");
083:
084: if (inputfname == null) {
085: inputfname = dp.getProperty("File");
086: }
087:
088: if (inputfname == null) {
089: throw new IllegalParametersException(
090: "call to FMEReader.read() has DataProperties w/o a InputFile specified");
091: }
092:
093: if (isCompressed) {
094: r = new BufferedReader(new InputStreamReader(CompressedFile
095: .openFile(inputfname, dp
096: .getProperty("CompressedFile"))));
097: } else {
098: r = new BufferedReader(new java.io.FileReader(inputfname));
099: }
100:
101: try {
102: try {
103: inputTemplate = getGMLInputTemplate(r, inputfname);
104: } finally {
105: r.close();
106: }
107: } finally {
108: r.close();
109: }
110:
111: if (isCompressed) {
112: r = new BufferedReader(new InputStreamReader(CompressedFile
113: .openFile(inputfname, dp
114: .getProperty("CompressedFile"))));
115: } else {
116: r = new BufferedReader(new java.io.FileReader(inputfname));
117: }
118:
119: try {
120: gmlReader.setInputTemplate(inputTemplate);
121:
122: try {
123: result = gmlReader.read(r, inputfname);
124: } finally {
125: r.close();
126: }
127: } finally {
128: r.close();
129: }
130:
131: return result;
132: }
133:
134: /**
135: * Parse the input file and make a GMLInputTemplate out of it
136: *
137: * @param fname just used in error message
138: * @param r Java Reader
139: */
140: public GMLInputTemplate getGMLInputTemplate(java.io.Reader r,
141: String fname) throws java.io.IOException, ParseException {
142: GMLInputTemplate result;
143: java.io.LineNumberReader reader = new java.io.LineNumberReader(
144: r);
145: int lineNo = 0;
146: boolean foundStartTag = false;
147: boolean foundEndTag = false;
148: String s;
149: String columns;
150: String columnName;
151: String columnType;
152: String columnDef;
153: String templateText;
154: int start;
155: int end;
156: String propertyNamePrefix;
157:
158: while ((foundStartTag == false) && (lineNo < 10)) {
159: s = reader.readLine();
160:
161: if (s == null) {
162: throw new ParseException(
163: "Couldn't find a <schemaFeatures> tag in the input FME GML file. This isn't a valid FME GML file.");
164: }
165:
166: lineNo++;
167:
168: if (s.indexOf("<schemaFeatures>") > -1) {
169: foundStartTag = true;
170: }
171: }
172:
173: if (!(foundStartTag)) {
174: throw new ParseException(
175: "Read first 10 lines of "
176: + fname
177: + " and couldn't find a <schemaFeatures> tag. This isn't a valid FME GML file.");
178: }
179:
180: columns = "";
181:
182: while ((foundEndTag == false)) {
183: s = reader.readLine();
184:
185: if (s.indexOf("</schemaFeatures>") > -1) {
186: foundEndTag = true;
187: }
188:
189: if ((s.indexOf("<property fme:name") != -1)
190: || (s.indexOf("<property name") != -1)) {
191: //column definition
192: //handle 2 fme variants - <property fme:name="name">...</property> and <property name="name">..</property>
193: propertyNamePrefix = "";
194:
195: if (s.indexOf("<property fme:name") != -1) {
196: propertyNamePrefix = "fme:";
197: }
198:
199: //get column name
200: start = s.indexOf("\"");
201: end = s.indexOf("\"", start + 1);
202:
203: if ((start == -1) || (end == -1)) {
204: throw new ParseException("Parsing file " + fname
205: + " couldn't get column name on line # "
206: + reader.getLineNumber() + " - " + s);
207: }
208:
209: columnName = s.substring(start + 1, end);
210:
211: start = s.indexOf(">");
212: end = s.indexOf("<", start + 1);
213:
214: if ((start == -1) || (end == -1)) {
215: throw new ParseException("Parsing file " + fname
216: + " couldn't get column type on line # "
217: + reader.getLineNumber() + " - " + s);
218: }
219:
220: columnType = FMEtypeToJCSType(s.substring(start + 1,
221: end));
222: columnDef = " <column>\n <name>" + columnName
223: + "</name>\n <type>" + columnType
224: + "</type>\n";
225: columnDef = columnDef
226: + " <valueElement elementName=\"property\" attributeName=\""
227: + propertyNamePrefix
228: + "name\" attributeValue=\"" + columnName
229: + "\" />\n";
230: columnDef = columnDef
231: + " <valueLocation position=\"body\" />\n";
232: columnDef = columnDef + " </column>\n";
233: columns = columns + columnDef;
234: }
235: }
236:
237: //add <featuretype>...</featuretype> 'column'
238: columnDef = " <column>\n <name>featuretype</name>\n";
239: columnDef = columnDef + " <type>STRING</type>\n";
240: columnDef = columnDef
241: + " <valueElement elementName=\"featureType\"/>\n";
242: columnDef = columnDef
243: + " <valueLocation position=\"body\"/>\n";
244: columnDef = columnDef + " </column>\n";
245: columns = columns + columnDef;
246:
247: templateText = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
248: templateText = templateText + "<JCSGMLInputTemplate>\n";
249: templateText = templateText
250: + " <CollectionElement>dataFeatures</CollectionElement>\n";
251: templateText = templateText
252: + " <FeatureElement>Feature</FeatureElement>\n";
253: templateText = templateText
254: + " <GeometryElement>gml:PointProperty</GeometryElement>\n";
255: templateText = templateText
256: + " <GeometryElement>gml:PolygonProperty</GeometryElement>\n";
257: templateText = templateText
258: + " <GeometryElement>gml:LineStringProperty</GeometryElement>\n";
259:
260: templateText = templateText
261: + " <GeometryElement>gml:MultiPointProperty</GeometryElement>\n";
262: templateText = templateText
263: + " <GeometryElement>gml:MultiPolygonProperty</GeometryElement>\n";
264: templateText = templateText
265: + " <GeometryElement>gml:MultiLineStringProperty</GeometryElement>\n";
266:
267: templateText = templateText
268: + " <GeometryElement>gml:MultiGeometryProperty</GeometryElement>\n";
269:
270: templateText = templateText + " <ColumnDefinitions>\n";
271: templateText = templateText + columns;
272: templateText = templateText + " </ColumnDefinitions>\n";
273: templateText = templateText + "</JCSGMLInputTemplate>\n";
274:
275: // System.out.println(templateText);
276: java.io.StringReader sr = new java.io.StringReader(templateText);
277: result = new GMLInputTemplate();
278: result.load(sr, "Auto created FME GML input template");
279: sr.close();
280:
281: return result;
282: }
283:
284: /**
285: * converts the name of an FME type to a JCS type (STRING,DOUBLE, INTEGER)
286: *
287: * @param fmeType type that fme reports (ie. fme_char, fme_decimal, long)
288: */
289: String FMEtypeToJCSType(String fmeType) {
290: if (fmeType.indexOf("fme_char") > -1) {
291: return "STRING";
292: }
293:
294: if (fmeType.indexOf("fme_decimal") > -1) {
295: int loc;
296:
297: loc = fmeType.indexOf(",");
298:
299: if ((loc == -1) || (loc == (fmeType.length() - 1))) {
300: return "STRING"; //bad
301: }
302:
303: if (fmeType.substring(loc + 1, loc + 2).equalsIgnoreCase(
304: "0")) {
305: return "INTEGER";
306: }
307:
308: return "DOUBLE";
309: }
310:
311: if (fmeType.indexOf("long") > -1) {
312: return "DOUBLE"; // strange but true!
313: }
314:
315: return "STRING";
316:
317: //Note that there is no FME "date" type. FME's Shapefile=>GML conversion converts
318: //dates to strings. [Jon Aquino]
319: }
320: }
|