Home | History | Annotate | Download | only in impl
      1 /*
      2 **********************************************************************
      3 * Copyright (c) 2002-2010, International Business Machines
      4 * Corporation and others.  All Rights Reserved.
      5 **********************************************************************
      6 * Author: M. Davis
      7 * Created: December 2002 (moved from UnicodeSet)
      8 * Since: ICU 2.4
      9 **********************************************************************
     10 */
     11 package com.ibm.icu.impl;
     12 
     13 import java.util.Iterator;
     14 import java.util.SortedSet;
     15 import java.util.TreeSet;
     16 
     17 /**
     18  * Computationally efficient determination of the relationship between
     19  * two SortedSets.
     20  */
     21 public class SortedSetRelation {
     22 
     23     /**
     24      * The relationship between two sets A and B can be determined by looking at:
     25      * A - B
     26      * A & B (intersection)
     27      * B - A
     28      * These are represented by a set of bits.
     29      * Bit 2 is true if A - B is not empty
     30      * Bit 1 is true if A & B is not empty
     31      * BIT 0 is true if B - A is not empty
     32      */
     33     public static final int
     34         A_NOT_B = 4,
     35         A_AND_B = 2,
     36         B_NOT_A = 1;
     37 
     38     /**
     39      * There are 8 combinations of the relationship bits. These correspond to
     40      * the filters (combinations of allowed bits) in hasRelation. They also
     41      * correspond to the modification functions, listed in comments.
     42      */
     43     public static final int
     44        ANY =            A_NOT_B |   A_AND_B |   B_NOT_A,    // union,           addAll
     45        CONTAINS =       A_NOT_B |   A_AND_B,                // A                (unnecessary)
     46        DISJOINT =       A_NOT_B |               B_NOT_A,    // A xor B,         missing Java function
     47        ISCONTAINED =                A_AND_B |   B_NOT_A,    // B                (unnecessary)
     48        NO_B =           A_NOT_B,                            // A setDiff B,     removeAll
     49        EQUALS =                     A_AND_B,                // A intersect B,   retainAll
     50        NO_A =                                   B_NOT_A,    // B setDiff A,     removeAll
     51        NONE =           0,                                  // null             (unnecessary)
     52 
     53        ADDALL = ANY,                // union,           addAll
     54        A = CONTAINS,                // A                (unnecessary)
     55        COMPLEMENTALL = DISJOINT,    // A xor B,         missing Java function
     56        B = ISCONTAINED,             // B                (unnecessary)
     57        REMOVEALL = NO_B,            // A setDiff B,     removeAll
     58        RETAINALL = EQUALS,          // A intersect B,   retainAll
     59        B_REMOVEALL = NO_A;          // B setDiff A,     removeAll
     60 
     61 
     62     /**
     63      * Utility that could be on SortedSet. Faster implementation than
     64      * what is in Java for doing contains, equals, etc.
     65      * @param a first set
     66      * @param allow filter, using ANY, CONTAINS, etc.
     67      * @param b second set
     68      * @return whether the filter relationship is true or not.
     69      */
     70     public static <T extends Object & Comparable<? super T>> boolean hasRelation(SortedSet<T> a, int allow, SortedSet<T> b) {
     71         if (allow < NONE || allow > ANY) {
     72             throw new IllegalArgumentException("Relation " + allow + " out of range");
     73         }
     74 
     75         // extract filter conditions
     76         // these are the ALLOWED conditions Set
     77 
     78         boolean anb = (allow & A_NOT_B) != 0;
     79         boolean ab = (allow & A_AND_B) != 0;
     80         boolean bna = (allow & B_NOT_A) != 0;
     81 
     82         // quick check on sizes
     83         switch(allow) {
     84             case CONTAINS: if (a.size() < b.size()) return false; break;
     85             case ISCONTAINED: if (a.size() > b.size()) return false; break;
     86             case EQUALS: if (a.size() != b.size()) return false; break;
     87         }
     88 
     89         // check for null sets
     90         if (a.size() == 0) {
     91             if (b.size() == 0) return true;
     92             return bna;
     93         } else if (b.size() == 0) {
     94             return anb;
     95         }
     96 
     97         // pick up first strings, and start comparing
     98         Iterator<? extends T> ait = a.iterator();
     99         Iterator<? extends T> bit = b.iterator();
    100 
    101         T aa = ait.next();
    102         T bb = bit.next();
    103 
    104         while (true) {
    105             int comp = aa.compareTo(bb);
    106             if (comp == 0) {
    107                 if (!ab) return false;
    108                 if (!ait.hasNext()) {
    109                     if (!bit.hasNext()) return true;
    110                     return bna;
    111                 } else if (!bit.hasNext()) {
    112                     return anb;
    113                 }
    114                 aa = ait.next();
    115                 bb = bit.next();
    116             } else if (comp < 0) {
    117                 if (!anb) return false;
    118                 if (!ait.hasNext()) {
    119                     return bna;
    120                 }
    121                 aa = ait.next();
    122             } else  {
    123                 if (!bna) return false;
    124                 if (!bit.hasNext()) {
    125                     return anb;
    126                 }
    127                 bb = bit.next();
    128             }
    129         }
    130     }
    131 
    132     /**
    133      * Utility that could be on SortedSet. Allows faster implementation than
    134      * what is in Java for doing addAll, removeAll, retainAll, (complementAll).
    135      * @param a first set
    136      * @param relation the relation filter, using ANY, CONTAINS, etc.
    137      * @param b second set
    138      * @return the new set
    139      */
    140     public static <T extends Object & Comparable<? super T>> SortedSet<? extends T> doOperation(SortedSet<T> a, int relation, SortedSet<T> b) {
    141         // TODO: optimize this as above
    142         TreeSet<? extends T> temp;
    143         switch (relation) {
    144             case ADDALL:
    145                 a.addAll(b);
    146                 return a;
    147             case A:
    148                 return a; // no action
    149             case B:
    150                 a.clear();
    151                 a.addAll(b);
    152                 return a;
    153             case REMOVEALL:
    154                 a.removeAll(b);
    155                 return a;
    156             case RETAINALL:
    157                 a.retainAll(b);
    158                 return a;
    159             // the following is the only case not really supported by Java
    160             // although all could be optimized
    161             case COMPLEMENTALL:
    162                 temp = new TreeSet<T>(b);
    163                 temp.removeAll(a);
    164                 a.removeAll(b);
    165                 a.addAll(temp);
    166                 return a;
    167             case B_REMOVEALL:
    168                 temp = new TreeSet<T>(b);
    169                 temp.removeAll(a);
    170                 a.clear();
    171                 a.addAll(temp);
    172                 return a;
    173             case NONE:
    174                 a.clear();
    175                 return a;
    176             default:
    177                 throw new IllegalArgumentException("Relation " + relation + " out of range");
    178         }
    179     }
    180 }
    181