001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2002-2006, GeoTools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.gml2.bindings;
017:
018: import org.w3c.dom.Document;
019: import org.w3c.dom.Element;
020: import java.util.StringTokenizer;
021: import javax.xml.namespace.QName;
022: import com.vividsolutions.jts.geom.Coordinate;
023: import com.vividsolutions.jts.geom.CoordinateSequence;
024: import com.vividsolutions.jts.geom.CoordinateSequenceFactory;
025: import org.geotools.xml.AbstractComplexBinding;
026: import org.geotools.xml.ElementInstance;
027: import org.geotools.xml.Node;
028:
029: /**
030: * Binding object for the type http://www.opengis.net/gml:CoordinatesType.
031: *
032: * <p>
033: * <pre>
034: * <code>
035: * <complexType name="CoordinatesType">
036: * <annotation>
037: * <documentation> Coordinates can be included in a single
038: * string, but there is no facility for validating
039: * string content. The value of the 'cs' attribute
040: * is the separator for coordinate values, and the value of the
041: * 'ts' attribute gives the tuple separator
042: * (a single space by default); the default values may
043: * be changed to reflect local usage. </documentation>
044: * </annotation>
045: * <simpleContent>
046: * <extension base="string">
047: * <attribute name="decimal" type="string" use="optional" default="."/>
048: * <attribute name="cs" type="string" use="optional" default=","/>
049: * <attribute name="ts" type="string" use="optional" default=" "/>
050: * </extension>
051: * </simpleContent>
052: * </complexType>
053: *
054: * </code>
055: * </pre>
056: * </p>
057: *
058: * @generated
059: */
060: public class GMLCoordinatesTypeBinding extends AbstractComplexBinding {
061: CoordinateSequenceFactory csFactory;
062:
063: public GMLCoordinatesTypeBinding(CoordinateSequenceFactory csFactory) {
064: this .csFactory = csFactory;
065: }
066:
067: /**
068: * @generated
069: */
070: public QName getTarget() {
071: return GML.CoordinatesType;
072: }
073:
074: /**
075: * <!-- begin-user-doc -->
076: * <!-- end-user-doc -->
077: *
078: * @generated modifiable
079: */
080: public Class getType() {
081: return CoordinateSequence.class;
082: }
083:
084: /**
085: * <!-- begin-user-doc -->
086: * Returns an object of type {@see com.vividsolutions.jts.geom.CoordinateSequence}
087: * TODO: this method should do more validation of the string
088: * <!-- end-user-doc -->
089: *
090: * @generated modifiable
091: */
092: public Object parse(ElementInstance instance, Node node,
093: Object value) throws Exception {
094: //get the coordinate and tuple seperators
095: String decimal = ".";
096: String cs = ",";
097: String ts = " ";
098:
099: if (node.getAttribute("decimal") != null) {
100: decimal = (String) node.getAttribute("decimal").getValue();
101: }
102:
103: if (node.getAttribute("cs") != null) {
104: cs = (String) node.getAttribute("cs").getValue();
105: }
106:
107: if (node.getAttribute("ts") != null) {
108: ts = (String) node.getAttribute("ts").getValue();
109: }
110:
111: //do the parsing
112: String text = instance.getText();
113:
114: //first tokenize by tuple seperators
115: StringTokenizer tuples = new StringTokenizer(text, ts);
116: CoordinateSequence seq = null;
117: int i = 0;
118: int ncoords = tuples.countTokens(); //number of coordinates
119:
120: while (tuples.hasMoreTokens()) {
121: String tuple = tuples.nextToken();
122:
123: //next tokenize by coordinate seperator
124: String[] oords = tuple.split(cs);
125:
126: //next tokenize by decimal
127: String x = null;
128:
129: //next tokenize by decimal
130: String y = null;
131:
132: //next tokenize by decimal
133: String z = null;
134:
135: //must be at least 1D
136: x = ".".equals(decimal) ? oords[0] : oords[0].replaceAll(
137: decimal, ".");
138:
139: //check for 2 and 3 D
140: if (oords.length > 1) {
141: y = ".".equals(decimal) ? oords[1] : oords[1]
142: .replaceAll(decimal, ".");
143: }
144:
145: if (oords.length > 2) {
146: z = ".".equals(decimal) ? oords[2] : oords[2]
147: .replaceAll(decimal, ".");
148: }
149:
150: if (seq == null) {
151: seq = csFactory.create(ncoords, oords.length);
152: }
153:
154: seq.setOrdinate(i, CoordinateSequence.X, Double
155: .parseDouble(x));
156:
157: if (y != null) {
158: seq.setOrdinate(i, CoordinateSequence.Y, Double
159: .parseDouble(y));
160: }
161:
162: if (z != null) {
163: seq.setOrdinate(i, CoordinateSequence.Z, Double
164: .parseDouble(z));
165: }
166:
167: i++;
168: }
169:
170: return seq;
171: }
172:
173: public Element encode(Object object, Document document,
174: Element value) throws Exception {
175: CoordinateSequence coordinates = (CoordinateSequence) object;
176: StringBuffer buf = new StringBuffer();
177:
178: for (int i = 0; i < coordinates.size(); i++) {
179: Coordinate c = coordinates.getCoordinate(i);
180: buf.append(c.x);
181:
182: boolean y = (coordinates.getDimension() > 1)
183: && !new Double(c.y).isNaN();
184:
185: if (y) {
186: buf.append("," + c.y);
187: }
188:
189: boolean z = y && (coordinates.getDimension() > 2)
190: && !new Double(c.z).isNaN();
191:
192: if (z) {
193: buf.append("," + c.z);
194: }
195:
196: if (i < (coordinates.size() - 1)) {
197: buf.append(" ");
198: }
199: }
200:
201: value.appendChild(document.createTextNode(buf.toString()));
202:
203: return value;
204: }
205: }
|