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