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 }