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 }