001package com.hammurapi.extract; 002 003import java.util.Arrays; 004import java.util.Set; 005 006/** 007 * Result of comparison of two extractors/predicates. 008 * @author Pavel Vlasov 009 * 010 */ 011public class ComparisonResult { 012 013 // Not mapping constants 014 public static final ComparisonResult EQUAL_NM = new ComparisonResult(Type.EQUAL, null); 015 public static final ComparisonResult UNEQUAL_NM = new ComparisonResult(Type.UNEQUAL, null); 016 public static final ComparisonResult LESS_RESTRICTIVE_NM = new ComparisonResult(Type.LESS_RESTRICTIVE, null); 017 public static final ComparisonResult MORE_RESTRICTIVE_NM = new ComparisonResult(Type.MORE_RESTRICTIVE, null); 018 public static final ComparisonResult NOT_EQUAL_NM = new ComparisonResult(Type.NOT_EQUAL, null); 019 public static final ComparisonResult OPPOSITE_NM = new ComparisonResult(Type.OPPOSITE, null); 020 public static final ComparisonResult OPPOSITE_LESS_RESTRICTIVE_NM = new ComparisonResult(Type.OPPOSITE_LESS_RESTRICTIVE, null); 021 public static final ComparisonResult OPPOSITE_MORE_RESTRICTIVE_NM = new ComparisonResult(Type.OPPOSITE_MORE_RESTRICTIVE, null); 022 023 /** 024 * Result of extractor comparison. 025 * @author Pavel Vlasov. 026 * 027 */ 028 public enum Type { 029 /** 030 * Extractors are equal. 031 */ 032 EQUAL, 033 /** 034 * Extractors are not equal, i.e. no conclusion can be drawn about values 035 * returned by extractors. 036 */ 037 NOT_EQUAL, 038 039 // Enums below are applicable only to predicates. 040 /** 041 * This predicate is less restrictive than the parameter 042 * predicate. E.g. x<=5 is less restrictive than x<5. 043 */ 044 LESS_RESTRICTIVE, 045 /** 046 * This predicate is more restrictive than the parameter 047 * predicate. E.g. x<6 is more restrictive than x<7. 048 */ 049 MORE_RESTRICTIVE, 050 /** 051 * When this predicate evaluates to true, the parameter 052 * predicate evaluates to false and vice-versa. 053 */ 054 OPPOSITE, 055 /** 056 * The opposite of this predicate is less restrictive than 057 * the parameter predicate. 058 * E.g. x>5 opposite is x<=5 and it is is less restrictive than x<5. 059 */ 060 OPPOSITE_LESS_RESTRICTIVE, 061 /** 062 * The opposite of this predicate is more restrictive than 063 * the parameter predicate. 064 * E.g. x>5 opposite is x<=5 and it is is more restrictive than x<7. 065 */ 066 OPPOSITE_MORE_RESTRICTIVE, 067 068 // Enums applicable to extractors and constants. 069 070 /** 071 * Value extracted by the first extractor is less than value extracted by the second extractor 072 * for any combination of parameters. 073 */ 074 LESS_THAN, 075 076 /** 077 * Value extracted by the first extractor is less than or equal to the value extracted by the second extractor 078 * for any combination of parameters. 079 */ 080 LESS_EQUAL, 081 082 /** 083 * Value extracted by the first extractor is more than or equal to the value extracted by the second extractor 084 * for any combination of parameters. 085 */ 086 MORE_EQUAL, 087 088 /** 089 * Value extracted by the first extractor is more than value extracted by the second extractor 090 * for any combination of parameters. 091 */ 092 MORE_THAN, 093 094 /** 095 * Value extracted by the first extractor is not equal to the value extracted by the second extractor 096 * for any combination of parameters. Do not mistake this with NOT_EQUAL. For boolean values (predicates) UNEQUAL is 097 * equivalent to OPPOSITE. 098 */ 099 UNEQUAL 100 } 101 102 private ComparisonResult.Type type; 103 private int[] indexMap; 104 105 public ComparisonResult(ComparisonResult.Type type, int[] indexMap) { 106 this.type = type; 107 this.indexMap = indexMap; 108 } 109 110 /** 111 * @return mapping of indices of parameter extractor to this extractor. E.g. extractors 112 * <code>arg[0] < arg[1]</code> and <code>arg[1] > arg[0]</code> are equal with index mapping {1, 0}. 113 * <code>null</code> is returned for no mapping (if extractors are <code>NOT_EQUAL</code>) and for 1 to 1 mapping. 114 * In other words, if cr = e1.compareTo(e2), 115 * then new MappedExtractor(e1, cr.getIndexMap()).compareTo(e2).isOneToOneMapping()==true or 116 * return value of new MappedExtractor(e1, cr.getIndexMap()).extract() is the same as of e2.extract() 117 */ 118 public int[] getIndexMap() { 119 return indexMap; 120 } 121 122 public Type getType() { 123 return type; 124 } 125 126 public boolean isOneToOneMapping() { 127 return isOneToOneMapping(indexMap); 128 } 129 130 public static boolean isOneToOneMapping(int[] map) { 131 if (map==null) { 132 return true; 133 } 134 for (int i=0; i<map.length; ++i) { 135 if (map[i]!=i && map[i]!=-1) { 136 return false; 137 } 138 } 139 return true; 140 } 141 142 public boolean compareIndexMaps(int[] otherIndexMap) { 143 if (indexMap==null) { // Assumes 1-1 mapping 144 if (otherIndexMap==null) { 145 return true; 146 } 147 148 for (int i=0; i<otherIndexMap.length; ++i) { 149 if (otherIndexMap[i]!=i) { 150 return false; 151 } 152 } 153 return true; 154 } 155 156 if (otherIndexMap==null) { 157 for (int i=0; i<indexMap.length; ++i) { 158 if (indexMap[i]!=i) { 159 return false; 160 } 161 } 162 return true; 163 } 164 165 return Arrays.equals(indexMap, otherIndexMap); 166 } 167 168 @Override 169 public String toString() { 170 return "ComparisonResult [type=" + type + ", indexMap=" 171 + Arrays.toString(indexMap) + "]"; 172 } 173 174 /** 175 * Inverses index map. 176 * @param indexMap2 177 * @return 178 */ 179 public static int[] inverse(int[] map, Set<Integer> parameterIndices) { 180 if (map==null) { 181 return null; 182 } 183 184 int dim = -1; 185 for (int i=0; i<map.length; ++i) { 186 if (parameterIndices.contains(i)) { 187 if (map[i]>dim) { 188 dim = map[i]; 189 } 190 } 191 } 192 int[] ret = new int[dim+1]; 193 194 for (int i=0; i<map.length; ++i) { 195 if (parameterIndices.contains(i)) { 196 ret[map[i]] = i; 197 } 198 } 199 return ret; 200 } 201 202 @Override 203 public int hashCode() { 204 final int prime = 31; 205 int result = 1; 206 result = prime * result + Arrays.hashCode(indexMap); 207 result = prime * result + ((type == null) ? 0 : type.hashCode()); 208 return result; 209 } 210 211 @Override 212 public boolean equals(Object obj) { 213 if (this == obj) 214 return true; 215 if (obj == null) 216 return false; 217 if (getClass() != obj.getClass()) 218 return false; 219 ComparisonResult other = (ComparisonResult) obj; 220 if (!(isOneToOneMapping() && other.isOneToOneMapping())) { 221 if (!Arrays.equals(indexMap, other.indexMap)) 222 return false; 223 } 224 225 if (type != other.type) 226 return false; 227 return true; 228 } 229 230}