001: //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/io/datastore/FeatureId.java $
002: /*---------------- FILE HEADER ------------------------------------------
003:
004: This file is part of deegree.
005: Copyright (C) 2001-2008 by:
006: EXSE, Department of Geography, University of Bonn
007: http://www.giub.uni-bonn.de/deegree/
008: lat/lon GmbH
009: http://www.lat-lon.de
010:
011: This library is free software; you can redistribute it and/or
012: modify it under the terms of the GNU Lesser General Public
013: License as published by the Free Software Foundation; either
014: version 2.1 of the License, or (at your option) any later version.
015:
016: This library is distributed in the hope that it will be useful,
017: but WITHOUT ANY WARRANTY; without even the implied warranty of
018: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: Lesser General Public License for more details.
020:
021: You should have received a copy of the GNU Lesser General Public
022: License along with this library; if not, write to the Free Software
023: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024:
025: Contact:
026:
027: Andreas Poth
028: lat/lon GmbH
029: Aennchenstr. 19
030: 53115 Bonn
031: Germany
032: E-Mail: poth@lat-lon.de
033:
034: Prof. Dr. Klaus Greve
035: Department of Geography
036: University of Bonn
037: Meckenheimer Allee 166
038: 53115 Bonn
039: Germany
040: E-Mail: greve@giub.uni-bonn.de
041:
042:
043: ---------------------------------------------------------------------------*/
044:
045: package org.deegree.io.datastore;
046:
047: import org.deegree.datatypes.Types;
048: import org.deegree.datatypes.UnknownTypeException;
049: import org.deegree.i18n.Messages;
050: import org.deegree.io.datastore.idgenerator.IdGenerationException;
051: import org.deegree.io.datastore.schema.MappedFeatureType;
052: import org.deegree.io.datastore.schema.MappedGMLId;
053: import org.deegree.io.datastore.schema.content.MappingField;
054:
055: /**
056: * Used to identify persistent (stored) feature instances.
057: *
058: * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider </a>
059: * @author last edited by: $Author: apoth $
060: *
061: * @version $Revision: 9342 $, $Date: 2007-12-27 04:32:57 -0800 (Thu, 27 Dec 2007) $
062: */
063: public class FeatureId implements Comparable {
064:
065: private MappedFeatureType ft;
066:
067: private MappedGMLId fidDefinition;
068:
069: private Object[] values;
070:
071: /**
072: * Creates a new instance of <code>FeatureId</code> from the given parameters.
073: *
074: * @param ft
075: * cannot be null, must not be an abstract feature type
076: * @param values
077: * cannot be null or empty
078: */
079: public FeatureId(MappedFeatureType ft, Object[] values) {
080: this .ft = ft;
081: this .fidDefinition = ft.getGMLId();
082: this .values = values;
083: }
084:
085: /**
086: * Creates a new instance of <code>FeatureId</code> from the given parameters.
087: *
088: * @param ft
089: * cannot be null, must not be an abstract feature type
090: * @param fid
091: * cannot be null
092: * @throws IdGenerationException
093: */
094: public FeatureId(MappedFeatureType ft, String fid)
095: throws IdGenerationException {
096: this .ft = ft;
097: this .fidDefinition = ft.getGMLId();
098: this .values = new Object[1];
099: this .values[0] = removeFIDPrefix(fid, fidDefinition);
100: }
101:
102: /**
103: * Creates a new instance of <code>FeatureId</code> from the given parameters.
104: *
105: * @param fidDefinition
106: * cannot be null
107: * @param values
108: * @deprecated use {@link #FeatureId(MappedFeatureType, Object[])} instead
109: */
110: @Deprecated
111: public FeatureId(MappedGMLId fidDefinition, Object[] values) {
112: this .fidDefinition = fidDefinition;
113: this .values = values;
114: }
115:
116: /**
117: * Creates a new instance of <code>FeatureId</code> from the given parameters.
118: *
119: * @param fidDefinition
120: * cannot be null
121: * @param fid
122: * cannot be null
123: * @throws IdGenerationException
124: * @deprecated use {@link #FeatureId(MappedFeatureType, String)} instead
125: */
126: @Deprecated
127: public FeatureId(MappedGMLId fidDefinition, String fid)
128: throws IdGenerationException {
129: this .fidDefinition = fidDefinition;
130: this .values = new Object[1];
131: this .values[0] = removeFIDPrefix(fid, fidDefinition);
132: }
133:
134: /**
135: * Return the {@link MappedFeatureType} of the identified feature.
136: * <p>
137: * The feature type is concrete, never abstract.
138: *
139: * @return type of the identified feature, never abstract
140: */
141: public MappedFeatureType getFeatureType() {
142: return this .ft;
143: }
144:
145: /**
146: * Return the underlying {@link MappedGMLId}.
147: *
148: * @return MappedGMLId
149: */
150: public MappedGMLId getFidDefinition() {
151: return this .fidDefinition;
152: }
153:
154: /**
155: * Returns the number of components that the key consists of.
156: *
157: * @return the number of components that the key consists of
158: */
159: public int getLength() {
160: return this .values.length;
161: }
162:
163: /**
164: * Returns all column values of the key.
165: *
166: * @return all column values of the key
167: */
168: public Object[] getValues() {
169: return this .values;
170: }
171:
172: /**
173: * Returns a certain column value of the key.
174: *
175: * @param i
176: * requested column
177: * @return the requested column value of the key
178: */
179: public Object getValue(int i) {
180: return this .values[i];
181: }
182:
183: /**
184: * Returns the canonical textual representation, i.e. the key components, separated by the
185: * separator defined in the associated {@link MappedGMLId}.
186: *
187: * @return the canonical textual representation
188: */
189: public String getAsString() {
190: StringBuffer sb = new StringBuffer(fidDefinition.getPrefix());
191: for (int i = 0; i < this .values.length; i++) {
192: sb.append(values[i]);
193: if (i != this .values.length - 1) {
194: sb.append(fidDefinition.getSeparator());
195: }
196: }
197: return sb.toString();
198: }
199:
200: public int compareTo(Object obj) {
201: FeatureId that = (FeatureId) obj;
202: return this .getAsString().compareTo(that.getAsString());
203: }
204:
205: @Override
206: public int hashCode() {
207: int hashCode = fidDefinition.hashCode();
208: for (int i = 0; i < this .values.length; i++) {
209: hashCode += this .values[i].toString().hashCode();
210: }
211: return hashCode;
212: }
213:
214: @Override
215: public boolean equals(Object obj) {
216: if (obj == null || !(obj instanceof FeatureId)) {
217: return false;
218: }
219: FeatureId that = (FeatureId) obj;
220: if (this .fidDefinition != that.fidDefinition) {
221: return false;
222: }
223: if (this .values == null && that.values == null) {
224: return true;
225: }
226: if ((this .values != null && that.values == null)
227: || (this .values == null && that.values != null)
228: || (this .values.length != that.values.length)) {
229: return false;
230: }
231: for (int i = 0; i < this .values.length; i++) {
232: if ((this .values[i] != null && that.values[i] == null)
233: || (this .values[i] == null && that.values[i] != null)) {
234: return false;
235: }
236: if (this .values[i] != null && that.values[i] != null) {
237: if (!this .values[i].equals(that.values[i])) {
238: return false;
239: }
240: }
241: }
242: return true;
243: }
244:
245: /**
246: * Returns a string representation of the object.
247: *
248: * @return a string representation of the object
249: */
250: @Override
251: public String toString() {
252: StringBuffer sb = new StringBuffer();
253: sb.append("fid=");
254: sb.append(getAsString());
255: sb.append(", ");
256: MappingField[] fidFields = fidDefinition.getIdFields();
257: for (int i = 0; i < fidFields.length; i++) {
258: sb.append(fidFields[i].getField());
259: sb.append("=");
260: sb.append(values[i]);
261: if (i != fidFields.length - 1) {
262: sb.append(", ");
263: }
264: }
265: return sb.toString();
266: }
267:
268: /**
269: * Removes the prefix from the given feature id.
270: * <p>
271: * The prefix is taken from the given gml:id mapping.
272: *
273: * @param id
274: * feature id (including prefix).
275: * @param idMapping
276: * target gml:id mapping (where the fid will be stored)
277: * @return feature id (without prefix) as an object of the right type (matching the table
278: * column)
279: * @throws IdGenerationException
280: * if the given fid does not begin with the expected prefix from the gml:id mapping
281: */
282: public static Object removeFIDPrefix(String id,
283: MappedGMLId idMapping) throws IdGenerationException {
284: Object fidObject = null;
285: String plainIdValue = id;
286: String prefix = idMapping.getPrefix();
287: if (prefix != null && prefix.length() > 0) {
288: if (!id.startsWith(prefix)) {
289: String msg = Messages.getMessage(
290: "DATASTORE_FEATURE_ID_NO_PREFIX", id, prefix);
291: throw new IdGenerationException(msg);
292: }
293: plainIdValue = id.substring(prefix.length());
294: }
295:
296: if (idMapping.getIdFields().length > 1) {
297: String msg = "Compound feature ids not supported in FeatureId.removeFIDPrefix().";
298: throw new IdGenerationException(msg);
299: }
300:
301: int sqlTypeCode = idMapping.getIdFields()[0].getType();
302: switch (sqlTypeCode) {
303: case Types.NUMERIC:
304: case Types.DOUBLE: {
305: try {
306: fidObject = Double.parseDouble(plainIdValue);
307: } catch (NumberFormatException e) {
308: String msg = Messages.getMessage(
309: "DATASTORE_FEATURE_ID_CONVERT", plainIdValue,
310: "Double");
311: throw new IdGenerationException(msg);
312: }
313: break;
314: }
315: case Types.FLOAT: {
316: try {
317: fidObject = Float.parseFloat(plainIdValue);
318: } catch (NumberFormatException e) {
319: String msg = Messages.getMessage(
320: "DATASTORE_FEATURE_ID_CONVERT", plainIdValue,
321: "Float");
322: throw new IdGenerationException(msg);
323: }
324: break;
325: }
326: case Types.INTEGER: {
327: try {
328: fidObject = Integer.parseInt(plainIdValue);
329: } catch (NumberFormatException e) {
330: String msg = Messages.getMessage(
331: "DATASTORE_FEATURE_ID_CONVERT", plainIdValue,
332: "Integer");
333: throw new IdGenerationException(msg);
334: }
335: break;
336: }
337: case Types.VARCHAR:
338: case Types.CHAR: {
339: fidObject = plainIdValue;
340: break;
341: }
342: default: {
343: String msg = null;
344: try {
345: msg = Messages.getMessage(
346: "DATASTORE_FEATURE_ID_CONVERT", plainIdValue,
347: Types.getTypeNameForSQLTypeCode(sqlTypeCode));
348: } catch (UnknownTypeException e) {
349: throw new IdGenerationException(e.getMessage());
350: }
351: throw new IdGenerationException(msg);
352: }
353: }
354: return fidObject;
355: }
356: }
|