001package com.hammurapi.extract; 002 003import java.io.Serializable; 004import java.util.Collections; 005import java.util.HashSet; 006import java.util.Map; 007import java.util.Set; 008import java.util.TreeSet; 009import java.util.concurrent.TimeUnit; 010 011 012/** 013 * Commutative OR. 014 * @author Pavel Vlasov. 015 * 016 * @param <T> 017 */ 018public class CommutativeOr<T, C> extends ExtractorBase<T, Boolean, C> implements CommutativeCompositePredicate<T, C, CommutativeOr<T,C>>, Serializable { 019 020 private Set<Predicate<T, C>> parts = new HashSet<Predicate<T, C>>(); 021 022 public CommutativeOr(double initialCost, TimeUnit costUnit) { 023 super(initialCost,costUnit); 024 } 025 026 public CommutativeOr(double initialCost,TimeUnit costUnit, Predicate<T,C>... parts) { 027 super(initialCost,costUnit); 028 for (Predicate<T,C> part: parts) { 029 addPart(part); 030 } 031 } 032 033 public CommutativeOr(double initialCost,TimeUnit costUnit, Iterable<Predicate<T,C>> parts) { 034 super(initialCost,costUnit); 035 for (Predicate<T,C> part: parts) { 036 addPart(part); 037 } 038 } 039 040 private void addPart(Predicate<T, C> part) { 041 if (part instanceof CommutativeOr) { 042 for (Predicate<T, C> pp: ((CommutativeOr<T, C>) part).getParts()) { 043 addPart(pp); 044 } 045 } else { 046 parts.add(part); 047 } 048 } 049 050 public Set<Predicate<T, C>> getParts() { 051 return Collections.unmodifiableSet(parts); 052 } 053 054 @Override 055 @SuppressWarnings("unchecked") 056 public ComparisonResult compareTo(Extractor<T, Boolean, C> otherPredicate) { 057 if (getParts().isEmpty()) { 058 return True.getInstance().compareTo((Extractor<Object, Boolean, Object>) otherPredicate); 059 } 060 061 if (otherPredicate instanceof CommutativeOr && parts.equals(((CommutativeOr) otherPredicate).parts)) { 062 return ComparisonResult.EQUAL_NM; 063 } 064 065 boolean isTrue = false; 066 boolean isFalse = true; 067 for (Predicate<T, C> part: getParts()) { 068 ComparisonResult pcr = part.compareTo((Predicate<T, C>) True.getInstance()); 069 if (pcr.getType().equals(ComparisonResult.Type.EQUAL)) { 070 isTrue = true; 071 isFalse = false; 072 break; 073 } else if (!pcr.getType().equals(ComparisonResult.Type.OPPOSITE)) { 074 isFalse = false; 075 } 076 } 077 078 if (isTrue) { 079 return otherPredicate.compareTo((Predicate<T, C>) True.getInstance()); 080 } 081 082 if (isFalse) { 083 return otherPredicate.compareTo((Predicate<T, C>) False.getInstance()); 084 } 085 086 if (getParts().size()==1) { 087 return getParts().iterator().next().compareTo(otherPredicate); 088 } 089 for (Predicate<T, C> part: getParts()) { 090 ComparisonResult pcr = part.compareTo(otherPredicate); 091 if (pcr.isOneToOneMapping()) { 092 switch (pcr.getType()) { 093 case EQUAL: 094 case LESS_RESTRICTIVE: 095 return ComparisonResult.LESS_RESTRICTIVE_NM; 096// case OPPOSITE: 097// case OPPOSITE_LESS_RESTRICTIVE: 098// return ComparisonResult.OPPOSITE_MORE_RESTRICTIVE_NM; 099 } 100 } 101 } 102 103 return super.compareTo(otherPredicate); 104 } 105 106 protected Boolean extractInternal(C context, Map<C, Map<Extractor<T, ? super Boolean, C>, ? super Boolean>> cache, T... obj) { 107 for (Predicate<T, C> part: parts) { 108 if (part.extract(context, cache, obj)) { 109 return true; 110 } 111 } 112 return false; 113 } 114 115 public Set<Integer> parameterIndices() { 116 Set<Integer> ret = new TreeSet<Integer>(); 117 for (Predicate<T, C> part: parts) { 118 ret.addAll(part.parameterIndices()); 119 } 120 return ret; 121 } 122 123 124 @SuppressWarnings("unchecked") 125 public Predicate<T, C> remove(Predicate<T, C> part) { 126 if (!parts.contains(part)) { 127 return this; 128 } 129 try { 130 CommutativeOr<T, C> ret = (CommutativeOr<T, C>) clone(); 131 ret.parts.remove(part); 132 return ret.parts.size()==1 ? ret.parts.iterator().next() : ret; 133 } catch (CloneNotSupportedException e) { 134 throw new ExtractorException(e); 135 } 136 } 137 138 @SuppressWarnings("unchecked") 139 public Predicate<T, C> normalize() { 140 if (getParts().isEmpty()) { 141 return True.getInstance(); 142 } 143 if (getParts().size()==1) { 144 Predicate<T, C> ret = getParts().iterator().next(); 145 if (ret instanceof CompositePredicate) { 146 ((CompositePredicate) ret).normalize(); 147 } 148 return ret; 149 } 150 ComparisonResult cr = compareTo((Predicate<T, C>) True.getInstance()); 151 if (cr.getType().equals(ComparisonResult.Type.EQUAL)) { 152 return True.getInstance(); 153 } 154 if (cr.getType().equals(ComparisonResult.Type.OPPOSITE)) { 155 return False.getInstance(); 156 } 157 158 Predicate<T, C>[] pa = getParts().toArray(new Predicate[getParts().size()]); 159 Z: for (int i=0; i<pa.length; ++i) { 160 for (int j=0; j<pa.length; ++j) { 161 if (j!=i && pa[i]!=null && pa[j]!=null) { 162 ComparisonResult pcr1 = pa[i].compareTo(pa[j]); 163 if (pcr1.isOneToOneMapping()) { 164 switch (pcr1.getType()) { 165 case EQUAL: 166 case MORE_RESTRICTIVE: 167 pa[j]=null; 168 continue; 169 case OPPOSITE: 170 case OPPOSITE_MORE_RESTRICTIVE: 171 return True.getInstance(); 172 } 173 } 174 175 ComparisonResult pcr2 = pa[j].compareTo(pa[i]); 176 if (pcr2.isOneToOneMapping()) { 177 switch (pcr2.getType()) { 178 case EQUAL: 179 case MORE_RESTRICTIVE: 180 pa[i]=null; 181 continue Z; 182 case OPPOSITE: 183 case OPPOSITE_MORE_RESTRICTIVE: 184 return True.getInstance(); 185 } 186 } 187 } 188 } 189 } 190 191 int pc = 0; 192 for (Predicate<T, C> part: pa) { 193 if (part!=null) { 194 ++pc; 195 } 196 } 197 198 if (pc==0) { 199 return True.getInstance(); 200 } 201 202 if (pc==1) { 203 for (Predicate<T, C> part: pa) { 204 if (part!=null) { 205 if (part instanceof CompositePredicate) { 206 ((CompositePredicate) part).normalize(); 207 } 208 return part; 209 } 210 } 211 } 212 213 if (pc!=pa.length) { 214 CommutativeOr<T, C> ret = new CommutativeOr<T, C>(cost,costUnit); 215 for (Predicate<T, C> part: pa) { 216 if (part!=null) { 217 ret.addPart(part); 218 } 219 } 220 return ret; 221 } 222 223 224 return this; 225 } 226 227 public boolean isContextDependent() { 228 for (Predicate<T, C> part: getParts()) { 229 if (part.isContextDependent()) { 230 return true; 231 } 232 } 233 return false; 234 } 235 236 @Override 237 public String toString() { 238 return getClass().getName()+getParts(); 239 } 240 241 @Override 242 public double getCost() { 243 if (cost==0 && costUnit==null) { 244 double ret = 0; 245 for (Predicate<T,C> part: parts) { 246 ret+=part.getCost(); 247 } 248 return ret; 249 } 250 return super.getCost(); 251 } 252 253 254 @Override 255 public Extractor<T, Boolean, C> map(int[] map) { 256 CommutativeOr<T,C> ret = new CommutativeOr<T, C>(initialCost, costUnit); 257 for (Predicate<T,C> part: parts) { 258 ret.addPart(MappedPredicate.mapPredicate(part, map)); 259 } 260 return ret; 261 } 262 263 @Override 264 public Object clone() throws CloneNotSupportedException { 265 @SuppressWarnings("unchecked") 266 CommutativeOr<T,C> ret = (CommutativeOr<T, C>) super.clone(); 267 ret.parts = new HashSet<Predicate<T,C>>(parts); 268 return ret; 269 } 270 271 @Override 272 public CommutativeOr<T, C> add(Predicate<T, C> part) { 273 CommutativeOr<T, C> ret = new CommutativeOr<T, C>(initialCost, costUnit, parts); 274 ret.parts.add(part); 275 return ret; 276 } 277 278}