blob: 2ac6975354ed25b72d679df17a49102b95cd7fcc [file] [log] [blame]
/**
*******************************************************************************
* Copyright (C) 1996-2001, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
* $Source: /xsrl/Nsvn/icu/unicodetools/com/ibm/text/utility/EquivalenceClass.java,v $
* $Date: 2004/02/06 18:29:39 $
* $Revision: 1.3 $
*
*******************************************************************************
*/
package com.ibm.text.utility;
import java.io.*;
import java.util.*;
public class EquivalenceClass {
static final boolean DEBUG = false;
/**
* Takes a many:many relation between source and value.
* Produces equivalence class.
* Two sources are in the same equivalence class any time they share the same value.
*/
// associated with each value, we keep a set of sources.
// whenever we add a <source, value> pair, we see if any sets collide.
// associated with each set of sources, we keep a representative Whenever we add to the set, if we
//
Map sourceToEquiv = new TreeMap();
Map valueToRepresentativeSource = new HashMap();
Map forcedMerge = new HashMap();
/**
* @return true if made a difference
*/
String itemSeparator;
int places;
boolean hex;
public EquivalenceClass() {
this(",", 4, true);
}
public EquivalenceClass(String itemSeparator, int places, boolean hex) {
this.itemSeparator = itemSeparator;
this.places = places;
this.hex = hex;
}
public boolean add(Object source, Object value) {
boolean result = false;
Object repSource = valueToRepresentativeSource.get(value);
Set equivSet = (Set)sourceToEquiv.get(source);
Set fm = (Set)forcedMerge.get(source);
if (fm == null) {
fm = new TreeSet();
forcedMerge.put(source, fm);
}
if (DEBUG) System.out.println("+Source " + source
+ ", value: " + value);
if (repSource == null && equivSet == null) {
equivSet = new TreeSet();
equivSet.add(source);
sourceToEquiv.put(source, equivSet);
valueToRepresentativeSource.put(value, source);
repSource = source; // for debugging
} else if (equivSet == null) {
equivSet = (Set) sourceToEquiv.get(repSource);
equivSet.add(source);
sourceToEquiv.put(source, equivSet);
result = true;
} else if (repSource == null) {
valueToRepresentativeSource.put(value, source);
repSource = source; // for debugging;
} else { // both non-null
Set repEquiv = (Set) sourceToEquiv.get(repSource);
if (!repEquiv.equals(equivSet)) {
result = true;
if (DEBUG) System.out.println("Merging (" + repSource + ") " + toString(repEquiv)
+ " + (" + source + ") " + toString(equivSet));
// merge!!
// put all items from equivSet into repEquiv
repEquiv.addAll(equivSet);
// now add the values to the forced sets
Iterator it = repEquiv.iterator();
while (it.hasNext()) {
Object n = it.next();
fm = (Set)forcedMerge.get(n);
fm.add(value);
}
// then replace all instances for equivSet by repEquiv
// we have to do this in two steps, since iterators are invalidated by changes
Set toReplace = new TreeSet();
it = sourceToEquiv.keySet().iterator();
while (it.hasNext()) {
Object otherSource = it.next();
Set otherSet = (Set) sourceToEquiv.get(otherSource);
if (otherSet == equivSet) {
toReplace.add(otherSource);
}
}
it = toReplace.iterator();
while (it.hasNext()) {
Object otherSource = it.next();
sourceToEquiv.put(otherSource,repEquiv);
}
equivSet = repEquiv; // for debugging
}
}
if (DEBUG) System.out.println("--- repSource: " + repSource
+ ", equivSet: " + equivSet);
return result;
}
public String toString () {
StringBuffer result = new StringBuffer();
// make a set to skip duplicates
Iterator it = new HashSet(sourceToEquiv.values()).iterator();
while (it.hasNext()) {
toString((Set)it.next(), result, forcedMerge);
}
return result.toString();
}
private class MyIterator implements Iterator {
Iterator it = sourceToEquiv.keySet().iterator();
public boolean hasNext() {
return it.hasNext();
}
public Object next() {
return sourceToEquiv.get(it.next());
}
public void remove() {
throw new IllegalArgumentException("can't remove");
}
}
public Iterator getSetIterator () {
return new MyIterator();
}
private String toString(Object s) {
if (s == null) return "null";
if (s instanceof Collection) {
StringBuffer sb = new StringBuffer();
toString((Collection)s, sb, null);
return sb.toString();
}
if (hex && s instanceof Number) {
return Utility.hex(s, places);
}
return s.toString();
}
private void toString(Collection s, StringBuffer sb, Map valueToRep) {
if (sb.length() != 0) sb.append(itemSeparator);
if (s == null) {
sb.append("{}");
return;
}
sb.append('{');
Iterator it = s.iterator();
boolean notFirst = false;
while (it.hasNext()) {
if (notFirst) sb.append(", ");
notFirst = true;
Object n = it.next();
sb.append(toString(n));
/*if (valueToRep != null) {
sb.append("(" + toString(valueToRep.get(n)) + ")");
}*/
}
sb.append('}');
}
}