001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/model/csct/units/PrefixSet.java $ 002 /* 003 * Map and oceanographical data visualisation 004 * Copyright (C) 1998 University Corporation for Atmospheric Research (Unidata) 005 * 1998 Bill Hibbard & al. (VisAD) 006 * 1999 P�ches et Oc�ans Canada 007 * 2000 Institut de Recherche pour le D�veloppement 008 * 009 * 010 * This library is free software; you can redistribute it and/or 011 * modify it under the terms of the GNU Library General Public 012 * License as published by the Free Software Foundation; either 013 * version 2 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 * Library General Public License for more details (http://www.gnu.org/). 019 * 020 * 021 * Contacts: 022 * FRANCE: Surveillance de l'Environnement Assist�e par Satellite 023 * Institut de Recherche pour le D�veloppement / US-Espace 024 * mailto:seasnet@teledetection.fr 025 * 026 * CANADA: Observatoire du Saint-Laurent 027 * Institut Maurice-Lamontagne 028 * mailto:osl@osl.gc.ca 029 * 030 * 031 * This package is inspired from the units package of VisAD. 032 * Unidata and Visad's work is fully acknowledged here. 033 * 034 * THIS IS A TEMPORARY CLASS 035 * 036 * This is a placeholder for future <code>Unit</code> class. 037 * This skeleton will be removed when the real classes from 038 * JSR-108: Units specification will be publicly available. 039 */ 040 package org.deegree.model.csct.units; 041 042 // Entr�s/sorties 043 import java.io.Serializable; 044 import java.util.Arrays; 045 046 import org.deegree.model.csct.resources.WeakHashSet; 047 048 /** 049 * Ensemble de pr�fix. Cette classe maintient une liste d'objets 050 * {@link Prefix} en ordre croissant et sans doublons, c'est-�-dire qu'elle garanti 051 * qu'il n'y aura pas deux pr�fix repr�sentant la m�me quantit� {@link Prefix#amount}. 052 * 053 * @version 1.0 054 * @author Martin Desruisseaux 055 */ 056 /*public*/final class PrefixSet implements Serializable { 057 /** 058 * Banque des objets qui ont �t� pr�c�demment cr��s et 059 * enregistr�s par un appel � la m�thode {@link #intern}. 060 */ 061 private static final WeakHashSet pool = Prefix.pool; 062 063 /** 064 * Ensemble de pr�fix. Les pr�fix de cet ensemble doivent 065 * obligatoirement �tre un ordre croissant et sans doublons. 066 */ 067 private final Prefix[] prefix; 068 069 /** 070 * Construit un ensemble de pr�fix. Le tableau <code>p</code> 071 * sera copi�, puis class�. Les �ventuels doublons seront �limin�s. 072 * Le tableau <code>p</code> original ne sera pas affect� par ces 073 * traitements. 074 */ 075 private PrefixSet( final Prefix[] p ) { 076 final Prefix[] px = new Prefix[p.length]; 077 System.arraycopy( p, 0, px, 0, px.length ); 078 Arrays.sort( px ); 079 int length = px.length; 080 for ( int i = length; --i >= 1; ) { 081 if ( px[i].amount == px[i - 1].amount ) { 082 px[i] = null; 083 length--; 084 } 085 } 086 int i = 0; 087 prefix = new Prefix[length]; 088 for ( int j = 0; j < px.length; j++ ) 089 if ( px[j] != null ) 090 prefix[i++] = px[j]; 091 //----- BEGIN JDK 1.4 DEPENDENCIES ---- 092 // assert i==length; 093 //----- END OF JDK 1.4 DEPENDENCIES ---- 094 } 095 096 /** 097 * Construit un ensemble de pr�fix. Le tableau <code>p</code> 098 * sera copi�, puis class�. Les �ventuels doublons seront �limin�s. 099 * Le tableau <code>p</code> original ne sera pas affect� par ces 100 * traitements. 101 */ 102 public static PrefixSet getPrefixSet( final Prefix[] p ) { 103 return new PrefixSet( p ).intern(); 104 } 105 106 /** 107 * Retourne le pr�fix repr�sent� par le symbole sp�fifi�. 108 * Si aucun pr�fix ne correspond � ce symbole, retourne 109 * <code>null</code>. 110 * 111 * @param symbol Symbole du pr�fix recherch�. 112 * @return Pr�fix d�sign� par le symbole <code>symbol</code>. 113 */ 114 public Prefix getPrefix( final String symbol ) { 115 for ( int i = 0; i < prefix.length; i++ ) { 116 final Prefix p = prefix[i]; 117 if ( symbol.equals( p.symbol ) ) 118 return p; 119 } 120 return null; 121 } 122 123 /** 124 * Retourne le pr�fix repr�sentant une quantit� �gale ou inf�rieure � la quantit� sp�cifi�e. 125 * Si <code>amount</code> est inf�rieur � la plus petite quantit� pouvant �tre repr�sent� 126 * par un pr�fix, alors cette m�thode retourne <code>null</code>. 127 */ 128 public Prefix getPrefix( double amount ) { 129 amount += 1E-8 * Math.abs( amount ); // Pour �viter d'�ventuelles erreurs d'arrondissements. 130 int index = Arrays.binarySearch( prefix, new Prefix( amount ) ); 131 if ( index < 0 ) { 132 index = ~index; 133 if ( index == 0 ) 134 return null; 135 if ( index > prefix.length ) 136 index = prefix.length; 137 index--; 138 } 139 return prefix[index]; 140 } 141 142 /** 143 * Retourne une cha�ne de caract�res qui �num�re tous les pr�fix contenu dans 144 * cet ensemble. La cha�ne sera de la forme "milli(m),centi(c),d�ci(d),kilo(k)" 145 * par exemple. 146 */ 147 public String toString() { 148 final StringBuffer buffer = new StringBuffer(); 149 for ( int i = 0; i < prefix.length; i++ ) { 150 final Prefix p = prefix[i]; 151 final String name = p.getLocalizedName(); 152 final String symb = p.symbol; 153 if ( name.length() != 0 || symb.length() != 0 ) { 154 if ( buffer.length() != 0 ) { 155 buffer.append( ',' ); 156 } 157 buffer.append( name ); 158 if ( symb.length() != 0 ) { 159 buffer.append( '(' ); 160 buffer.append( symb ); 161 buffer.append( ')' ); 162 } 163 } 164 } 165 return buffer.toString(); 166 } 167 168 /** 169 * V�rifie si cet ensemble est identique � l'objet <code>other</code> 170 * sp�cifi�. Deux ensembles sont consid�r�s identiques s'ils contienent 171 * les m�mes pr�fix. 172 */ 173 public boolean equals( final Object other ) { 174 if ( other == this ) 175 return true; // slight optimisation 176 if ( other instanceof PrefixSet ) { 177 final Prefix[] array = ( (PrefixSet) other ).prefix; 178 if ( prefix.length == array.length ) { 179 for ( int i = 0; i < array.length; i++ ) 180 if ( !prefix[i].equals( array[i] ) ) 181 return false; 182 return true; 183 } 184 } 185 return false; 186 } 187 188 /** 189 * Retourne un code repr�sentant cet ensemble de pr�fix. 190 */ 191 public int hashCode() { 192 int code = prefix.length << 1; 193 for ( int i = 0; i < prefix.length; i += 5 ) 194 code += prefix[i].hashCode(); 195 return code; 196 } 197 198 /** 199 * Retourne un exemplaire unique de cet ensemble de pr�fix. Une banque de pr�fix, initialement 200 * vide, est maintenue de fa�on interne par la classe <code>PrefixSet</code>. Lorsque la m�thode 201 * <code>intern</code> est appel�e, elle recherchera des pr�fix �gaux � <code>this</code> au 202 * sens de la m�thode {@link #equals}. Si de tels pr�fix sont trouv�s, ils seront retourn�s. 203 * Sinon, les pr�fix <code>this</code> seront ajout�s � la banque de donn�es en utilisant une 204 * {@link java.lang.ref.WeakReference r�f�rence faible} et cette m�thode retournera <code>this</code>. 205 * <br><br> 206 * De cette m�thode il s'ensuit que pour deux ensembles de pr�fix <var>u</var> et <var>v</var>, 207 * la condition <code>u.intern()==v.intern()</code> sera vrai si et seulement si 208 * <code>u.equals(v)</code> est vrai. 209 */ 210 private final PrefixSet intern() { 211 return (PrefixSet) pool.intern( this ); 212 } 213 214 /** 215 * Apr�s la lecture d'une unit�, v�rifie si ce pr�fix 216 * appara�t d�j� dans la banque des pr�fix . 217 * Si oui, l'exemplaire de la banque sera retourn� plut�t 218 * que de garder inutilement le pr�fix courant comme copie. 219 */ 220 private Object readResolve() { 221 return intern(); 222 } 223 }