/*
* Map and oceanographical data visualisation
* Copyright (C) 1998 University Corporation for Atmospheric Research (Unidata)
* 1998 Bill Hibbard & al. (VisAD)
* 1999 P�ches et Oc�ans Canada
* 2000 Institut de Recherche pour le D�veloppement
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details (http://www.gnu.org/).
*
*
* Contacts:
* FRANCE: Surveillance de l'Environnement Assist�e par Satellite
* Institut de Recherche pour le D�veloppement / US-Espace
* mailto:seasnet@teledetection.fr
*
* CANADA: Observatoire du Saint-Laurent
* Institut Maurice-Lamontagne
* mailto:osl@osl.gc.ca
*
*
* This package is inspired from the units package of VisAD.
* Unidata and Visad's work is fully acknowledged here.
*
* THIS IS A TEMPORARY CLASS
*
* This is a placeholder for future <code>Unit</code> class.
* This skeleton will be removed when the real classes from
* JSR-108: Units specification will be publicly available.
*/
package org.deegree.model.csct.units;
// Entr�s/sorties
import java.io.Serializable;
import java.util.Arrays;
import org.deegree.model.csct.resources.WeakHashSet;
/**
* Ensemble de pr�fix. Cette classe maintient une liste d'objets
* {@link Prefix} en ordre croissant et sans doublons, c'est-�-dire qu'elle garanti
* qu'il n'y aura pas deux pr�fix repr�sentant la m�me quantit� {@link Prefix#amount}.
*
* @version 1.0
* @author Martin Desruisseaux
*/
/*public*/final class PrefixSet implements Serializable {
/**
* Banque des objets qui ont �t� pr�c�demment cr��s et
* enregistr�s par un appel � la m�thode {@link #intern}.
*/
private static final WeakHashSet pool = Prefix.pool;
/**
* Ensemble de pr�fix. Les pr�fix de cet ensemble doivent
* obligatoirement �tre un ordre croissant et sans doublons.
*/
private final Prefix[] prefix;
/**
* Construit un ensemble de pr�fix. Le tableau <code>p</code>
* sera copi�, puis class�. Les �ventuels doublons seront �limin�s.
* Le tableau <code>p</code> original ne sera pas affect� par ces
* traitements.
*/
private PrefixSet( final Prefix[] p ) {
final Prefix[] px = new Prefix[p.length];
System.arraycopy( p, 0, px, 0, px.length );
Arrays.sort( px );
int length = px.length;
for ( int i = length; --i >= 1; ) {
if ( px[i].amount == px[i - 1].amount ) {
px[i] = null;
length--;
}
}
int i = 0;
prefix = new Prefix[length];
for ( int j = 0; j < px.length; j++ )
if ( px[j] != null )
prefix[i++] = px[j];
//----- BEGIN JDK 1.4 DEPENDENCIES ----
// assert i==length;
//----- END OF JDK 1.4 DEPENDENCIES ----
}
/**
* Construit un ensemble de pr�fix. Le tableau <code>p</code>
* sera copi�, puis class�. Les �ventuels doublons seront �limin�s.
* Le tableau <code>p</code> original ne sera pas affect� par ces
* traitements.
*/
public static PrefixSet getPrefixSet( final Prefix[] p ) {
return new PrefixSet( p ).intern();
}
/**
* Retourne le pr�fix repr�sent� par le symbole sp�fifi�.
* Si aucun pr�fix ne correspond � ce symbole, retourne
* <code>null</code>.
*
* @param symbol Symbole du pr�fix recherch�.
* @return Pr�fix d�sign� par le symbole <code>symbol</code>.
*/
public Prefix getPrefix( final String symbol ) {
for ( int i = 0; i < prefix.length; i++ ) {
final Prefix p = prefix[i];
if ( symbol.equals( p.symbol ) )
return p;
}
return null;
}
/**
* Retourne le pr�fix repr�sentant une quantit� �gale ou inf�rieure � la quantit� sp�cifi�e.
* Si <code>amount</code> est inf�rieur � la plus petite quantit� pouvant �tre repr�sent�
* par un pr�fix, alors cette m�thode retourne <code>null</code>.
*/
public Prefix getPrefix( double amount ) {
amount += 1E-8 * Math.abs( amount ); // Pour �viter d'�ventuelles erreurs d'arrondissements.
int index = Arrays.binarySearch( prefix, new Prefix( amount ) );
if ( index < 0 ) {
index = ~index;
if ( index == 0 )
return null;
if ( index > prefix.length )
index = prefix.length;
index--;
}
return prefix[index];
}
/**
* Retourne une cha�ne de caract�res qui �num�re tous les pr�fix contenu dans
* cet ensemble. La cha�ne sera de la forme "milli(m),centi(c),d�ci(d),kilo(k)"
* par exemple.
*/
public String toString() {
final StringBuffer buffer = new StringBuffer();
for ( int i = 0; i < prefix.length; i++ ) {
final Prefix p = prefix[i];
final String name = p.getLocalizedName();
final String symb = p.symbol;
if ( name.length() != 0 || symb.length() != 0 ) {
if ( buffer.length() != 0 ) {
buffer.append( ',' );
}
buffer.append( name );
if ( symb.length() != 0 ) {
buffer.append( '(' );
buffer.append( symb );
buffer.append( ')' );
}
}
}
return buffer.toString();
}
/**
* V�rifie si cet ensemble est identique � l'objet <code>other</code>
* sp�cifi�. Deux ensembles sont consid�r�s identiques s'ils contienent
* les m�mes pr�fix.
*/
public boolean equals( final Object other ) {
if ( other == this )
return true; // slight optimisation
if ( other instanceof PrefixSet ) {
final Prefix[] array = ( (PrefixSet) other ).prefix;
if ( prefix.length == array.length ) {
for ( int i = 0; i < array.length; i++ )
if ( !prefix[i].equals( array[i] ) )
return false;
return true;
}
}
return false;
}
/**
* Retourne un code repr�sentant cet ensemble de pr�fix.
*/
public int hashCode() {
int code = prefix.length << 1;
for ( int i = 0; i < prefix.length; i += 5 )
code += prefix[i].hashCode();
return code;
}
/**
* Retourne un exemplaire unique de cet ensemble de pr�fix. Une banque de pr�fix, initialement
* vide, est maintenue de fa�on interne par la classe <code>PrefixSet</code>. Lorsque la m�thode
* <code>intern</code> est appel�e, elle recherchera des pr�fix �gaux � <code>this</code> au
* sens de la m�thode {@link #equals}. Si de tels pr�fix sont trouv�s, ils seront retourn�s.
* Sinon, les pr�fix <code>this</code> seront ajout�s � la banque de donn�es en utilisant une
* {@link java.lang.ref.WeakReference r�f�rence faible} et cette m�thode retournera <code>this</code>.
* <br><br>
* De cette m�thode il s'ensuit que pour deux ensembles de pr�fix <var>u</var> et <var>v</var>,
* la condition <code>u.intern()==v.intern()</code> sera vrai si et seulement si
* <code>u.equals(v)</code> est vrai.
*/
private final PrefixSet intern() {
return (PrefixSet) pool.intern( this );
}
/**
* Apr�s la lecture d'une unit�, v�rifie si ce pr�fix
* appara�t d�j� dans la banque des pr�fix .
* Si oui, l'exemplaire de la banque sera retourn� plut�t
* que de garder inutilement le pr�fix courant comme copie.
*/
private Object readResolve() {
return intern();
}
}