001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/crs/Identifiable.java $ 002 /*---------------------------------------------------------------------------- 003 This file is part of deegree, http://deegree.org/ 004 Copyright (C) 2001-2009 by: 005 Department of Geography, University of Bonn 006 and 007 lat/lon GmbH 008 009 This library is free software; you can redistribute it and/or modify it under 010 the terms of the GNU Lesser General Public License as published by the Free 011 Software Foundation; either version 2.1 of the License, or (at your option) 012 any later version. 013 This library is distributed in the hope that it will be useful, but WITHOUT 014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 016 details. 017 You should have received a copy of the GNU Lesser General Public License 018 along with this library; if not, write to the Free Software Foundation, Inc., 019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 021 Contact information: 022 023 lat/lon GmbH 024 Aennchenstr. 19, 53177 Bonn 025 Germany 026 http://lat-lon.de/ 027 028 Department of Geography, University of Bonn 029 Prof. Dr. Klaus Greve 030 Postfach 1147, 53001 Bonn 031 Germany 032 http://www.geographie.uni-bonn.de/deegree/ 033 034 e-mail: info@deegree.org 035 ----------------------------------------------------------------------------*/ 036 037 package org.deegree.crs; 038 039 import static org.deegree.framework.log.LoggerFactory.getLogger; 040 041 import java.io.Serializable; 042 043 import org.deegree.framework.log.ILogger; 044 import org.deegree.i18n.Messages; 045 046 /** 047 * The <code>Identifiable</code> class can be used to identify a crs, ellipsoid, Datum and primemeridian 048 * 049 * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a> 050 * 051 * @author last edited by: $Author: aschmitz $ 052 * 053 * @version $Revision: 21456 $, $Date: 2009-12-15 15:17:33 +0100 (Di, 15 Dez 2009) $ 054 * 055 */ 056 057 public class Identifiable implements Serializable { 058 059 private static final long serialVersionUID = 4687689233685635124L; 060 061 private static final ILogger LOG = getLogger( Identifiable.class ); 062 063 private String[] identifiers; 064 065 private String[] versions; 066 067 private String[] names; 068 069 private String[] descriptions; 070 071 private String[] areasOfUse; 072 073 private double[] areaOfUseBBox; 074 075 /** 076 * Takes the references of the other object and stores them in this Identifiable Object. 077 * 078 * @param other 079 * identifiable object. 080 */ 081 public Identifiable( Identifiable other ) { 082 this( other.getIdentifiers(), other.getNames(), other.getVersions(), other.getDescriptions(), 083 other.getAreasOfUse() ); 084 } 085 086 /** 087 * 088 * @param identifiers 089 * @param names 090 * the human readable names of the object. 091 * @param versions 092 * @param descriptions 093 * @param areasOfUse 094 * @throws IllegalArgumentException 095 * if no identifier(s) was/were given. 096 */ 097 public Identifiable( String[] identifiers, String[] names, String[] versions, String[] descriptions, 098 String[] areasOfUse ) { 099 if ( identifiers == null || identifiers.length == 0 ) { 100 throw new IllegalArgumentException( "An identifiable object must at least have one identifier." ); 101 } 102 this.identifiers = identifiers; 103 104 this.names = names; 105 this.versions = versions; 106 this.descriptions = descriptions; 107 this.areasOfUse = areasOfUse; 108 } 109 110 /** 111 * Creates arrays fromt the given identifier and name without setting the versions, descriptions and areasOfUse. 112 * 113 * @param identifiers 114 * of the object. 115 */ 116 public Identifiable( String[] identifiers ) { 117 this( identifiers, null, null, null, null ); 118 } 119 120 // /** 121 // * Creates arrays fromt the given identifier and name without setting the versions, 122 // descriptions and areasOfUse. 123 // * 124 // * @param identifier of the object. 125 // * @param name the human readable name of the object. 126 // */ 127 // protected Identifiable( String identifier, String name ) { 128 // this( new String[]{identifier}, new String[]{name}, null, null, null ); 129 // } 130 131 /** 132 * @param id 133 * of the Identifier 134 */ 135 public Identifiable( String id ) { 136 this( new String[] { id } ); 137 } 138 139 /** 140 * @return the first of all areasOfUse or <code>null</code> if no areasOfUse were given. 141 */ 142 public final String getAreaOfUse() { 143 return ( areasOfUse != null && areasOfUse.length > 0 ) ? areasOfUse[0] : null; 144 } 145 146 /** 147 * @return the first of all descriptions or <code>null</code> if no descriptions were given. 148 */ 149 public final String getDescription() { 150 return ( descriptions != null && descriptions.length > 0 ) ? descriptions[0] : null; 151 } 152 153 /** 154 * @return the first of all identifiers. 155 */ 156 public final String getIdentifier() { 157 return identifiers[0]; 158 } 159 160 /** 161 * @return the first of all names or <code>null</code> if no names were given. 162 */ 163 public final String getName() { 164 return ( names != null && names.length > 0 ) ? names[0] : null; 165 } 166 167 /** 168 * @return the first of all versions or <code>null</code> if no versions were given. 169 */ 170 public final String getVersion() { 171 return ( versions != null && versions.length > 0 ) ? versions[0] : null; 172 } 173 174 /** 175 * throws an InvalidParameterException if the given object is null 176 * 177 * @param toBeChecked 178 * for <code>null</code> 179 * @param message 180 * to put into the exception. If absent, the default message (CRS_INVALID_NULL_PARAMETER) will be 181 * inserted. 182 * @throws IllegalArgumentException 183 * if the given object is <code>null</code>. 184 */ 185 protected void checkForNullObject( Object toBeChecked, String message ) 186 throws IllegalArgumentException { 187 if ( toBeChecked == null ) { 188 if ( message == null || "".equals( message.trim() ) ) { 189 message = Messages.getMessage( "CRS_INVALID_NULL_PARAMETER" ); 190 } 191 throw new IllegalArgumentException( message ); 192 } 193 194 } 195 196 /** 197 * throws an InvalidParameterException if the given object is null 198 * 199 * @param toBeChecked 200 * for <code>null</code> 201 * @param functionName 202 * of the caller 203 * @param paramName 204 * of the parameter to be checked. 205 * @throws IllegalArgumentException 206 * if the given object is <code>null</code>. 207 */ 208 public static void checkForNullObject( Object toBeChecked, String functionName, String paramName ) 209 throws IllegalArgumentException { 210 if ( toBeChecked == null ) { 211 throw new IllegalArgumentException( Messages.getMessage( "CRS_PARAMETER_NOT_NULL", functionName, paramName ) ); 212 } 213 } 214 215 /** 216 * throws an IllegalArgumentException if the given object array is null or empty 217 * 218 * @param toBeChecked 219 * for <code>null</code> or empty 220 * @param message 221 * to put into the exception. If absent, the default message (CRS_INVALID_NULL_PARAMETER) will be 222 * inserted. 223 * @throws IllegalArgumentException 224 * if the given object array is <code>null</code> or empty. 225 */ 226 public static void checkForNullObject( Object[] toBeChecked, String message ) 227 throws IllegalArgumentException { 228 if ( toBeChecked != null && toBeChecked.length != 0 ) { 229 return; 230 } 231 if ( message == null || "".equals( message.trim() ) ) { 232 message = Messages.getMessage( "CRS_INVALID_NULL_ARRAY" ); 233 } 234 throw new IllegalArgumentException( message ); 235 } 236 237 @Override 238 public String toString() { 239 StringBuilder sb = new StringBuilder( "id: [" ); 240 for ( int i = 0; i < identifiers.length; ++i ) { 241 sb.append( identifiers[i] ); 242 if ( ( i + 1 ) < identifiers.length ) { 243 sb.append( ", " ); 244 } 245 } 246 if ( getName() != null ) { 247 sb.append( "], name: [" ); 248 for ( int i = 0; i < names.length; ++i ) { 249 sb.append( names[i] ); 250 if ( ( i + 1 ) < names.length ) { 251 sb.append( ", " ); 252 } 253 } 254 } 255 if ( getVersion() != null ) { 256 sb.append( "], version: [" ); 257 for ( int i = 0; i < versions.length; ++i ) { 258 sb.append( versions[i] ); 259 if ( ( i + 1 ) < versions.length ) { 260 sb.append( ", " ); 261 } 262 } 263 } 264 if ( getDescription() != null ) { 265 sb.append( "], description: [" ); 266 for ( int i = 0; i < descriptions.length; ++i ) { 267 sb.append( descriptions[i] ); 268 if ( ( i + 1 ) < descriptions.length ) { 269 sb.append( ", " ); 270 } 271 } 272 } 273 if ( getAreaOfUse() != null ) { 274 sb.append( "], areasOfUse: [" ); 275 for ( int i = 0; i < areasOfUse.length; ++i ) { 276 sb.append( areasOfUse[i] ); 277 if ( ( i + 1 ) < areasOfUse.length ) { 278 sb.append( ", " ); 279 } 280 } 281 } 282 return sb.toString(); 283 } 284 285 /** 286 * @return the first id and the name (if given) as id: id, name: name. 287 */ 288 public String getIdAndName() { 289 StringBuilder sb = new StringBuilder( "id: " ).append( getIdentifier() ); 290 if ( getName() != null ) { 291 sb.append( ", name: " ).append( getName() ); 292 } 293 return sb.toString(); 294 } 295 296 @Override 297 public boolean equals( Object other ) { 298 if ( other != null && other instanceof Identifiable ) { 299 final Identifiable that = (Identifiable) other; 300 boolean isThisEPSG = false; 301 boolean isThatEPSG = false; 302 for ( String id : getIdentifiers() ) { 303 if ( id.toLowerCase().contains( "epsg" ) ) { 304 isThisEPSG = true; 305 break; 306 } 307 } 308 for ( String id : that.getIdentifiers() ) { 309 if ( id.toLowerCase().contains( "epsg" ) ) { 310 isThatEPSG = true; 311 break; 312 } 313 } 314 if ( isThatEPSG && isThisEPSG ) { 315 return idsMatch( that.identifiers ); 316 } 317 return true;// idsMatch( that.identifiers ); 318 } 319 return false; 320 } 321 322 /** 323 * Checks for the equality of id's between to different identifiable objects. 324 * 325 * @param otherIDs 326 * of the other identifiable object. 327 * @return true if the given strings match this.identifiers false otherwise. 328 */ 329 private boolean idsMatch( String[] otherIDs ) { 330 if ( otherIDs == null || identifiers.length != otherIDs.length ) { 331 return false; 332 } 333 for ( int i = 0; i < identifiers.length; ++i ) { 334 String tmp = identifiers[i]; 335 String other = otherIDs[i]; 336 if ( tmp != null ) { 337 if ( !tmp.equals( other ) ) { 338 return false; 339 } 340 } else if ( other != null ) { 341 return false; 342 } 343 } 344 return true; 345 346 } 347 348 /** 349 * @return the areasOfUse or <code>null</code> if no areasOfUse were given. 350 */ 351 public final String[] getAreasOfUse() { 352 return areasOfUse; 353 } 354 355 /** 356 * @return the descriptions or <code>null</code> if no descriptions were given. 357 */ 358 public final String[] getDescriptions() { 359 return descriptions; 360 } 361 362 /** 363 * @return the identifiers, each identifiable object has atleast one id. 364 */ 365 public final String[] getIdentifiers() { 366 return identifiers; 367 } 368 369 /** 370 * @return the names or <code>null</code> if no names were given. 371 */ 372 public final String[] getNames() { 373 return names; 374 } 375 376 /** 377 * @return the versions or <code>null</code> if no versions were given. 378 */ 379 public final String[] getVersions() { 380 return versions; 381 } 382 383 /** 384 * @param id 385 * a string which could match this identifiable. 386 * @return true if this identifiable can be identified with the given string, false otherwise. 387 */ 388 public boolean hasID( String id ) { 389 if ( id == null || "".equals( id.trim() ) ) { 390 return false; 391 } 392 for ( String s : getIdentifiers() ) { 393 if ( id.equalsIgnoreCase( s ) ) { 394 return true; 395 } 396 } 397 return false; 398 } 399 400 /** 401 * Returns the area of use, i.e. the domain where this {@link Identifiable} is valid. 402 * 403 * @return the domain of validity (EPSG:4326 coordinates), order: minX, minY, maxX, maxY, never <code>null</code> 404 * (-180,-90,180,90) if no such information is available 405 */ 406 public double[] getAreaOfUseBBox() { 407 408 if ( areaOfUseBBox == null ) { 409 areaOfUseBBox = new double[4]; 410 areaOfUseBBox[0] = Double.NaN; 411 areaOfUseBBox[1] = Double.NaN; 412 areaOfUseBBox[2] = Double.NaN; 413 areaOfUseBBox[3] = Double.NaN; 414 if ( areasOfUse != null ) { 415 for ( String bboxString : areasOfUse ) { 416 try { 417 double[] ords = parseAreaBBox( bboxString ); 418 for ( int i = 0; i < 4; i++ ) { 419 if ( Double.isNaN( areaOfUseBBox[i] ) || areaOfUseBBox[i] > ords[i] ) { 420 areaOfUseBBox[i] = ords[i]; 421 } 422 } 423 } catch ( Exception e ) { 424 LOG.logDebug( "Error parsing areaOfUse bbox (ignoring it): '" + e.getMessage() + "'" ); 425 } 426 } 427 } 428 if ( Double.isNaN( areaOfUseBBox[0] ) ) { 429 LOG.logDebug( "No areaOfUse BBox available, assuming world." ); 430 areaOfUseBBox[0] = -180; 431 areaOfUseBBox[1] = -90; 432 areaOfUseBBox[2] = 180; 433 areaOfUseBBox[3] = 90; 434 } 435 } 436 return areaOfUseBBox; 437 } 438 439 private double[] parseAreaBBox( String s ) 440 throws IllegalArgumentException, NumberFormatException { 441 String[] tokens = s.split( "," ); 442 if ( tokens.length != 4 ) { 443 throw new IllegalArgumentException( "Invalid areaOfUse: expected CSV-list of length 4." ); 444 } 445 double[] ords = new double[4]; 446 for ( int i = 0; i < 4; i++ ) { 447 ords[i] = Double.parseDouble( tokens[i] ); 448 } 449 return ords; 450 } 451 }