001: package gnu.xquery.util;
002:
003: import gnu.lists.*;
004: import gnu.mapping.*;
005: import gnu.kawa.util.*;
006: import gnu.xml.*;
007: import gnu.kawa.xml.*;
008: import gnu.math.*;
009:
010: public class DistinctValues {
011: public static void distinctValues$X(Object values,
012: NamedCollator coll, CallContext ctx) {
013: DistinctValuesConsumer out = new DistinctValuesConsumer(coll,
014: ctx.consumer);
015: Values.writeValues(values, out);
016: }
017:
018: /*
019: public void apply (CallContext ctx) throws Throwable
020: {
021: Object arg = ctx.getNextArg();
022: Object collation = ctx.getNextArg(null);
023: ctx.lastArg();
024: DistinctValuesConsumer out
025: = new DistinctValuesConsumer(ctx.consumer);
026: if (collation != null)
027: {
028: // FIXME
029: }
030: Values.writeValues(arg, out);
031: }
032: */
033: }
034:
035: /*
036: class FilterValueConsumer implements Consumer
037: {
038: Convert convert;
039:
040: public Consumer append (char v)
041: {
042: writeObject(convert.charToObject(v));
043: }
044:
045: public void writeBoolean (boolean v)
046: {
047: writeObject(convert.booleanToObject(v));
048: }
049:
050: public void writeFloat (float v)
051: {
052: writeObject(convert.floatToObject(v));
053: }
054:
055: public void writeDouble (double v)
056: {
057: writeObject(convert.doubleToObject(v));
058: }
059:
060: public void writeInt (int v)
061: {
062: writeObject(convert.intToObject(v));
063: }
064:
065: public void writeLong (long v)
066: {
067: writeObject(convert.longToObject(v));
068: }
069: }
070: */
071:
072: class DistinctValuesHashTable extends GeneralHashTable {
073: NamedCollator collator;
074:
075: public DistinctValuesHashTable(NamedCollator collator) {
076: this .collator = collator;
077: }
078:
079: public int hash(Object key) {
080: if (key == null)
081: return 0;
082: if (key instanceof Number
083: && (key instanceof RealNum || !(key instanceof Numeric))) {
084: int hash = Float
085: .floatToIntBits(((Number) key).floatValue());
086: if (hash == 0x80000000) // Map -0.0 to 0
087: hash = 0;
088: return hash;
089: }
090: // This mostly-works, but isn't reliable FIXME.
091: // One problem is that we ignore collation.
092: return key.hashCode();
093: }
094:
095: public boolean matches(Object value1, Object value2) {
096: if (value1 == value2)
097: return true;
098: if (NumberValue.isNaN(value1) && NumberValue.isNaN(value2))
099: return true;
100: return Compare.apply(Compare.LENIENT_EQ, value1, value2,
101: collator);
102: }
103: }
104:
105: class DistinctValuesConsumer extends FilterConsumer implements
106: PositionConsumer {
107: DistinctValuesHashTable table;
108:
109: public DistinctValuesConsumer(NamedCollator collator, Consumer out) {
110: super (out);
111: table = new DistinctValuesHashTable(collator);
112: }
113:
114: public void consume(SeqPosition position) {
115: writeObject(position);
116: }
117:
118: public void writePosition(AbstractSequence seq, int ipos) {
119: writeObject(((NodeTree) seq).typedValue(ipos));
120: }
121:
122: public void writeBoolean(boolean v) {
123: writeObject(v ? Boolean.TRUE : Boolean.FALSE);
124: }
125:
126: public void writeObject(Object value) {
127: if (value instanceof Values) {
128: Values.writeValues(value, this );
129: return;
130: }
131: if (value instanceof KNode) {
132: KNode node = (KNode) value;
133: writeObject(((NodeTree) node.sequence)
134: .typedValue(node.ipos));
135: return;
136: }
137: Object old = table.get(value, null);
138: if (old != null)
139: return;
140: table.put(value, value);
141: base.writeObject(value);
142: }
143: }
|