Revision 47632

View differences:

trunk/org.gvsig.desktop/org.gvsig.desktop.compat.cdc/org.gvsig.fmap.geometry/org.gvsig.fmap.geometry.jts/src/main/java/org/gvsig/fmap/geom/jts/DefaultGeometryManager.java
56 56
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
57 57
import org.gvsig.fmap.geom.exception.CreateGeometryException;
58 58
import org.gvsig.fmap.geom.jts.coerce.DefaultGeometryCoercionContext;
59
import org.gvsig.fmap.geom.jts.gml.GMLReader;
59 60
import org.gvsig.fmap.geom.jts.gputils.DefaultGeneralPathX;
60 61
import org.gvsig.fmap.geom.jts.primitive.DefaultNullGeometry;
61 62
import org.gvsig.fmap.geom.jts.primitive.Envelope2D;
......
762 763
        char ch;
763 764
        int i=0;
764 765
        while(i < s.length()) {
765
            if( !Character.isSpaceChar(ch = s.charAt(i++)) ) {
766
            if( !Character.isWhitespace(ch = s.charAt(i++)) ) {
766 767
                return ch;
767 768
            }
768 769
        }
......
774 775
            int ch;
775 776
            int i=0;
776 777
            while( (ch=r.read())!= -1) {
777
                if( !Character.isSpaceChar(ch) ) {
778
                if( !Character.isWhitespace(ch) ) {
778 779
                    return ch;
779 780
                }
780 781
            }
......
842 843
                switch(ch) {
843 844
                    case '0':
844 845
                    case '1':
846
                        geom.reset();
847
                        //FIXME: Habr?a que eliminar los blancos
845 848
                        return createFrom(Hex.decodeHex(IOUtils.toCharArray(geom)), srs);
846 849
                    case '{':
847 850
                        try {
851
                            geom.reset();
848 852
                            com.vividsolutions.jts.io.geojson.GeoJsonReader reader = new com.vividsolutions.jts.io.geojson.GeoJsonReader();
849 853
                            com.vividsolutions.jts.geom.Geometry geom_jts = reader.read(geom);
850 854
                            return JTSUtils.createGeometry(srs, geom_jts);
......
857 861
                            char[] buffer = new char[100];
858 862
                            IOUtils.read(geom, buffer);
859 863
                            String s = new String(buffer);
860
                            if( StringUtils.startsWithIgnoreCase(s,"<gml:") ) {
861
                                com.vividsolutions.jts.io.gml2.GMLReader reader = new com.vividsolutions.jts.io.gml2.GMLReader();
864
                            if( StringUtils.startsWithIgnoreCase(s,"gml:") ) {
865
                                geom.reset();
866
                                GMLReader reader = new GMLReader();
862 867
                                com.vividsolutions.jts.geom.Geometry geom_jts = reader.read(
863 868
                                        geom, 
864 869
                                        new com.vividsolutions.jts.geom.GeometryFactory()
......
866 871
                                return JTSUtils.createGeometry(srs, geom_jts);
867 872
                            }
868 873
                        } catch(Exception ex) {
869
                            LOGGER.debug("Can't parse as GML");
874
                            LOGGER.debug("Can't parse as GML", ex);
870 875
                        }
871 876
                        break;
872 877
                }
trunk/org.gvsig.desktop/org.gvsig.desktop.compat.cdc/org.gvsig.fmap.geometry/org.gvsig.fmap.geometry.jts/src/main/java/org/gvsig/fmap/geom/jts/gml/GeometryStrategiesGML3.java
1
/*
2
 * To change this license header, choose License Headers in Project Properties.
3
 * To change this template file, choose Tools | Templates
4
 * and open the template in the editor.
5
 */
6
package org.gvsig.fmap.geom.jts.gml;
7

  
8
import com.vividsolutions.jts.geom.Coordinate;
9
import com.vividsolutions.jts.geom.CoordinateSequence;
10
import com.vividsolutions.jts.geom.GeometryFactory;
11
import com.vividsolutions.jts.geom.LinearRing;
12
import com.vividsolutions.jts.geom.MultiPolygon;
13
import com.vividsolutions.jts.geom.Polygon;
14
import com.vividsolutions.jts.io.gml2.GMLConstants;
15
import java.util.HashMap;
16
import java.util.List;
17
import org.apache.commons.lang3.StringUtils;
18
import org.apache.commons.lang3.tuple.ImmutablePair;
19
import org.apache.commons.lang3.tuple.Pair;
20
import static org.gvsig.fmap.geom.jts.gml.GeometryStrategies.getSrid;
21
import org.xml.sax.SAXException;
22

  
23
/**
24
 *
25
 * @author fdiaz
26
 */
27
public class GeometryStrategiesGML3 {
28

  
29
    @SuppressWarnings("Convert2Lambda")
30
    public static HashMap loadStrategies(HashMap strats) {
31
        
32
        GeometryStrategies.ParseStrategy oneChild = new GeometryStrategies.ParseStrategy() {
33

  
34
            public Object parse(GMLHandler.Handler arg, GeometryFactory gf) throws SAXException {
35
                if (arg.children.size() != 1) {
36
                    throw new SAXException("Geometry Members may only contain one geometry.");
37
                }
38

  
39
                // type checking will occur in the parent geom collection.
40
                // may wish to add this in the future
41
                return arg.children.get(0);
42
            }
43
        };
44

  
45
        GeometryStrategies.ParseStrategy manyChilds = new GeometryStrategies.ParseStrategy() {
46

  
47
            public Object parse(GMLHandler.Handler arg, GeometryFactory gf) throws SAXException {
48
                return arg.children;
49
            }
50
        };
51
        
52
        strats.put("pos".toLowerCase(), new GeometryStrategies.ParseStrategy() {
53

  
54
            @Override
55
            public Object parse(GMLHandler.Handler arg, GeometryFactory gf) throws SAXException {
56
                String[] ss = StringUtils.split(arg.text.toString(), ' ');
57
                Coordinate c = new Coordinate();
58
                c.x = Double.parseDouble(ss[0]);
59
                if (ss.length > 1) {
60
                    c.y = Double.parseDouble(ss[1]);
61
                }
62
                if (ss.length > 3) {
63
                    c.z = Double.parseDouble(ss[2]);
64
                }
65
                return c;
66
            }
67
        });
68

  
69
        strats.put("posList".toLowerCase(), new GeometryStrategies.ParseStrategy() {
70

  
71
            public Object parse(GMLHandler.Handler arg, GeometryFactory gf) throws SAXException {
72
                if (arg.text == null || "".equals(arg.text)) {
73
                    throw new SAXException("Cannot create a coordinate sequence without text to parse");
74
                }
75

  
76
                String coordSeperator = " ";
77
                int srsDimension = 2;
78

  
79
                if (arg.attrs.getIndex("cs") >= 0) {
80
                    coordSeperator = arg.attrs.getValue("cs");
81
                } else if (arg.attrs.getIndex(GMLConstants.GML_NAMESPACE, "cs") >= 0) {
82
                    coordSeperator = arg.attrs.getValue(GMLConstants.GML_NAMESPACE, "cs");
83
                }
84

  
85
                if (arg.attrs.getIndex("srsDimension") >= 0) {
86
                    srsDimension = Integer.parseInt(arg.attrs.getValue("srsDimension"));
87
                } else if (arg.attrs.getIndex(GMLConstants.GML_NAMESPACE, "srsDimension") >= 0) {
88
                    srsDimension = Integer.parseInt(arg.attrs.getValue(GMLConstants.GML_NAMESPACE, "srsDimension"));
89
                }
90

  
91
                // now to start parse
92
                String t = arg.text.toString();
93
                t = t.replaceAll("\\s", " ");
94
                String[] ss = StringUtils.split(t,coordSeperator);
95
                int len = ss.length/srsDimension;
96
                CoordinateSequence cs = gf.getCoordinateSequenceFactory().create(len, srsDimension);
97
                for (int i = 0; i < len; i++) {
98
                    cs.setOrdinate(i, 0, Double.parseDouble(ss[i*2]));
99
                    if(srsDimension > 1) {
100
                        cs.setOrdinate(i, 1, Double.parseDouble(ss[(i*2)+1]));
101
                    }
102
                    if(srsDimension > 2) {
103
                        cs.setOrdinate(i, 2, Double.parseDouble(ss[(i*2)+2]));
104
                    }
105
                }
106
       
107
                return cs;
108
            }
109
        });
110

  
111
        strats.put("PolygonPatch".toLowerCase(), new GeometryStrategies.ParseStrategy() {
112

  
113
            public Object parse(GMLHandler.Handler arg, GeometryFactory gf) throws SAXException {
114
                Object exterior = arg.children.get(0);
115
                Object interior = null;
116
                if(arg.children.size() > 1){
117
                    interior = arg.children.get(1);
118
                }
119
                return new ImmutablePair(exterior, interior);
120
            }
121
        });
122

  
123
        strats.put("patches".toLowerCase(), new GeometryStrategies.ParseStrategy() {
124

  
125
            public Object parse(GMLHandler.Handler arg, GeometryFactory gf) throws SAXException {
126
                return arg.children;
127
            }
128
        });
129

  
130
        strats.put("Surface".toLowerCase(), new GeometryStrategies.ParseStrategy() {
131

  
132
            public Object parse(GMLHandler.Handler arg, GeometryFactory gf) throws SAXException {
133

  
134
                List<Pair<LinearRing,List<LinearRing>>> patches = (List<Pair<LinearRing,List<LinearRing>>>) arg.children.get(0);
135
                LinearRing shell = patches.get(0).getLeft();
136
                List<LinearRing> holes = patches.get(0).getRight();
137
                Polygon polygon;
138
                if(holes == null){
139
                    polygon = gf.createPolygon(shell);
140
                } else {
141
                    polygon = gf.createPolygon(shell, holes.toArray(new LinearRing[holes.size()]));
142
                }
143
                int srid = getSrid(arg.attrs,gf.getSRID());
144
                if (polygon.getSRID() != srid) {
145
                    polygon.setSRID(srid);
146
                }
147

  
148
                return polygon;
149
            }
150
        });
151

  
152
        strats.put("exterior".toLowerCase(), oneChild);
153
        strats.put("surfaceMember".toLowerCase(), oneChild);
154

  
155
        strats.put("interior".toLowerCase(), manyChilds);
156
        
157
        strats.put("MultiSurface".toLowerCase(), new GeometryStrategies.ParseStrategy() {
158

  
159
            public Object parse(GMLHandler.Handler arg, GeometryFactory gf) throws SAXException {
160

  
161
                List<Polygon> polygons = arg.children;
162
                MultiPolygon multiPolygon = gf.createMultiPolygon(polygons.toArray(new Polygon[polygons.size()]));
163
                int srid = getSrid(arg.attrs,gf.getSRID());
164
                if (multiPolygon.getSRID() != srid) {
165
                    multiPolygon.setSRID(srid);
166
                }
167
                return multiPolygon;
168

  
169
            }
170
        });
171

  
172

  
173
        return strats;
174

  
175
    }
176

  
177
}
trunk/org.gvsig.desktop/org.gvsig.desktop.compat.cdc/org.gvsig.fmap.geometry/org.gvsig.fmap.geometry.jts/src/main/java/org/gvsig/fmap/geom/jts/gml/GMLHandler.java
1
/*
2
 * The JTS Topology Suite is a collection of Java classes that
3
 * implement the fundamental operations required to validate a given
4
 * geo-spatial data set to a known topological specification.
5
 *
6
 * Copyright (C) 2001 Vivid Solutions
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2.1 of the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with this library; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
 *
22
 * For more information, contact:
23
 *
24
 *     Vivid Solutions
25
 *     Suite #1A
26
 *     2328 Government Street
27
 *     Victoria BC  V8T 5G5
28
 *     Canada
29
 *
30
 *     (250)385-6040
31
 *     www.vividsolutions.com
32
 */
33
package org.gvsig.fmap.geom.jts.gml;
34

  
35
import com.vividsolutions.jts.geom.Geometry;
36
import com.vividsolutions.jts.geom.GeometryFactory;
37
import java.util.*;
38
import org.gvsig.fmap.geom.jts.gml.GeometryStrategies.ParseStrategy;
39
import org.xml.sax.*;
40
import org.xml.sax.helpers.AttributesImpl;
41
import org.xml.sax.helpers.DefaultHandler;
42

  
43
/**
44
 * A SAX {@link DefaultHandler} which builds {@link Geometry}s 
45
 * from GML2-formatted geometries.
46
 * An XML parser can delegate SAX events to this handler
47
 * to parse and building Geometrys. 
48
 * <p>
49
 * This handler currently ignores both namespaces and prefixes. 
50
 * 
51
 * Hints: 
52
 * <ul>
53
 * <li>If your parent handler is a DefaultHandler register the parent handler to receive the errors and locator calls.
54
 * <li>Use {@link GeometryStrategies#findStrategy(String, String)} to help check for applicability
55
 * </ul>
56
 * 
57
 * @see DefaultHandler
58
 *
59
 * @author David Zwiers, Vivid Solutions. 
60
 */
61
public class GMLHandler extends DefaultHandler {
62

  
63
	/**
64
	 * This class is intended to log the SAX acitivity within a given element until its termination. 
65
	 * At this time, a new object of value is created and passed to the parent. 
66
	 * An object of value is typically either java.lang.* or a JTS Geometry
67
	 * This class is not intended for use outside this distribution, 
68
	 * and may change in subsequent versions.
69
	 *
70
	 * @author David Zwiers, Vivid Solutions.
71
	 */
72
	static class Handler {
73
		protected Attributes attrs = null;
74

  
75
		protected ParseStrategy strategy;
76

  
77
		/**
78
		 * @param strategy 
79
		 * @param attributes Nullable
80
		 */
81
		public Handler(ParseStrategy strategy, Attributes attributes) {
82
			if (attributes != null)
83
				this.attrs = new AttributesImpl(attributes);
84
			this.strategy = strategy;
85
		}
86

  
87
		protected StringBuffer text = null;
88

  
89
		/**
90
		 * Caches text for the future
91
		 * @param str
92
		 */
93
		public void addText(String str) {
94
			if (text == null)
95
				text = new StringBuffer();
96
			text.append(str);
97
		}
98

  
99
		protected List children = null;
100

  
101
		/**
102
		 * Store param for the future
103
		 * 
104
		 * @param obj
105
		 */
106
		public void keep(Object obj) {
107
			if (children == null)
108
				children = new LinkedList();
109
			children.add(obj);
110

  
111
		}
112

  
113
		/**
114
		 * @param gf GeometryFactory
115
		 * @return Parsed Object
116
		 * @throws SAXException 
117
		 */
118
		public Object create(GeometryFactory gf) throws SAXException {
119
                    System.out.println("create "+this.strategy.getClass().getSimpleName());
120
                    return strategy.parse(this, gf);
121
		}
122
	}
123

  
124
	private Stack stack = new Stack();
125

  
126
	private ErrorHandler delegate = null;
127

  
128
	private GeometryFactory gf = null;
129

  
130
	/**
131
	 * Creates a new handler.
132
	 * Allows the user to specify a delegate object for error / warning messages. 
133
	 * If the delegate also implements ContentHandler then the document Locator will be passed on.
134
	 * 
135
	 * @param gf Geometry Factory
136
	 * @param delegate Nullable
137
	 * 
138
	 * @see ErrorHandler
139
	 * @see ContentHandler
140
	 * @see ContentHandler#setDocumentLocator(org.xml.sax.Locator)
141
	 * @see org.xml.sax.Locator
142
	 * 
143
	 */
144
	public GMLHandler(GeometryFactory gf, ErrorHandler delegate) {
145
		this.delegate = delegate;
146
		this.gf = gf;
147
		stack.push(new Handler(null, null));
148
	}
149

  
150
	/**
151
	 * Tests whether this handler has completed parsing 
152
	 * a geometry.
153
	 * If this is the case, {@link #getGeometry()} can be called
154
	 * to get the value of the parsed geometry.
155
	 * 
156
	 * @return if the parsing of the geometry is complete
157
	 */
158
	public boolean isGeometryComplete()
159
	{
160
		if (stack.size() > 1)
161
			return false;
162
		// top level node on stack needs to have at least one child 
163
		Handler h = (Handler) stack.peek();
164
		if (h.children.size() < 1)
165
			return false;
166
		return true;
167
		
168
	}
169
	
170
	/**
171
	 * Gets the geometry parsed by this handler.
172
	 * This method should only be called AFTER the parser has completed execution
173
	 * 
174
	 * @return the parsed Geometry, or a GeometryCollection if more than one geometry was parsed
175
	 * @throws IllegalStateException if called before the parse is complete
176
	 */
177
	public Geometry getGeometry() {
178
		if (stack.size() == 1) {
179
			Handler h = (Handler) stack.peek();
180
			if (h.children.size() == 1)
181
				return (Geometry) h.children.get(0);
182
			return gf.createGeometryCollection(
183
					(Geometry[]) h.children.toArray(new Geometry[stack.size()]));
184
		}
185
		throw new IllegalStateException(
186
				"Parse did not complete as expected, there are " + stack.size()
187
						+ " elements on the Stack");
188
	}
189

  
190
	//////////////////////////////////////////////
191
	// Parsing Methods
192

  
193
	/**
194
	 * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
195
	 */
196
	public void characters(char[] ch, int start, int length) throws SAXException {
197
		if (!stack.isEmpty())
198
			((Handler) stack.peek()).addText(new String(ch, start, length));
199
	}
200

  
201
	/**
202
	 * @see org.xml.sax.helpers.DefaultHandler#ignorableWhitespace(char[], int, int)
203
	 */
204
	public void ignorableWhitespace(char[] ch, int start, int length)
205
			throws SAXException {
206
		if (!stack.isEmpty())
207
			((Handler) stack.peek()).addText(" ");
208
	}
209

  
210
	/**
211
	 * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
212
	 */
213
	public void endElement(String uri, String localName, String qName)
214
			throws SAXException {
215
            System.out.println("endElement: "+localName +" , "+qName);
216
		Handler thisAction = (Handler) stack.pop();
217
		((Handler) stack.peek()).keep(thisAction.create(gf));
218
	}
219

  
220
	/**
221
	 * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
222
	 */
223
	public void startElement(String uri, String localName, String qName,
224
			Attributes attributes) throws SAXException {
225
            System.out.println("startElement: "+localName +" , "+qName);
226
		// create a handler
227
		ParseStrategy ps = GeometryStrategies.findStrategy(uri, localName);
228
		if (ps == null) {
229
			String qn = qName.substring(qName.indexOf(':') + 1, qName.length());
230
			ps = GeometryStrategies.findStrategy(null, qn);
231
		}
232
		Handler h = new Handler(ps, attributes);
233
		// and add it to the stack
234
		stack.push(h);
235
	}
236

  
237
	//////////////////////////////////////////////
238
	// Logging Methods
239

  
240
	/**
241
	 * @see org.xml.sax.helpers.DefaultHandler#setDocumentLocator(org.xml.sax.Locator)
242
	 */
243
	public void setDocumentLocator(Locator locator) {
244
		this.locator = locator;
245
		if (delegate != null && delegate instanceof ContentHandler)
246
			((ContentHandler) delegate).setDocumentLocator(locator);
247

  
248
	}
249

  
250
	private Locator locator = null;
251

  
252
	protected Locator getDocumentLocator() {
253
		return locator;
254
	}
255

  
256
	//////////////////////////////////////////////
257
	// ERROR Methods
258

  
259
	/**
260
	 * @see org.xml.sax.helpers.DefaultHandler#fatalError(org.xml.sax.SAXParseException)
261
	 */
262
	public void fatalError(SAXParseException e) throws SAXException {
263
		if (delegate != null)
264
			delegate.fatalError(e);
265
		else
266
			super.fatalError(e);
267
	}
268

  
269
	/**
270
	 * @see org.xml.sax.helpers.DefaultHandler#error(org.xml.sax.SAXParseException)
271
	 */
272
	public void error(SAXParseException e) throws SAXException {
273
		if (delegate != null)
274
			delegate.error(e);
275
		else
276
			super.error(e);
277
	}
278

  
279
	/**
280
	 * @see org.xml.sax.helpers.DefaultHandler#warning(org.xml.sax.SAXParseException)
281
	 */
282
	public void warning(SAXParseException e) throws SAXException {
283
		if (delegate != null)
284
			delegate.warning(e);
285
		else
286
			super.warning(e);
287
	}
288

  
289
}
trunk/org.gvsig.desktop/org.gvsig.desktop.compat.cdc/org.gvsig.fmap.geometry/org.gvsig.fmap.geometry.jts/src/main/java/org/gvsig/fmap/geom/jts/gml/GMLReader.java
1
/*
2
 * The JTS Topology Suite is a collection of Java classes that
3
 * implement the fundamental operations required to validate a given
4
 * geo-spatial data set to a known topological specification.
5
 *
6
 * Copyright (C) 2001 Vivid Solutions
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2.1 of the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with this library; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
 *
22
 * For more information, contact:
23
 *
24
 *     Vivid Solutions
25
 *     Suite #1A
26
 *     2328 Government Street
27
 *     Victoria BC  V8T 5G5
28
 *     Canada
29
 *
30
 *     (250)385-6040
31
 *     www.vividsolutions.com
32
 */
33
package org.gvsig.fmap.geom.jts.gml;
34

  
35
import java.io.*;
36

  
37
import javax.xml.parsers.*;
38

  
39
import org.xml.sax.InputSource;
40
import org.xml.sax.SAXException;
41
import org.xml.sax.helpers.DefaultHandler;
42

  
43
import com.vividsolutions.jts.geom.*;
44

  
45
/**
46
 * Reads a GML2 geometry from an XML fragment into a {@link Geometry}.
47
 * <p>
48
 * An example of the GML2 format handled is:
49
 * <pre>
50
 *   <LineString>
51
 *  	<coordinates>24824.045318333192,38536.15071012041
52
 *  		26157.378651666528,37567.42733944659 26666.666,36000.0
53
 *  		26157.378651666528,34432.57266055341
54
 *  		24824.045318333192,33463.84928987959
55
 *  		23175.954681666804,33463.84928987959
56
 *  		21842.621348333472,34432.57266055341 21333.333,36000.0
57
 *  		21842.621348333472,37567.42733944659
58
 *  		23175.954681666808,38536.15071012041 </coordinates>
59
 *  </LineString>
60
 * </pre>
61
 *
62
 * The reader ignores namespace prefixes, 
63
 * and disables both the validation and namespace options on the <tt>SAXParser</tt>.
64
 * This class requires the presence of a SAX Parser available via the 
65
 * {@link javax.xml.parsers.SAXParserFactory#newInstance()}
66
 * method.
67
 * <p>
68
 * A specification of the GML XML format 
69
 * can be found at the OGC web site: <a href='http://www.opengeospatial.org/'>http://www.opengeospatial.org/</a>.
70
 * <p>
71
 * It is the caller's responsibility to ensure that the supplied {@link PrecisionModel}
72
 * matches the precision of the incoming data.
73
 * If a lower precision for the data is required, a subsequent
74
 * process must be run on the data to reduce its precision.
75
 * <p>
76
 * To parse and build geometry directly from a SAX stream, see {@link GMLHandler}.
77
 *
78
 * @author David Zwiers, Vivid Solutions.
79
 * 
80
 * @see GMLHandler
81
 */
82
public class GMLReader 
83
{
84

  
85
	/**
86
	 * Reads a GML2 Geometry from a <tt>String</tt> into a single {@link Geometry}
87
	 *
88
	 * If a collection of geometries is found, a {@link GeometryCollection} is returned.
89
	 *
90
	 * @param gml The GML String to parse
91
	 * @param geometryFactory When null, a default will be used.
92
	 * @return the resulting JTS Geometry
93
	 * 
94
	 * @throws ParserConfigurationException
95
	 * @throws IOException
96
	 * @throws SAXException
97
	 *
98
	 * @see #read(Reader, GeometryFactory)
99
	 */
100
	public Geometry read(String gml, GeometryFactory geometryFactory) throws SAXException, IOException, ParserConfigurationException{
101
		return read(new StringReader(gml),geometryFactory);
102
	}
103

  
104
	/**
105
	 * Reads a GML2 Geometry from a {@link Reader} into a single {@link Geometry}
106
	 *
107
	 * If a collection of Geometries is found, a {@link GeometryCollection} is returned.
108
	 *
109
	 * @param reader The input source
110
	 * @param geometryFactory When null, a default will be used.
111
	 * @return The resulting JTS Geometry
112
	 * @throws SAXException
113
	 * @throws IOException
114
	 */
115
	public Geometry read(Reader reader, GeometryFactory geometryFactory) throws SAXException, IOException, ParserConfigurationException{
116
		SAXParserFactory fact = SAXParserFactory.newInstance();
117

  
118
		fact.setNamespaceAware(false);
119
		fact.setValidating(false);
120

  
121
		SAXParser parser = fact.newSAXParser();
122

  
123
		if(geometryFactory == null)
124
			geometryFactory = new GeometryFactory();
125

  
126
		GMLHandler gh = new GMLHandler(geometryFactory,null);
127
		parser.parse(new InputSource(reader), (DefaultHandler)gh);
128

  
129
		return gh.getGeometry();
130
	}
131

  
132
}
trunk/org.gvsig.desktop/org.gvsig.desktop.compat.cdc/org.gvsig.fmap.geometry/org.gvsig.fmap.geometry.jts/src/main/java/org/gvsig/fmap/geom/jts/gml/GeometryStrategies.java
1
/*
2
 * The JTS Topology Suite is a collection of Java classes that
3
 * implement the fundamental operations required to validate a given
4
 * geo-spatial data set to a known topological specification.
5
 *
6
 * Copyright (C) 2001 Vivid Solutions
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2.1 of the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with this library; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
 *
22
 * For more information, contact:
23
 *
24
 *     Vivid Solutions
25
 *     Suite #1A
26
 *     2328 Government Street
27
 *     Victoria BC  V8T 5G5
28
 *     Canada
29
 *
30
 *     (250)385-6040
31
 *     www.vividsolutions.com
32
 */
33
package org.gvsig.fmap.geom.jts.gml;
34

  
35
import java.util.*;
36
import java.util.regex.Pattern;
37

  
38
import org.xml.sax.Attributes;
39
import org.xml.sax.SAXException;
40

  
41
import com.vividsolutions.jts.geom.*;
42
import com.vividsolutions.jts.io.gml2.GMLConstants;
43
import com.vividsolutions.jts.util.StringUtil;
44
import org.apache.commons.lang3.StringUtils;
45
import org.gvsig.fmap.geom.jts.gml.GMLHandler.Handler;
46

  
47
/**
48
 * Container for GML2 Geometry parsing strategies which can be represented in JTS.
49
 *
50
 * @author David Zwiers, Vivid Solutions.
51
 */
52
public class GeometryStrategies{
53

  
54
	/**
55
	 * This set of strategies is not expected to be used directly outside of this distribution.
56
	 * 
57
	 * The implementation of this class are intended to be used as static function points in C. These strategies should be associated with an element when the element begins. The strategy is utilized at the end of the element to create an object of value to the user. 
58
	 * 
59
	 * In this case all the objects are either java.lang.* or JTS Geometry objects
60
	 *
61
	 * @author David Zwiers, Vivid Solutions.
62
	 */
63
	static interface ParseStrategy{
64
		/**
65
		 * @param arg Value to interpret
66
		 * @param gf GeometryFactory
67
		 * @return The interpreted value
68
		 * @throws SAXException 
69
		 */
70
		Object parse(Handler arg, GeometryFactory gf) throws SAXException;
71
	}
72
	
73
	private static HashMap strategies = loadStrategies();
74
	private static HashMap loadStrategies(){
75
		HashMap strats = new HashMap();
76
                loadStrategies(strats);
77
                GeometryStrategiesGML3.loadStrategies(strats);
78
                return strats;
79
            
80
        }
81
        
82
	private static HashMap loadStrategies(HashMap strats){
83
		
84
		// point
85
		strats.put(GMLConstants.GML_POINT.toLowerCase(),new ParseStrategy(){
86

  
87
			public Object parse(Handler arg, GeometryFactory gf) throws SAXException {
88
				// one child, either a coord
89
				// or a coordinate sequence
90
				
91
				if(arg.children.size()!=1)
92
					throw new SAXException("Cannot create a point without exactly one coordinate");
93

  
94
				int srid = getSrid(arg.attrs,gf.getSRID());
95

  
96
				Object c = arg.children.get(0);
97
				Point p = null;
98
				if(c instanceof Coordinate){
99
					p = gf.createPoint((Coordinate)c);
100
				}else{
101
					p = gf.createPoint((CoordinateSequence)c);
102
				}
103
				if(p.getSRID()!=srid)
104
					p.setSRID(srid);
105
				
106
				return p;
107
			}
108
		});
109
		
110
		// linestring
111
		strats.put(GMLConstants.GML_LINESTRING.toLowerCase(),new ParseStrategy(){
112

  
113
			public Object parse(Handler arg, GeometryFactory gf) throws SAXException {
114
				// one child, either a coord
115
				// or a coordinate sequence
116
				
117
				if(arg.children.size()<1)
118
					throw new SAXException("Cannot create a linestring without atleast two coordinates or one coordinate sequence");
119

  
120
				int srid = getSrid(arg.attrs,gf.getSRID());
121
				
122
				LineString ls = null;
123
				if(arg.children.size() == 1){
124
					// coord set
125
					try{
126
						CoordinateSequence cs = (CoordinateSequence) arg.children.get(0);
127
						ls = gf.createLineString(cs);
128
					}catch(ClassCastException e){
129
						throw new SAXException("Cannot create a linestring without atleast two coordinates or one coordinate sequence",e);
130
					}
131
				}else{
132
					try{
133
						Coordinate[] coords = (Coordinate[]) arg.children.toArray(new Coordinate[arg.children.size()]);
134
						ls = gf.createLineString(coords);
135
					}catch(ClassCastException e){
136
						throw new SAXException("Cannot create a linestring without atleast two coordinates or one coordinate sequence",e);
137
					}
138
				}
139
				
140
				if(ls.getSRID()!=srid)
141
					ls.setSRID(srid);
142
				
143
				return ls;
144
			}
145
		});
146
		
147
		// linearring
148
		strats.put(GMLConstants.GML_LINEARRING.toLowerCase(),new ParseStrategy(){
149

  
150
			public Object parse(Handler arg, GeometryFactory gf) throws SAXException {
151
				// one child, either a coord
152
				// or a coordinate sequence
153
				
154
				if(arg.children.size()!=1 && arg.children.size()<4)
155
					throw new SAXException("Cannot create a linear ring without atleast four coordinates or one coordinate sequence");
156

  
157
				int srid = getSrid(arg.attrs,gf.getSRID());
158
				
159
				LinearRing ls = null;
160
				if(arg.children.size() == 1){
161
					// coord set
162
					try{
163
						CoordinateSequence cs = (CoordinateSequence) arg.children.get(0);
164
						ls = gf.createLinearRing(cs);
165
					}catch(ClassCastException e){
166
						throw new SAXException("Cannot create a linear ring without atleast four coordinates or one coordinate sequence",e);
167
					}
168
				}else{
169
					try{
170
						Coordinate[] coords = (Coordinate[]) arg.children.toArray(new Coordinate[arg.children.size()]);
171
						ls = gf.createLinearRing(coords);
172
					}catch(ClassCastException e){
173
						throw new SAXException("Cannot create a linear ring without atleast four coordinates or one coordinate sequence",e);
174
					}
175
				}
176
				
177
				if(ls.getSRID()!=srid)
178
					ls.setSRID(srid);
179
				
180
				return ls;
181
			}
182
		});
183
		
184
		// polygon
185
		strats.put(GMLConstants.GML_POLYGON.toLowerCase(),new ParseStrategy(){
186

  
187
			public Object parse(Handler arg, GeometryFactory gf) throws SAXException {
188
				// one child, either a coord
189
				// or a coordinate sequence
190
				
191
				if(arg.children.size()<1)
192
					throw new SAXException("Cannot create a polygon without atleast one linear ring");
193

  
194
				int srid = getSrid(arg.attrs,gf.getSRID());
195
				
196
				LinearRing outer = (LinearRing) arg.children.get(0); // will be the first
197
				List t = arg.children.size()>1?arg.children.subList(1,arg.children.size()):null;
198
				LinearRing[] inner = t==null?null:(LinearRing[]) t.toArray(new LinearRing[t.size()]);
199
				
200
				Polygon p = gf.createPolygon(outer,inner);
201
				
202
				if(p.getSRID()!=srid)
203
					p.setSRID(srid);
204
				
205
				return p;
206
			}
207
		});
208
		
209
		// box
210
		strats.put(GMLConstants.GML_BOX.toLowerCase(),new ParseStrategy(){
211

  
212
			public Object parse(Handler arg, GeometryFactory gf) throws SAXException {
213
				// one child, either a coord
214
				// or a coordinate sequence
215
				
216
				if(arg.children.size()<1 || arg.children.size()>2)
217
					throw new SAXException("Cannot create a box without either two coords or one coordinate sequence");
218

  
219
//				int srid = getSrid(arg.attrs,gf.getSRID());
220
				
221
				Envelope box = null;
222
				if(arg.children.size() == 1){
223
					CoordinateSequence cs = (CoordinateSequence) arg.children.get(0);
224
					box = cs.expandEnvelope(new Envelope());
225
				}else{
226
					box = new Envelope((Coordinate)arg.children.get(0),(Coordinate)arg.children.get(1));
227
				}
228
				
229
				return box;
230
			}
231
		});
232
		
233
		// multi-point
234
		strats.put(GMLConstants.GML_MULTI_POINT.toLowerCase(),new ParseStrategy(){
235

  
236
			public Object parse(Handler arg, GeometryFactory gf) throws SAXException {
237
				// one child, either a coord
238
				// or a coordinate sequence
239
				
240
				if(arg.children.size()<1)
241
					throw new SAXException("Cannot create a multi-point without atleast one point");
242

  
243
				int srid = getSrid(arg.attrs,gf.getSRID());
244
				
245
				Point[] pts = (Point[]) arg.children.toArray(new Point[arg.children.size()]);
246
				
247
				MultiPoint mp = gf.createMultiPoint(pts);
248
				
249
				if(mp.getSRID()!=srid)
250
					mp.setSRID(srid);
251
				
252
				return mp;
253
			}
254
		});
255
		
256
		// multi-linestring
257
		strats.put(GMLConstants.GML_MULTI_LINESTRING.toLowerCase(),new ParseStrategy(){
258

  
259
			public Object parse(Handler arg, GeometryFactory gf) throws SAXException {
260
				// one child, either a coord
261
				// or a coordinate sequence
262
				
263
				if(arg.children.size()<1)
264
					throw new SAXException("Cannot create a multi-linestring without atleast one linestring");
265

  
266
				int srid = getSrid(arg.attrs,gf.getSRID());
267
				
268
				LineString[] lns = (LineString[]) arg.children.toArray(new LineString[arg.children.size()]);
269
				
270
				MultiLineString mp = gf.createMultiLineString(lns);
271
				
272
				if(mp.getSRID()!=srid)
273
					mp.setSRID(srid);
274
				
275
				return mp;
276
			}
277
		});
278
		
279
		// multi-poly
280
		strats.put(GMLConstants.GML_MULTI_POLYGON.toLowerCase(),new ParseStrategy(){
281

  
282
			public Object parse(Handler arg, GeometryFactory gf) throws SAXException {
283
				// one child, either a coord
284
				// or a coordinate sequence
285
				
286
				if(arg.children.size()<1)
287
					throw new SAXException("Cannot create a multi-polygon without atleast one polygon");
288

  
289
				int srid = getSrid(arg.attrs,gf.getSRID());
290
				
291
				Polygon[] plys = (Polygon[]) arg.children.toArray(new Polygon[arg.children.size()]);
292
				
293
				MultiPolygon mp = gf.createMultiPolygon(plys);
294
				
295
				if(mp.getSRID()!=srid)
296
					mp.setSRID(srid);
297
				
298
				return mp;
299
			}
300
		});
301
		
302
		// multi-geom
303
		strats.put(GMLConstants.GML_MULTI_GEOMETRY.toLowerCase(),new ParseStrategy(){
304

  
305
			public Object parse(Handler arg, GeometryFactory gf) throws SAXException {
306
				// one child, either a coord
307
				// or a coordinate sequence
308
				
309
				if(arg.children.size()<1)
310
					throw new SAXException("Cannot create a multi-polygon without atleast one geometry");
311
				
312
				Geometry[] geoms = (Geometry[]) arg.children.toArray(new Geometry[arg.children.size()]);
313
				
314
				GeometryCollection gc = gf.createGeometryCollection(geoms);
315
								
316
				return gc;
317
			}
318
		});
319
		
320
		// coordinates
321
		strats.put(GMLConstants.GML_COORDINATES.toLowerCase(),new ParseStrategy(){
322

  
323
			private WeakHashMap patterns = new WeakHashMap();
324
			
325
			public Object parse(Handler arg, GeometryFactory gf) throws SAXException {
326
				// one child, either a coord
327
				// or a coordinate sequence
328

  
329
				if(arg.text == null || "".equals(arg.text))
330
					throw new SAXException("Cannot create a coordinate sequence without text to parse");
331
				
332
				String decimal = ".";
333
				String coordSeperator = ",";
334
				String toupleSeperator = " ";
335
				
336
				// get overides from coordinates
337
				if(arg.attrs.getIndex("decimal")>=0)
338
					decimal = arg.attrs.getValue("decimal");
339
				else if(arg.attrs.getIndex(GMLConstants.GML_NAMESPACE,"decimal")>=0)
340
					decimal = arg.attrs.getValue(GMLConstants.GML_NAMESPACE,"decimal");
341

  
342
				if(arg.attrs.getIndex("cs")>=0)
343
					coordSeperator = arg.attrs.getValue("cs");
344
				else if(arg.attrs.getIndex(GMLConstants.GML_NAMESPACE,"cs")>=0)
345
					coordSeperator = arg.attrs.getValue(GMLConstants.GML_NAMESPACE,"cs");
346

  
347
				if(arg.attrs.getIndex("ts")>=0)
348
					toupleSeperator = arg.attrs.getValue("ts");
349
				else if(arg.attrs.getIndex(GMLConstants.GML_NAMESPACE,"ts")>=0)
350
					toupleSeperator = arg.attrs.getValue(GMLConstants.GML_NAMESPACE,"ts");
351
				
352
				// now to start parse
353
				String t = arg.text.toString();
354
				t = t.replaceAll("\\s"," ");
355
				
356
				Pattern ptn = (Pattern) patterns.get(toupleSeperator);
357
				if(ptn == null){
358
					String ts = new String(toupleSeperator);
359
					if(ts.indexOf('\\')>-1){
360
							// need to escape it
361
							ts = ts.replaceAll("\\","\\\\");
362
					}
363
					if(ts.indexOf('.')>-1){
364
						// need to escape it
365
						ts = ts.replaceAll("\\.","\\\\.");
366
					}
367
					ptn = Pattern.compile(ts);
368
					patterns.put(toupleSeperator,ptn);
369
				}
370
				String[] touples = ptn.split(t.trim());//  t.trim().split(toupleSeperator);
371
				
372
				if(touples.length == 0)
373
					throw new SAXException("Cannot create a coordinate sequence without a touple to parse");
374
				
375
				// we may have null touples, so calculate the num first
376
				int numNonNullTouples = 0;
377
				for(int i=0;i<touples.length;i++){
378
					if(touples[i] !=null && !"".equals(touples[i].trim())){
379
						if(i!=numNonNullTouples){
380
							touples[numNonNullTouples] = touples[i]; // always shift left
381
						}
382
						numNonNullTouples++;
383
					}
384
				}
385
				for(int i=numNonNullTouples;i<touples.length;i++)
386
					touples[i] = null;
387
				
388
				// null touples now at end of array
389
				if(numNonNullTouples == 0)
390
					throw new SAXException("Cannot create a coordinate sequence without a non-null touple to parse");
391
				
392
				int dim = StringUtil.split(touples[0], coordSeperator).length;
393
				CoordinateSequence cs = gf.getCoordinateSequenceFactory().create(numNonNullTouples,dim);
394
				dim = cs.getDimension(); // max dim
395
				
396
				boolean replaceDec = !".".equals(decimal);
397
				
398
				for(int i=0;i<numNonNullTouples;i++){
399
					// for each touple, split, parse, add
400

  
401
					ptn = (Pattern) patterns.get(coordSeperator);
402
					if(ptn == null){
403
						String ts = new String(coordSeperator);
404
						if(ts.indexOf('\\')>-1){
405
								// need to escape it
406
							ts = ts.replaceAll("\\","\\\\");
407
						}
408
						if(ts.indexOf('.')>-1){
409
							// need to escape it
410
							ts = ts.replaceAll("\\.","\\\\.");
411
						}
412
						ptn = Pattern.compile(ts);
413
						patterns.put(coordSeperator,ptn);
414
					}
415
					String[] coords = ptn.split(touples[i]);//  touples[i].split(coordSeperator);
416
					
417
					int dimIndex = 0;
418
					for(int j=0;j<coords.length && j<dim;j++){
419
						if(coords[j] != null && !"".equals(coords[j].trim())){
420
							double ordinate = Double.parseDouble(replaceDec?coords[j].replaceAll(decimal,"."):coords[j]);
421
							cs.setOrdinate(i,dimIndex++,ordinate);
422
						}
423
					}
424
						// fill remaining dim
425
					for(;dimIndex<dim;)cs.setOrdinate(i,dimIndex++,Double.NaN);
426
				}
427
				
428
				return cs;
429
			}
430
		});
431
		
432
		// coord
433
		strats.put(GMLConstants.GML_COORD.toLowerCase(),new ParseStrategy(){
434

  
435
			public Object parse(Handler arg, GeometryFactory gf) throws SAXException {
436
				// one child, either a coord
437
				// or a coordinate sequence
438

  
439
				if(arg.children.size()<1)
440
					throw new SAXException("Cannot create a coordinate without atleast one axis");
441
				if(arg.children.size()>3)
442
					throw new SAXException("Cannot create a coordinate with more than 3 axis");
443
				
444
				Double[] axis = (Double[]) arg.children.toArray(new Double[arg.children.size()]);
445
				Coordinate c = new Coordinate();
446
				c.x = axis[0].doubleValue();
447
				if(axis.length>1)
448
					c.y = axis[1].doubleValue();
449
				if(axis.length>2)
450
					c.z = axis[2].doubleValue();
451
				
452
				return c;
453
			}
454
		});
455
		
456
		ParseStrategy coord_child = new ParseStrategy(){
457

  
458
			public Object parse(Handler arg, GeometryFactory gf) throws SAXException {
459
				if(arg.text == null)
460
					return null;
461
				return new Double((arg.text.toString()));
462
			}
463
		};
464
		
465
		// coord-x
466
		strats.put(GMLConstants.GML_COORD_X.toLowerCase(),coord_child);
467
		
468
		// coord-y
469
		strats.put(GMLConstants.GML_COORD_Y.toLowerCase(),coord_child);
470
		
471
		// coord-z
472
		strats.put(GMLConstants.GML_COORD_Z.toLowerCase(),coord_child);
473
		
474
		ParseStrategy member = new ParseStrategy(){
475

  
476
			public Object parse(Handler arg, GeometryFactory gf) throws SAXException {
477
				if(arg.children.size()!=1)
478
					throw new SAXException("Geometry Members may only contain one geometry.");
479
				
480
				// type checking will occur in the parent geom collection.
481
				// may wish to add this in the future
482
				
483
				return arg.children.get(0);
484
			}
485
		};
486
		// outerBoundary - linear ring member
487
		strats.put(GMLConstants.GML_OUTER_BOUNDARY_IS.toLowerCase(),member);
488
		
489
		// innerBoundary - linear ring member
490
		strats.put(GMLConstants.GML_INNER_BOUNDARY_IS.toLowerCase(),member);
491
		
492
		// point member
493
		strats.put(GMLConstants.GML_POINT_MEMBER.toLowerCase(),member);
494
		
495
		// line string member
496
		strats.put(GMLConstants.GML_LINESTRING_MEMBER.toLowerCase(),member);
497
		
498
		// polygon member
499
		strats.put(GMLConstants.GML_POLYGON_MEMBER.toLowerCase(),member);
500
		
501
		return strats;
502
	}
503
        
504
	
505
	static int getSrid(Attributes attrs, int defaultValue){
506
		String srs = null;
507
		if(attrs.getIndex(GMLConstants.GML_ATTR_SRSNAME)>=0)
508
			srs = attrs.getValue(GMLConstants.GML_ATTR_SRSNAME);
509
		else if(attrs.getIndex(GMLConstants.GML_NAMESPACE,GMLConstants.GML_ATTR_SRSNAME)>=0)
510
			srs = attrs.getValue(GMLConstants.GML_NAMESPACE,GMLConstants.GML_ATTR_SRSNAME);
511
		
512
		if(srs != null){
513
			srs = srs.trim();
514
			if(srs != null && !"".equals(srs)){
515
				try{
516
					return Integer.parseInt(srs);
517
				}catch(NumberFormatException e){
518
					// rip out the end, uri's are used here sometimes
519
					int index = srs.lastIndexOf('#');
520
					if(index > -1)
521
						srs = srs.substring(index);
522
					try{
523
						return Integer.parseInt(srs);
524
					}catch(NumberFormatException e2){
525
						// ignore
526
					}
527
				}
528
			}
529
		}
530
		
531
		return defaultValue;
532
	}
533
	
534
	/**
535
	 * @param uri Not currently used, included for future work
536
	 * @param localName Used to look up an appropriate parse strategy
537
	 * @return The ParseStrategy which should be employed
538
	 * 
539
	 * @see ParseStrategy
540
	 */
541
	public static ParseStrategy findStrategy(String uri,String localName){
542
		return localName == null?null:(ParseStrategy) strategies.get(localName.toLowerCase());
543
	}
544
}

Also available in: Unified diff