001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/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 13:32:57 +0100 (Do, 27 Dez 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 ) throws IdGenerationException { 095 this.ft = ft; 096 this.fidDefinition = ft.getGMLId(); 097 this.values = new Object[1]; 098 this.values[0] = removeFIDPrefix( fid, fidDefinition ); 099 } 100 101 /** 102 * Creates a new instance of <code>FeatureId</code> from the given parameters. 103 * 104 * @param fidDefinition 105 * cannot be null 106 * @param values 107 * @deprecated use {@link #FeatureId(MappedFeatureType, Object[])} instead 108 */ 109 @Deprecated 110 public FeatureId( MappedGMLId fidDefinition, Object[] values ) { 111 this.fidDefinition = fidDefinition; 112 this.values = values; 113 } 114 115 /** 116 * Creates a new instance of <code>FeatureId</code> from the given parameters. 117 * 118 * @param fidDefinition 119 * cannot be null 120 * @param fid 121 * cannot be null 122 * @throws IdGenerationException 123 * @deprecated use {@link #FeatureId(MappedFeatureType, String)} instead 124 */ 125 @Deprecated 126 public FeatureId( MappedGMLId fidDefinition, String fid ) throws IdGenerationException { 127 this.fidDefinition = fidDefinition; 128 this.values = new Object[1]; 129 this.values[0] = removeFIDPrefix( fid, fidDefinition ); 130 } 131 132 /** 133 * Return the {@link MappedFeatureType} of the identified feature. 134 * <p> 135 * The feature type is concrete, never abstract. 136 * 137 * @return type of the identified feature, never abstract 138 */ 139 public MappedFeatureType getFeatureType () { 140 return this.ft; 141 } 142 143 /** 144 * Return the underlying {@link MappedGMLId}. 145 * 146 * @return MappedGMLId 147 */ 148 public MappedGMLId getFidDefinition() { 149 return this.fidDefinition; 150 } 151 152 /** 153 * Returns the number of components that the key consists of. 154 * 155 * @return the number of components that the key consists of 156 */ 157 public int getLength() { 158 return this.values.length; 159 } 160 161 /** 162 * Returns all column values of the key. 163 * 164 * @return all column values of the key 165 */ 166 public Object[] getValues() { 167 return this.values; 168 } 169 170 /** 171 * Returns a certain column value of the key. 172 * 173 * @param i 174 * requested column 175 * @return the requested column value of the key 176 */ 177 public Object getValue( int i ) { 178 return this.values[i]; 179 } 180 181 /** 182 * Returns the canonical textual representation, i.e. the key components, separated by the 183 * separator defined in the associated {@link MappedGMLId}. 184 * 185 * @return the canonical textual representation 186 */ 187 public String getAsString() { 188 StringBuffer sb = new StringBuffer( fidDefinition.getPrefix() ); 189 for ( int i = 0; i < this.values.length; i++ ) { 190 sb.append( values[i] ); 191 if ( i != this.values.length - 1 ) { 192 sb.append( fidDefinition.getSeparator() ); 193 } 194 } 195 return sb.toString(); 196 } 197 198 public int compareTo( Object obj ) { 199 FeatureId that = (FeatureId) obj; 200 return this.getAsString().compareTo( that.getAsString() ); 201 } 202 203 @Override 204 public int hashCode() { 205 int hashCode = fidDefinition.hashCode(); 206 for ( int i = 0; i < this.values.length; i++ ) { 207 hashCode += this.values[i].toString().hashCode(); 208 } 209 return hashCode; 210 } 211 212 @Override 213 public boolean equals( Object obj ) { 214 if ( obj == null || !( obj instanceof FeatureId ) ) { 215 return false; 216 } 217 FeatureId that = (FeatureId) obj; 218 if ( this.fidDefinition != that.fidDefinition ) { 219 return false; 220 } 221 if ( this.values == null && that.values == null ) { 222 return true; 223 } 224 if ( ( this.values != null && that.values == null ) 225 || ( this.values == null && that.values != null ) 226 || ( this.values.length != that.values.length ) ) { 227 return false; 228 } 229 for ( int i = 0; i < this.values.length; i++ ) { 230 if ( ( this.values[i] != null && that.values[i] == null ) 231 || ( this.values[i] == null && that.values[i] != null ) ) { 232 return false; 233 } 234 if ( this.values[i] != null && that.values[i] != null ) { 235 if ( !this.values[i].equals( that.values[i] ) ) { 236 return false; 237 } 238 } 239 } 240 return true; 241 } 242 243 /** 244 * Returns a string representation of the object. 245 * 246 * @return a string representation of the object 247 */ 248 @Override 249 public String toString() { 250 StringBuffer sb = new StringBuffer(); 251 sb.append( "fid=" ); 252 sb.append( getAsString() ); 253 sb.append( ", " ); 254 MappingField[] fidFields = fidDefinition.getIdFields(); 255 for ( int i = 0; i < fidFields.length; i++ ) { 256 sb.append( fidFields[i].getField() ); 257 sb.append( "=" ); 258 sb.append( values[i] ); 259 if ( i != fidFields.length - 1 ) { 260 sb.append( ", " ); 261 } 262 } 263 return sb.toString(); 264 } 265 266 /** 267 * Removes the prefix from the given feature id. 268 * <p> 269 * The prefix is taken from the given gml:id mapping. 270 * 271 * @param id 272 * feature id (including prefix). 273 * @param idMapping 274 * target gml:id mapping (where the fid will be stored) 275 * @return feature id (without prefix) as an object of the right type (matching the table 276 * column) 277 * @throws IdGenerationException 278 * if the given fid does not begin with the expected prefix from the gml:id mapping 279 */ 280 public static Object removeFIDPrefix( String id, MappedGMLId idMapping ) 281 throws IdGenerationException { 282 Object fidObject = null; 283 String plainIdValue = id; 284 String prefix = idMapping.getPrefix(); 285 if ( prefix != null && prefix.length() > 0 ) { 286 if ( !id.startsWith( prefix ) ) { 287 String msg = Messages.getMessage( "DATASTORE_FEATURE_ID_NO_PREFIX", id, prefix ); 288 throw new IdGenerationException( msg ); 289 } 290 plainIdValue = id.substring( prefix.length() ); 291 } 292 293 if ( idMapping.getIdFields().length > 1 ) { 294 String msg = "Compound feature ids not supported in FeatureId.removeFIDPrefix()."; 295 throw new IdGenerationException( msg ); 296 } 297 298 int sqlTypeCode = idMapping.getIdFields()[0].getType(); 299 switch ( sqlTypeCode ) { 300 case Types.NUMERIC: 301 case Types.DOUBLE: { 302 try { 303 fidObject = Double.parseDouble( plainIdValue ); 304 } catch ( NumberFormatException e ) { 305 String msg = Messages.getMessage( "DATASTORE_FEATURE_ID_CONVERT", plainIdValue, 306 "Double" ); 307 throw new IdGenerationException( msg ); 308 } 309 break; 310 } 311 case Types.FLOAT: { 312 try { 313 fidObject = Float.parseFloat( plainIdValue ); 314 } catch ( NumberFormatException e ) { 315 String msg = Messages.getMessage( "DATASTORE_FEATURE_ID_CONVERT", plainIdValue, 316 "Float" ); 317 throw new IdGenerationException( msg ); 318 } 319 break; 320 } 321 case Types.INTEGER: { 322 try { 323 fidObject = Integer.parseInt( plainIdValue ); 324 } catch ( NumberFormatException e ) { 325 String msg = Messages.getMessage( "DATASTORE_FEATURE_ID_CONVERT", plainIdValue, 326 "Integer" ); 327 throw new IdGenerationException( msg ); 328 } 329 break; 330 } 331 case Types.VARCHAR: 332 case Types.CHAR:{ 333 fidObject = plainIdValue; 334 break; 335 } 336 default: { 337 String msg = null; 338 try { 339 msg = Messages.getMessage( "DATASTORE_FEATURE_ID_CONVERT", plainIdValue, 340 Types.getTypeNameForSQLTypeCode( sqlTypeCode ) ); 341 } catch ( UnknownTypeException e ) { 342 throw new IdGenerationException( e.getMessage() ); 343 } 344 throw new IdGenerationException( msg ); 345 } 346 } 347 return fidObject; 348 } 349 }