1 13 package mondrian.olap.fun; 14 15 import mondrian.olap.*; 16 import mondrian.olap.type.*; 17 import mondrian.resource.MondrianResource; 18 import mondrian.calc.Calc; 19 import mondrian.calc.ExpCompiler.ResultStyle; 20 import mondrian.calc.DoubleCalc; 21 import mondrian.mdx.*; 22 23 import org.apache.log4j.Logger; 24 25 import java.util.*; 26 import java.util.Set ; 27 import java.io.PrintWriter ; 28 29 37 public class FunUtil extends Util { 38 39 static final String [] emptyStringArray = new String [0]; 40 private static final boolean debug = false; 41 public static final NullMember NullMember = new NullMember(); 42 43 47 public static final double DoubleNull = 0.000000012345; 48 49 53 public static final double DoubleEmpty = -0.000000012345; 54 55 59 public static final int IntegerNull = Integer.MIN_VALUE + 1; 60 61 65 public static final boolean BooleanNull = false; 66 67 71 public static RuntimeException newEvalException( 72 FunDef funDef, 73 String message) { 74 Util.discard(funDef); return new MondrianEvaluationException(message); 76 } 77 78 82 public static RuntimeException newEvalException(Throwable throwable) { 83 return new MondrianEvaluationException(throwable.getMessage()); 84 } 85 86 public static final boolean isMemberType(Calc calc) { 87 Type type = calc.getType(); 88 return (type instanceof SetType) && 89 (((SetType) type).getElementType() instanceof MemberType); 90 } 91 92 public static final void checkIterListResultStyles(Calc calc) { 93 switch (calc.getResultStyle()) { 94 case ITERABLE: 95 case LIST: 96 case MUTABLE_LIST: 97 break; 98 default: 99 throw ResultStyleException.generateBadType( 100 new ResultStyle[] { 101 ResultStyle.ITERABLE, 102 ResultStyle.LIST, 103 ResultStyle.MUTABLE_LIST 104 }, 105 calc.getResultStyle()); 106 } 107 } 108 109 public static final void checkListResultStyles(Calc calc) { 110 switch (calc.getResultStyle()) { 111 case LIST: 112 case MUTABLE_LIST: 113 break; 114 default: 115 throw ResultStyleException.generateBadType( 116 new ResultStyle[] { 117 ResultStyle.LIST, 118 ResultStyle.MUTABLE_LIST 119 }, 120 calc.getResultStyle()); 121 } 122 } 123 124 125 128 static String getLiteralArg( 129 ResolvedFunCall call, 130 int i, 131 String defaultValue, 132 String [] allowedValues) { 133 if (i >= call.getArgCount()) { 134 if (defaultValue == null) { 135 throw newEvalException(call.getFunDef(), 136 "Required argument is missing"); 137 } else { 138 return defaultValue; 139 } 140 } 141 Exp arg = call.getArg(i); 142 if (!(arg instanceof Literal) || 143 arg.getCategory() != Category.Symbol) { 144 throw newEvalException(call.getFunDef(), 145 "Expected a symbol, found '" + arg + "'"); 146 } 147 String s = (String ) ((Literal) arg).getValue(); 148 StringBuilder sb = new StringBuilder (64); 149 for (int j = 0; j < allowedValues.length; j++) { 150 String allowedValue = allowedValues[j]; 151 if (allowedValue.equalsIgnoreCase(s)) { 152 return allowedValue; 153 } 154 if (j > 0) { 155 sb.append(", "); 156 } 157 sb.append(allowedValue); 158 } 159 throw newEvalException(call.getFunDef(), 160 "Allowed values are: {" + sb + "}"); 161 } 162 163 167 static <E extends Enum <E>> E getLiteralArg( 168 ResolvedFunCall call, 169 int i, 170 E defaultValue, 171 Class <E> allowedValues) { 172 if (i >= call.getArgCount()) { 173 if (defaultValue == null) { 174 throw newEvalException(call.getFunDef(), 175 "Required argument is missing"); 176 } else { 177 return defaultValue; 178 } 179 } 180 Exp arg = call.getArg(i); 181 if (!(arg instanceof Literal) || 182 arg.getCategory() != Category.Symbol) { 183 throw newEvalException(call.getFunDef(), 184 "Expected a symbol, found '" + arg + "'"); 185 } 186 String s = (String ) ((Literal) arg).getValue(); 187 for (E e : allowedValues.getEnumConstants()) { 188 if (e.name().equalsIgnoreCase(s)) { 189 return e; 190 } 191 } 192 StringBuilder buf = new StringBuilder (64); 193 int k = 0; 194 for (E e : allowedValues.getEnumConstants()) { 195 if (k++ > 0) { 196 buf.append(", "); 197 } 198 buf.append(e.name()); 199 } 200 throw newEvalException(call.getFunDef(), 201 "Allowed values are: {" + buf + "}"); 202 } 203 204 211 static void checkCompatible(Exp left, Exp right, FunDef funDef) { 212 final Type leftType = TypeUtil.stripSetType(left.getType()); 213 final Type rightType = TypeUtil.stripSetType(right.getType()); 214 if (!TypeUtil.isUnionCompatible(leftType, rightType)) { 215 throw newEvalException(funDef, "Expressions must have the same hierarchy"); 216 } 217 } 218 219 228 static boolean checkFlag(int value, int mask, boolean strict) { 229 return (strict) 230 ? ((value & mask) == mask) 231 : ((value & mask) != 0); 232 } 233 234 238 static void addUnique(List left, List right, Set set) { 239 assert left != null; 240 assert right != null; 241 if (right.isEmpty()) { 242 return; 243 } 244 for (int i = 0, n = right.size(); i < n; i++) { 245 Object o = right.get(i), 246 p = o; 247 if (o instanceof Object []) { 248 p = new ArrayHolder((Object []) o); 249 } 250 if (set.add(p)) { 251 left.add(o); 252 } 253 } 254 } 255 256 static List<Member> addMembers( 257 SchemaReader schemaReader, 258 List<Member> members, 259 Hierarchy hierarchy) { 260 Level[] levels = schemaReader.getHierarchyLevels(hierarchy); 262 for (int i = 0; i < levels.length; i++) { 263 addMembers(schemaReader, members, levels[i]); 264 } 265 return members; 266 } 267 268 static List<Member> addMembers( 269 SchemaReader schemaReader, 270 List<Member> members, 271 Level level) { 272 Member[] levelMembers = schemaReader.getLevelMembers(level, true); 273 addAll(members, levelMembers); 274 return members; 275 } 276 277 281 static void removeCalculatedMembers(List<Member> memberList) 282 { 283 for (int i = 0; i < memberList.size(); i++) { 284 Member member = (Member) memberList.get(i); 285 if (member.isCalculated()) { 286 memberList.remove(i); 287 --i; 288 } 289 } 290 } 291 292 297 static boolean isAncestorOf(Member m0, Member m1, boolean strict) { 298 if (strict) { 299 if (m1 == null) { 300 return false; 301 } 302 m1 = m1.getParentMember(); 303 } 304 while (m1 != null) { 305 if (m1 == m0) { 306 return true; 307 } 308 m1 = m1.getParentMember(); 309 } 310 return false; 311 } 312 313 329 static Map<Member, Object > evaluateMembers( 330 Evaluator evaluator, 331 Calc exp, 332 List<Member> members, 333 boolean parentsToo) { 334 evaluator= evaluator.push(); 336 337 assert exp.getType() instanceof ScalarType; 338 Map<Member, Object > mapMemberToValue = new HashMap<Member, Object >(); 339 for (int i = 0, count = members.size(); i < count; i++) { 340 Member member = members.get(i); 341 while (true) { 342 evaluator.setContext(member); 343 Object result = exp.evaluate(evaluator); 344 if (result == null) { 345 result = Util.nullValue; 346 } 347 mapMemberToValue.put(member, result); 348 if (!parentsToo) { 349 break; 350 } 351 member = member.getParentMember(); 352 if (member == null) { 353 break; 354 } 355 if (mapMemberToValue.containsKey(member)) { 356 break; 357 } 358 } 359 } 360 return mapMemberToValue; 361 } 362 363 374 static Map<Object , Object > evaluateTuples( 375 Evaluator evaluator, 376 Calc exp, 377 List<Member[]> members) { 378 evaluator= evaluator.push(); 380 381 assert exp.getType() instanceof ScalarType; 382 Map<Object , Object > mapMemberToValue = new HashMap<Object , Object >(); 383 for (int i = 0, count = members.size(); i < count; i++) { 384 Member[] tuples = members.get(i); 385 evaluator.setContext(tuples); 386 Object result = exp.evaluate(evaluator); 387 if (result == null) { 388 result = Util.nullValue; 389 } 390 mapMemberToValue.put(new ArrayHolder<Member>(tuples), result); 391 } 392 return mapMemberToValue; 393 } 394 395 static Map<Member, Object > evaluateMembers( 396 Evaluator evaluator, 397 List<Member> members, 398 boolean parentsToo) { 399 Map<Member, Object > mapMemberToValue = new HashMap<Member, Object >(); 400 for (int i = 0, count = members.size(); i < count; i++) { 401 Member member = members.get(i); 402 while (true) { 403 evaluator.setContext(member); 404 Object result = evaluator.evaluateCurrent(); 405 mapMemberToValue.put(member, result); 406 if (!parentsToo) { 407 break; 408 } 409 member = member.getParentMember(); 410 if (member == null) { 411 break; 412 } 413 if (mapMemberToValue.containsKey(member)) { 414 break; 415 } 416 } 417 } 418 return mapMemberToValue; 419 } 420 421 426 static void sortMembers( 427 Evaluator evaluator, 428 List<Member> members, 429 Calc exp, 430 boolean desc, 431 boolean brk) { 432 if (members.isEmpty()) { 433 return; 434 } 435 Object first = members.get(0); 436 Comparator comparator; 437 Map<Member, Object > mapMemberToValue; 438 if (first instanceof Member) { 439 final boolean parentsToo = !brk; 440 mapMemberToValue = evaluateMembers(evaluator, exp, members, parentsToo); 441 if (brk) { 442 comparator = new BreakMemberComparator(mapMemberToValue, desc); 443 } else { 444 comparator = new HierarchicalMemberComparator(mapMemberToValue, desc); 445 } 446 } else { 447 Util.assertTrue(first instanceof Member[]); 448 final int arity = ((Member[]) first).length; 449 if (brk) { 450 comparator = new BreakArrayComparator(evaluator, exp, arity); 451 if (desc) { 452 comparator = new ReverseComparator(comparator); 453 } 454 } else { 455 comparator = new HierarchicalArrayComparator(evaluator, exp, arity, desc); 456 } 457 } 458 Collections.sort(members, comparator); 459 if (debug) { 460 final PrintWriter pw = new PrintWriter (System.out); 461 for (int i = 0; i < members.size(); i++) { 462 Object o = members.get(i); 463 pw.print(i); 464 pw.print(": "); 465 if (mapMemberToValue != null) { 466 pw.print(mapMemberToValue.get(o)); 467 pw.print(": "); 468 } 469 pw.println(o); 470 } 471 pw.flush(); 472 } 473 } 474 475 480 static void sortTuples( 481 Evaluator evaluator, 482 List<Member[]> tuples, 483 Calc exp, 484 boolean desc, 485 boolean brk, 486 int arity) 487 { 488 if (tuples.isEmpty()) { 489 return; 490 } 491 Comparator comparator; 492 if (brk) { 493 comparator = new BreakArrayComparator(evaluator, exp, arity); 494 if (desc) { 495 comparator = new ReverseComparator(comparator); 496 } 497 } else { 498 comparator = new HierarchicalArrayComparator(evaluator, exp, arity, desc); 499 } 500 Collections.sort(tuples, comparator); 501 if (debug) { 502 final PrintWriter pw = new PrintWriter (System.out); 503 for (int i = 0; i < tuples.size(); i++) { 504 Object o = tuples.get(i); 505 pw.print(i); 506 pw.print(": "); 507 pw.println(o); 508 } 509 pw.flush(); 510 } 511 } 512 513 public static void hierarchize(List members, boolean post) { 514 if (members.isEmpty()) { 515 return; 516 } 517 Object first = members.get(0); 518 Comparator comparator; 519 if (first instanceof Member) { 520 comparator = new HierarchizeComparator(post); 521 } else { 522 Util.assertTrue(first instanceof Member[]); 523 final int arity = ((Member[]) first).length; 524 comparator = new HierarchizeArrayComparator(arity, post); 525 } 526 Collections.sort(members, comparator); 527 } 528 529 static int sign(double d) { 530 return (d == 0) 531 ? 0 532 : (d < 0) 533 ? -1 534 : 1; 535 } 536 537 547 static int compareValues(double d1, double d2) { 548 if (Double.isNaN(d1)) { 549 if (d2 == Double.POSITIVE_INFINITY) { 550 return -1; 551 } else if (Double.isNaN(d2)) { 552 return 0; 553 } else { 554 return 1; 555 } 556 } else if (Double.isNaN(d2)) { 557 if (d1 == Double.POSITIVE_INFINITY) { 558 return 1; 559 } else { 560 return -1; 561 } 562 } else if (d1 == d2) { 563 return 0; 564 } else if (d1 == FunUtil.DoubleNull) { 565 if (d2 == Double.NEGATIVE_INFINITY) { 566 return 1; 567 } else { 568 return -1; 569 } 570 } else if (d2 == FunUtil.DoubleNull) { 571 if (d1 == Double.NEGATIVE_INFINITY) { 572 return -1; 573 } else { 574 return 1; 575 } 576 } else if (d1 < d2) { 577 return -1; 578 } else { 579 return 1; 580 } 581 } 582 583 static int compareValues(int i, int j) { 584 return (i == j) 585 ? 0 586 : (i < j) 587 ? -1 588 : 1; 589 } 590 591 603 static int compareValues(Object value0, Object value1) { 604 if (value0 == value1) { 605 return 0; 606 } 607 if (value0 == null) { 609 return -1; 610 } 611 if (value1 == null) { 612 return 1; 613 } 614 if (value0 instanceof RuntimeException || 615 value1 instanceof RuntimeException ) { 616 return 0; 618 } else if (value0 == Util.nullValue) { 619 return -1; } else if (value1 == Util.nullValue) { 621 return 1; } else if (value0 instanceof String ) { 623 return ((String ) value0).compareTo((String ) value1); 624 } else if (value0 instanceof Number ) { 625 return FunUtil.compareValues( 626 ((Number ) value0).doubleValue(), 627 ((Number ) value1).doubleValue()); 628 } else { 629 throw Util.newInternal("cannot compare " + value0); 630 } 631 } 632 633 638 static void toPercent(List members, Map mapMemberToValue, boolean isMember) { 639 double total = 0; 640 int memberCount = members.size(); 641 for (int i = 0; i < memberCount; i++) { 642 Object o = (isMember) 643 ? mapMemberToValue.get(members.get(i)) 644 : mapMemberToValue.get( 645 new ArrayHolder<Member>((Member []) members.get(i))); 646 if (o instanceof Number ) { 647 total += ((Number ) o).doubleValue(); 648 } 649 } 650 for (int i = 0; i < memberCount; i++) { 651 Object mo = members.get(i); 652 Object o = (isMember) ? 653 mapMemberToValue.get(mo) : 654 mapMemberToValue.get(new ArrayHolder<Member>((Member []) mo)); 655 if (o instanceof Number ) { 656 double d = ((Number ) o).doubleValue(); 657 if (isMember) { 658 mapMemberToValue.put( 659 mo, 660 d / total * (double) 100); 661 } else { 662 mapMemberToValue.put( 663 new ArrayHolder<Member>((Member []) mo), 664 d / total * (double) 100); 665 } 666 } 667 } 668 } 669 670 671 680 public static Syntax decodeSyntacticType(String flags) { 681 char c = flags.charAt(0); 682 switch (c) { 683 case 'p': 684 return Syntax.Property; 685 case 'f': 686 return Syntax.Function; 687 case 'm': 688 return Syntax.Method; 689 case 'i': 690 return Syntax.Infix; 691 case 'P': 692 return Syntax.Prefix; 693 case 'Q': 694 return Syntax.Postfix; 695 case 'I': 696 return Syntax.Internal; 697 default: 698 throw newInternal( 699 "unknown syntax code '" + c + "' in string '" + flags + "'"); 700 } 701 } 702 703 717 public static int decodeReturnCategory(String flags) { 718 final int returnCategory = decodeCategory(flags, 1); 719 if ((returnCategory & Category.Mask) != returnCategory) { 720 throw newInternal("bad return code flag in flags '" + flags + "'"); 721 } 722 return returnCategory; 723 } 724 725 766 public static int decodeCategory(String flags, int offset) { 767 char c = flags.charAt(offset); 768 switch (c) { 769 case 'a': 770 return Category.Array; 771 case 'd': 772 return Category.Dimension; 773 case 'h': 774 return Category.Hierarchy; 775 case 'l': 776 return Category.Level; 777 case 'b': 778 return Category.Logical; 779 case 'm': 780 return Category.Member; 781 case 'N': 782 return Category.Numeric | Category.Constant; 783 case 'n': 784 return Category.Numeric; 785 case 'I': 786 return Category.Numeric | Category.Integer | Category.Constant; 787 case 'i': 788 return Category.Numeric | Category.Integer; 789 case 'x': 790 return Category.Set; 791 case '#': 792 return Category.String | Category.Constant; 793 case 'S': 794 return Category.String; 795 case 't': 796 return Category.Tuple; 797 case 'v': 798 return Category.Value; 799 case 'y': 800 return Category.Symbol; 801 case 'U': 802 return Category.Null; 803 default: 804 throw newInternal( 805 "unknown type code '" + c + "' in string '" + flags + "'"); 806 } 807 } 808 809 822 public static int[] decodeParameterCategories(String flags) { 823 int[] parameterCategories = new int[flags.length() - 2]; 824 for (int i = 0; i < parameterCategories.length; i++) { 825 parameterCategories[i] = decodeCategory(flags, i + 2); 826 } 827 return parameterCategories; 828 } 829 830 833 public static void sortValuesDesc(Object [] values) { 834 Arrays.sort(values, DescendingValueComparator.instance); 835 } 836 837 840 public static int searchValuesDesc(Object [] values, Object value) { 841 return Arrays.binarySearch( 842 values, value, DescendingValueComparator.instance); 843 } 844 845 static Object median(Evaluator evaluator, List members, Calc exp) { 846 SetWrapper sw = evaluateSet(evaluator, members, exp); 847 if (sw.errorCount > 0) { 848 return new Double (Double.NaN); 849 } else if (sw.v.size() == 0) { 850 return Util.nullValue; 851 } 852 double[] asArray = new double[sw.v.size()]; 853 for (int i = 0; i < asArray.length; i++) { 854 asArray[i] = ((Double ) sw.v.get(i)).doubleValue(); 855 } 856 Arrays.sort(asArray); 857 858 867 int length = asArray.length; 868 Double result = ((length & 1) == 1) 869 ? new Double (asArray[length >> 1]) 872 : new Double ((asArray[(length >> 1) - 1] + asArray[length >> 1]) / 2.0); 873 874 return result; 875 } 876 877 888 protected static double quartile( 889 Evaluator evaluator, 890 List members, 891 Calc exp, 892 int range) { 893 Util.assertPrecondition(range >= 1 && range <= 3, "range >= 1 && range <= 3"); 894 895 SetWrapper sw = evaluateSet(evaluator, members, exp); 896 if (sw.errorCount > 0) { 897 return Double.NaN; 898 } else if (sw.v.size() == 0) { 899 return DoubleNull; 900 } 901 902 double[] asArray = new double[sw.v.size()]; 903 for (int i = 0; i < asArray.length; i++) { 904 asArray[i] = ((Double ) sw.v.get(i)).doubleValue(); 905 } 906 907 Arrays.sort(asArray); 908 double dm = (asArray.length * range) / 4; 910 int median = (int) Math.floor(dm); 911 return dm == median && median < asArray.length - 1 ? 912 (asArray[median] + asArray[median + 1]) / 2 : 913 asArray[median]; 914 } 915 916 public static Object min(Evaluator evaluator, List members, Calc calc) { 917 SetWrapper sw = evaluateSet(evaluator, members, calc); 918 if (sw.errorCount > 0) { 919 return new Double (Double.NaN); 920 } else if (sw.v.size() == 0) { 921 return Util.nullValue; 922 } else { 923 double min = Double.MAX_VALUE; 924 for (int i = 0; i < sw.v.size(); i++) { 925 double iValue = ((Double ) sw.v.get(i)).doubleValue(); 926 if (iValue < min) { 927 min = iValue; 928 } 929 } 930 return new Double (min); 931 } 932 } 933 934 public static Object max(Evaluator evaluator, List members, Calc exp) { 935 SetWrapper sw = evaluateSet(evaluator, members, exp); 936 if (sw.errorCount > 0) { 937 return new Double (Double.NaN); 938 } else if (sw.v.size() == 0) { 939 return Util.nullValue; 940 } else { 941 double max = Double.MIN_VALUE; 942 for (int i = 0; i < sw.v.size(); i++) { 943 double iValue = ((Double ) sw.v.get(i)).doubleValue(); 944 if (iValue > max) { 945 max = iValue; 946 } 947 } 948 return new Double (max); 949 } 950 } 951 952 static Object var( 953 Evaluator evaluator, 954 List members, 955 Calc exp, 956 boolean biased) { 957 SetWrapper sw = evaluateSet(evaluator, members, exp); 958 return _var(sw, biased); 959 } 960 961 private static Object _var(SetWrapper sw, boolean biased) { 962 if (sw.errorCount > 0) { 963 return new Double (Double.NaN); 964 } else if (sw.v.size() == 0) { 965 return Util.nullValue; 966 } else { 967 double stdev = 0.0; 968 double avg = _avg(sw); 969 for (int i = 0; i < sw.v.size(); i++) { 970 stdev += Math.pow((((Double ) sw.v.get(i)).doubleValue() - avg),2); 971 } 972 int n = sw.v.size(); 973 if (!biased) { 974 n--; 975 } 976 return new Double (stdev / (double) n); 977 } 978 } 979 980 static double correlation( 981 Evaluator evaluator, 982 List memberList, 983 Calc exp1, 984 Calc exp2) { 985 SetWrapper sw1 = evaluateSet(evaluator, memberList, exp1); 986 SetWrapper sw2 = evaluateSet(evaluator, memberList, exp2); 987 Object covar = _covariance(sw1, sw2, false); 988 Object var1 = _var(sw1, false); Object var2 = _var(sw2, false); 990 if ((covar instanceof Double ) && 991 (var1 instanceof Double ) && 992 (var2 instanceof Double )) { 993 return ((Double ) covar).doubleValue() / 994 Math.sqrt(((Double ) var1).doubleValue() * 995 ((Double ) var2).doubleValue()); 996 } else { 997 return DoubleNull; 998 } 999 } 1000 1001 static Object covariance(Evaluator evaluator, List members, 1002 Calc exp1, Calc exp2, boolean biased) { 1003 SetWrapper sw1 = evaluateSet(evaluator.push(), members, exp1); 1004 SetWrapper sw2 = evaluateSet(evaluator.push(), members, exp2); 1005 return _covariance(sw1, sw2, biased); 1008 } 1009 1010 1011 private static Object _covariance(SetWrapper sw1, 1012 SetWrapper sw2, 1013 boolean biased) { 1014 if (sw1.v.size() != sw2.v.size()) { 1015 return Util.nullValue; 1016 } 1017 double avg1 = _avg(sw1); 1018 double avg2 = _avg(sw2); 1019 double covar = 0.0; 1020 for (int i = 0; i < sw1.v.size(); i++) { 1021 double diff1 = (((Double ) sw1.v.get(i)).doubleValue() - avg1); 1024 double diff2 = (((Double ) sw2.v.get(i)).doubleValue() - avg2); 1025 covar += (diff1 * diff2); 1026 } 1027 int n = sw1.v.size(); 1028 if (!biased) { 1029 n--; 1030 } 1031 return new Double (covar / (double) n); 1032 } 1033 1034 static Object stdev( 1035 Evaluator evaluator, 1036 List members, 1037 Calc exp, 1038 boolean biased) { 1039 Object o = var(evaluator, members, exp, biased); 1040 return (o instanceof Double ) 1041 ? new Double (Math.sqrt(((Double ) o).doubleValue())) 1042 : o; 1043 } 1044 1045 public static Object avg(Evaluator evaluator, List members, Calc calc) { 1046 SetWrapper sw = evaluateSet(evaluator, members, calc); 1047 return (sw.errorCount > 0) ? 1048 new Double (Double.NaN) : 1049 (sw.v.size() == 0) ? 1050 Util.nullValue : 1051 new Double (_avg(sw)); 1052 } 1053 1054 private static double _avg(SetWrapper sw) { 1057 double sum = 0.0; 1058 for (int i = 0; i < sw.v.size(); i++) { 1059 sum += ((Double ) sw.v.get(i)).doubleValue(); 1060 } 1061 return sum / (double) sw.v.size(); 1063 } 1064 1065 public static Object sum(Evaluator evaluator, List members, Calc exp) { 1066 double d = sumDouble(evaluator, members, exp); 1067 return d == DoubleNull ? Util.nullValue : new Double (d); 1068 } 1069 1070 public static double sumDouble(Evaluator evaluator, List members, Calc exp) { 1071 SetWrapper sw = evaluateSet(evaluator, members, exp); 1072 if (sw.errorCount > 0) { 1073 return Double.NaN; 1074 } else if (sw.v.size() == 0) { 1075 return DoubleNull; 1076 } else { 1077 double sum = 0.0; 1078 for (int i = 0; i < sw.v.size(); i++) { 1079 sum += ((Double ) sw.v.get(i)).doubleValue(); 1080 } 1081 return sum; 1082 } 1083 } 1084 public static double sumDouble(Evaluator evaluator, Iterable iterable, Calc exp) { 1085 SetWrapper sw = evaluateSet(evaluator, iterable, exp); 1086 if (sw.errorCount > 0) { 1087 return Double.NaN; 1088 } else if (sw.v.size() == 0) { 1089 return DoubleNull; 1090 } else { 1091 double sum = 0.0; 1092 for (int i = 0; i < sw.v.size(); i++) { 1093 sum += ((Double ) sw.v.get(i)).doubleValue(); 1094 } 1095 return sum; 1096 } 1097 } 1098 public static int count( 1099 Evaluator evaluator, 1100 Iterable iterable, 1101 boolean includeEmpty) { 1102 if (iterable == null) { 1103 return 0; 1104 } 1105 if (includeEmpty) { 1106 if (iterable instanceof Collection) { 1107 return ((Collection) iterable).size(); 1108 } else { 1109 int retval = 0; 1110 Iterator it = iterable.iterator(); 1111 while (it.hasNext()) { 1112 it.next(); 1114 retval++; 1115 } 1116 return retval; 1117 } 1118 } else { 1119 int retval = 0; 1120 for (Object object: iterable) { 1121 if (object instanceof Member) { 1122 evaluator.setContext((Member) object); 1123 } else { 1124 evaluator.setContext((Member[]) object); 1125 } 1126 Object o = evaluator.evaluateCurrent(); 1127 if (o != Util.nullValue && o != null) { 1128 retval++; 1129 } 1130 } 1131 return retval; 1132 } 1133 } 1134 1135 1195 1196 1204 static SetWrapper evaluateSet( 1205 Evaluator evaluator, 1206 Iterable members, 1207 Calc calc) { 1208 Util.assertPrecondition(members != null, "members != null"); 1209 Util.assertPrecondition(calc != null, "calc != null"); 1210 Util.assertPrecondition(calc.getType() instanceof ScalarType); 1211 1212 SetWrapper retval = new SetWrapper(); 1214 for (Iterator it = members.iterator(); it.hasNext();) { 1215 Object obj = it.next(); 1216 if (obj instanceof Member[]) { 1217 evaluator.setContext((Member[])obj); 1218 } else { 1219 evaluator.setContext((Member)obj); 1220 } 1221 Object o = calc.evaluate(evaluator); 1222 if (o == null || o == Util.nullValue) { 1223 retval.nullCount++; 1224 } else if (o instanceof Throwable ) { 1225 retval.errorCount++; 1229 } else if (o instanceof Double ) { 1230 retval.v.add(o); 1231 } else if (o instanceof Number ) { 1232 retval.v.add(((Number ) o).doubleValue()); 1233 } else { 1234 retval.v.add(o); 1235 } 1236 } 1237 return retval; 1238 } 1239 1240 1252 static SetWrapper[] evaluateSet( 1253 Evaluator evaluator, 1254 List members, 1255 DoubleCalc[] calcs, 1256 boolean isTuples) { 1257 Util.assertPrecondition(calcs != null, "calcs != null"); 1258 1259 SetWrapper[] retvals = new SetWrapper[calcs.length]; 1261 for (int i = 0; i < calcs.length; i++) { 1262 retvals[i] = new SetWrapper(); 1263 } 1264 for (int j = 0; j < members.size(); j++) { 1265 if (isTuples) { 1266 evaluator.setContext((Member[]) members.get(j)); 1267 } else { 1268 evaluator.setContext((Member) members.get(j)); 1269 } 1270 for (int i = 0; i < calcs.length; i++) { 1271 DoubleCalc calc = calcs[i]; 1272 SetWrapper retval = retvals[i]; 1273 double o = calc.evaluateDouble(evaluator); 1274 if (o == FunUtil.DoubleNull) { 1275 retval.nullCount++; 1276 retval.v.add(null); 1277 } else { 1278 retval.v.add(o); 1279 } 1280 } 1285 } 1286 return retvals; 1287 } 1288 1289 static List<Member> periodsToDate( 1290 Evaluator evaluator, 1291 Level level, 1292 Member member) { 1293 if (member == null) { 1294 member = evaluator.getContext(level.getHierarchy().getDimension()); 1295 } 1296 Member m = member; 1297 while (m != null) { 1298 if (m.getLevel() == level) { 1299 break; 1300 } 1301 m = m.getParentMember(); 1302 } 1303 List<Member> members = new ArrayList<Member>(); 1307 if (m != null) { 1308 SchemaReader reader = evaluator.getSchemaReader(); 1312 m = Util.getFirstDescendantOnLevel(reader, m, member.getLevel()); 1313 reader.getMemberRange(level, m, member, members); 1314 } 1315 return members; 1316 } 1317 1318 static List<Member> memberRange( 1319 Evaluator evaluator, 1320 Member startMember, 1321 Member endMember) 1322 { 1323 final Level level = startMember.getLevel(); 1324 assertTrue(level == endMember.getLevel()); 1325 List<Member> members = new ArrayList<Member>(); 1326 evaluator.getSchemaReader().getMemberRange( 1327 level, startMember, endMember, members); 1328 1329 if (members.isEmpty()) { 1330 evaluator.getSchemaReader().getMemberRange( 1333 level, endMember, startMember, members); 1334 } 1335 return members; 1336 } 1337 1338 1348 static Member cousin(SchemaReader schemaReader, 1349 Member member, 1350 Member ancestorMember) { 1351 if (ancestorMember.isNull()) { 1352 return ancestorMember; 1353 } 1354 if (member.getHierarchy() != ancestorMember.getHierarchy()) { 1355 throw MondrianResource.instance().CousinHierarchyMismatch.ex( 1356 member.getUniqueName(), ancestorMember.getUniqueName()); 1357 } 1358 if (member.getLevel().getDepth() < ancestorMember.getLevel().getDepth()) { 1359 return member.getHierarchy().getNullMember(); 1360 } 1361 1362 Member cousin = cousin2(schemaReader, member, ancestorMember); 1363 if (cousin == null) { 1364 cousin = member.getHierarchy().getNullMember(); 1365 } 1366 1367 return cousin; 1368 } 1369 1370 static private Member cousin2(SchemaReader schemaReader, 1371 Member member1, 1372 Member member2) { 1373 if (member1.getLevel() == member2.getLevel()) { 1374 return member2; 1375 } 1376 Member uncle = cousin2(schemaReader, member1.getParentMember(), member2); 1377 if (uncle == null) { 1378 return null; 1379 } 1380 int ordinal = Util.getMemberOrdinalInParent(schemaReader, member1); 1381 Member[] cousins = schemaReader.getMemberChildren(uncle); 1382 if (cousins.length <= ordinal) { 1383 return null; 1384 } 1385 return cousins[ordinal]; 1386 } 1387 1388 1407 static Member ancestor(Evaluator evaluator, 1408 Member member, 1409 int distance, 1410 Level targetLevel) { 1411 if ((targetLevel != null) && 1412 (member.getHierarchy() != targetLevel.getHierarchy())) { 1413 throw MondrianResource.instance().MemberNotInLevelHierarchy.ex( 1414 member.getUniqueName(), targetLevel.getUniqueName()); 1415 } 1416 1417 if (distance == 0) { 1418 1421 return member; 1422 } else if (distance < 0) { 1423 1426 return member.getHierarchy().getNullMember(); 1427 } 1428 1429 Member[] ancestors = member.getAncestorMembers(); 1430 final SchemaReader schemaReader = evaluator.getSchemaReader(); 1431 1432 Member result = member.getHierarchy().getNullMember(); 1433 1434 searchLoop: 1435 for (int i = 0; i < ancestors.length; i++) { 1436 final Member ancestorMember = ancestors[i]; 1437 1438 if (targetLevel != null) { 1439 if (ancestorMember.getLevel() == targetLevel) { 1440 if (schemaReader.isVisible(ancestorMember)) { 1441 result = ancestorMember; 1442 break searchLoop; 1443 } else { 1444 result = member.getHierarchy().getNullMember(); 1445 break searchLoop; 1446 } 1447 } 1448 } else { 1449 if (schemaReader.isVisible(ancestorMember)) { 1450 distance--; 1451 1452 if (distance == 0) { 1467 if (targetLevel == null || ancestorMember.getLevel() == targetLevel) { 1468 result = ancestorMember; 1469 break searchLoop; 1470 } else { 1471 result = member.getHierarchy().getNullMember(); 1472 break searchLoop; 1473 } 1474 } 1475 } 1476 } 1477 } 1478 1479 return result; 1480 } 1481 1482 1496 public static int compareHierarchically( 1497 Member m1, 1498 Member m2, 1499 boolean post) { 1500 if (equals(m1, m2)) { 1501 return 0; 1502 } 1503 while (true) { 1504 int depth1 = m1.getDepth(); 1505 int depth2 = m2.getDepth(); 1506 if (depth1 < depth2) { 1507 m2 = m2.getParentMember(); 1508 if (equals(m1, m2)) { 1509 return post ? 1 : -1; 1510 } 1511 } else if (depth1 > depth2) { 1512 m1 = m1.getParentMember(); 1513 if (equals(m1, m2)) { 1514 return post ? -1 : 1; 1515 } 1516 } else { 1517 Member prev1 = m1; 1518 Member prev2 = m2; 1519 m1 = m1.getParentMember(); 1520 m2 = m2.getParentMember(); 1521 if (equals(m1, m2)) { 1522 return compareSiblingMembers(prev1, prev2); 1523 } 1524 } 1525 } 1526 } 1527 1528 1546 public static int compareSiblingMembers(Member m1, Member m2) { 1547 final boolean calculated1 = m1.isCalculatedInQuery(); 1549 final boolean calculated2 = m2.isCalculatedInQuery(); 1550 if (calculated1) { 1551 if (!calculated2) { 1552 return 1; 1553 } 1554 } else { 1555 if (calculated2) { 1556 return -1; 1557 } 1558 } 1559 final Comparable k1 = m1.getOrderKey(); 1560 final Comparable k2 = m2.getOrderKey(); 1561 if ((k1 != null) && (k2 != null)) { 1562 return k1.compareTo(k2); 1563 } else { 1564 final int ordinal1 = m1.getOrdinal(); 1565 final int ordinal2 = m2.getOrdinal(); 1566 return (ordinal1 == ordinal2) ? 1567 m1.compareTo(m2) : 1568 (ordinal1 < ordinal2) ? 1569 -1 : 1570 1; 1571 } 1572 } 1573 1574 1582 public static boolean canConvert( 1583 Exp fromExp, 1584 int to, 1585 int[] conversionCount) { 1586 int from = fromExp.getCategory(); 1587 if (from == to) { 1588 return true; 1589 } 1590 switch (from) { 1591 case Category.Array: 1592 return false; 1593 case Category.Dimension: 1594 switch (to) { 1599 case Category.Member: 1600 case Category.Tuple: 1601 conversionCount[0]++; 1604 return true; 1605 case Category.Hierarchy: 1606 case Category.Level: 1607 conversionCount[0] += 2; 1608 return true; 1609 default: 1610 return false; 1611 } 1612 case Category.Hierarchy: 1613 switch (to) { 1614 case Category.Dimension: 1615 case Category.Member: 1616 case Category.Tuple: 1617 conversionCount[0]++; 1618 return true; 1619 default: 1620 return false; 1621 } 1622 case Category.Level: 1623 switch (to) { 1624 case Category.Dimension: 1625 conversionCount[0] += 2; 1630 return true; 1631 case Category.Hierarchy: 1632 conversionCount[0]++; 1633 return true; 1634 default: 1635 return false; 1636 } 1637 case Category.Logical: 1638 return false; 1639 case Category.Member: 1640 switch (to) { 1641 case Category.Dimension: 1642 case Category.Hierarchy: 1643 case Category.Level: 1644 case Category.Tuple: 1645 conversionCount[0]++; 1646 return true; 1647 case (Category.Numeric | Category.Expression): 1648 conversionCount[0]++; 1652 return true; 1653 case Category.Value: 1654 case (Category.String | Category.Expression): 1655 conversionCount[0] += 2; 1656 return true; 1657 default: 1658 return false; 1659 } 1660 case Category.Numeric | Category.Constant: 1661 return to == Category.Value || 1662 to == Category.Numeric; 1663 case Category.Numeric: 1664 return to == Category.Value || 1665 to == Category.Integer || 1666 to == (Category.Integer | Category.Constant) || 1667 to == (Category.Numeric | Category.Constant); 1668 case Category.Integer: 1669 return to == Category.Value || 1670 to == (Category.Integer | Category.Constant) || 1671 to == Category.Numeric || 1672 to == (Category.Numeric | Category.Constant); 1673 case Category.Set: 1674 return false; 1675 case Category.String | Category.Constant: 1676 return to == Category.Value || 1677 to == Category.String; 1678 case Category.String: 1679 return to == Category.Value || 1680 to == (Category.String | Category.Constant); 1681 case Category.Tuple: 1682 return to == Category.Value || 1683 to == Category.Numeric; 1684 case Category.Value: 1685 return false; 1686 case Category.Symbol: 1687 return false; 1688 case Category.Null: 1689 return to == Category.Numeric || to == Category.Member; 1691 default: 1692 throw newInternal("unknown category " + from); 1693 } 1694 } 1695 1696 1699 static boolean tupleContainsNullMember(Member[] tuple) { 1700 for (int i = 0; i < tuple.length; i++) { 1701 Member member = tuple[i]; 1702 if (member.isNull()) { 1703 return true; 1704 } 1705 } 1706 return false; 1707 } 1708 1709 public static Member[] makeNullTuple(final TupleType tupleType) { 1710 Member[] members = new Member[tupleType.elementTypes.length]; 1711 for (int i = 0; i < tupleType.elementTypes.length; i++) { 1712 MemberType type = (MemberType) tupleType.elementTypes[i]; 1713 members[i] = makeNullMember(type); 1714 } 1715 return members; 1716 } 1717 1718 static Member makeNullMember( 1719 MemberType memberType) { 1720 Hierarchy hierarchy = memberType.getHierarchy(); 1721 if (hierarchy == null) { 1722 return NullMember; 1723 } 1724 return hierarchy.getNullMember(); 1725 } 1726 1727 1739 public static FunDef resolveFunArgs( 1740 Validator validator, Exp[] args, Exp[] newArgs, String name, 1741 Syntax syntax) { 1742 1743 Query query = validator.getQuery(); 1744 Cube cube = null; 1745 if (query != null) { 1746 cube = query.getCube(); 1747 } 1748 for (int i = 0; i < args.length; i++) { 1749 newArgs[i] = validator.validate(args[i], false); 1750 } 1751 final FunTable funTable = validator.getFunTable(); 1752 FunDef funDef = funTable.getDef(newArgs, validator, name, syntax); 1753 1754 if (!(funDef instanceof SetFunDef) && query != null && 1770 query.nativeCrossJoinVirtualCube()) 1771 { 1772 int[] paramCategories = funDef.getParameterCategories(); 1773 if (paramCategories.length > 0 && 1774 ((paramCategories[0] == Category.Dimension && 1775 newArgs[0] instanceof DimensionExpr && 1776 ((DimensionExpr) newArgs[0]).getDimension(). 1777 getOrdinal(cube) == 0) || 1778 (paramCategories[0] == Category.Member && 1779 newArgs[0] instanceof MemberExpr && 1780 ((MemberExpr) newArgs[0]).getMember().getDimension(). 1781 getOrdinal(cube) == 0 && 1782 (funDef.getReturnCategory() == Category.Member || 1783 funDef.getReturnCategory() == Category.Set)))) 1784 { 1785 query.setVirtualCubeNonNativeCrossJoin(); 1786 } 1787 } 1788 1789 return funDef; 1790 } 1791 1792 static void appendTuple(StringBuilder buf, Member[] members) { 1793 buf.append("("); 1794 for (int j = 0; j < members.length; j++) { 1795 if (j > 0) { 1796 buf.append(", "); 1797 } 1798 Member member = members[j]; 1799 buf.append(member.getUniqueName()); 1800 } 1801 buf.append(")"); 1802 } 1803 1804 1813 static boolean equalTuple(Member[] members0, Member[] members1) { 1814 final int count = members0.length; 1815 if (count != members1.length) { 1816 return false; 1817 } 1818 outer: 1819 for (int i = 0; i < count; i++) { 1820 final Member member0 = members0[i]; 1823 if (member0.equals(members1[i])) { 1824 continue; 1825 } 1826 for (int j = 0; j < count; j++) { 1830 if (i != j && member0.equals(members1[j])) { 1831 continue outer; 1832 } 1833 } 1834 return false; 1837 } 1838 return true; 1839 } 1840 1841 static FunDef createDummyFunDef( 1842 Resolver resolver, 1843 int returnCategory, 1844 Exp[] args) 1845 { 1846 final int[] argCategories = ExpBase.getTypes(args); 1847 return new FunDefBase(resolver, returnCategory, argCategories) {}; 1848 } 1849 1850 1852 1853 private static abstract class MemberComparator implements Comparator { 1854 private static final Logger LOGGER = 1855 Logger.getLogger(MemberComparator.class); 1856 Map<Member, Object > mapMemberToValue; 1857 private boolean desc; 1858 1859 MemberComparator(Map<Member, Object > mapMemberToValue, boolean desc) { 1860 this.mapMemberToValue = mapMemberToValue; 1861 this.desc = desc; 1862 } 1863 1864 public int compare(Object o1, Object o2) { 1866 Member m1 = (Member) o1, 1867 m2 = (Member) o2; 1868 int c = compareInternal(m1, m2); 1869 if (LOGGER.isDebugEnabled()) { 1870 LOGGER.debug( 1871 "compare " + 1872 m1.getUniqueName() + 1873 "(" + mapMemberToValue.get(m1) + "), " + 1874 m2.getUniqueName() + 1875 "(" + mapMemberToValue.get(m2) + ")" + 1876 " yields " + c); 1877 } 1878 return c; 1879 } 1880 1881 protected abstract int compareInternal(Member m1, Member m2); 1882 1883 protected int compareByValue(Member m1, Member m2) { 1884 Object value1 = mapMemberToValue.get(m1), 1885 value2 = mapMemberToValue.get(m2); 1886 final int c = FunUtil.compareValues(value1, value2); 1887 return desc ? -c : c; 1888 } 1889 1890 protected int compareHierarchicallyButSiblingsByValue(Member m1, Member m2) { 1891 if (FunUtil.equals(m1, m2)) { 1892 return 0; 1893 } 1894 while (true) { 1895 int depth1 = m1.getDepth(), 1896 depth2 = m2.getDepth(); 1897 if (depth1 < depth2) { 1898 m2 = m2.getParentMember(); 1899 if (Util.equals(m1, m2)) { 1900 return -1; 1901 } 1902 } else if (depth1 > depth2) { 1903 m1 = m1.getParentMember(); 1904 if (Util.equals(m1, m2)) { 1905 return 1; 1906 } 1907 } else { 1908 Member prev1 = m1, prev2 = m2; 1909 m1 = m1.getParentMember(); 1910 m2 = m2.getParentMember(); 1911 if (Util.equals(m1, m2)) { 1912 int c = compareByValue(prev1, prev2); 1914 if (c != 0) { 1915 return c; 1916 } 1917 c = FunUtil.compareSiblingMembers(prev1, prev2); 1922 return c; 1923 } 1924 } 1925 } 1926 } 1927 } 1928 1929 private static class HierarchicalMemberComparator 1930 extends MemberComparator { 1931 HierarchicalMemberComparator(Map<Member, Object > mapMemberToValue, boolean desc) { 1932 super(mapMemberToValue, desc); 1933 } 1934 1935 protected int compareInternal(Member m1, Member m2) { 1936 return compareHierarchicallyButSiblingsByValue(m1, m2); 1937 } 1938 } 1939 1940 private static class BreakMemberComparator extends MemberComparator { 1941 BreakMemberComparator(Map<Member, Object > mapMemberToValue, boolean desc) { 1942 super(mapMemberToValue, desc); 1943 } 1944 1945 protected int compareInternal(Member m1, Member m2) { 1946 return compareByValue(m1, m2); 1947 } 1948 } 1949 1950 1953 private static abstract class ArrayComparator implements Comparator { 1954 private static final Logger LOGGER = 1955 Logger.getLogger(ArrayComparator.class); 1956 int arity; 1957 1958 ArrayComparator(int arity) { 1959 this.arity = arity; 1960 } 1961 1962 private static String toString(Member[] a) { 1963 StringBuilder sb = new StringBuilder (); 1964 for (int i = 0; i < a.length; i++) { 1965 Member member = a[i]; 1966 if (i > 0) { 1967 sb.append(","); 1968 } 1969 sb.append(member.getUniqueName()); 1970 } 1971 return sb.toString(); 1972 } 1973 1974 public int compare(Object o1, Object o2) { 1975 final Member[] a1 = (Member[]) o1; 1976 final Member[] a2 = (Member[]) o2; 1977 final int c = compare(a1, a2); 1978 if (LOGGER.isDebugEnabled()) { 1979 LOGGER.debug( 1980 "compare {" + toString(a1)+ "}, {" + toString(a2) + 1981 "} yields " + c); 1982 } 1983 return c; 1984 } 1985 1986 protected abstract int compare(Member[] a1, Member[] a2); 1987 } 1988 1989 1993 private static abstract class ArrayExpComparator 1994 extends ArrayComparator { 1995 Evaluator evaluator; 1996 final Calc calc; 1997 1998 ArrayExpComparator(Evaluator evaluator, Calc calc, int arity) { 1999 super(arity); 2000 this.evaluator = evaluator; 2001 this.calc = calc; 2002 } 2003 2004 } 2005 2006 private static class HierarchicalArrayComparator 2007 extends ArrayExpComparator { 2008 private final boolean desc; 2009 2010 HierarchicalArrayComparator( 2011 Evaluator evaluator, Calc calc, int arity, boolean desc) { 2012 super(evaluator, calc, arity); 2013 this.desc = desc; 2014 } 2015 2016 protected int compare(Member[] a1, Member[] a2) { 2017 int c = 0; 2018 evaluator = evaluator.push(); 2019 for (int i = 0; i < arity; i++) { 2020 Member m1 = a1[i], 2021 m2 = a2[i]; 2022 c = compareHierarchicallyButSiblingsByValue(m1, m2); 2023 if (c != 0) { 2024 break; 2025 } 2026 Util.assertTrue(m1.equals(m2)); 2029 evaluator.setContext(m1); 2030 } 2031 evaluator = evaluator.pop(); 2032 return c; 2033 } 2034 2035 protected int compareHierarchicallyButSiblingsByValue( 2036 Member m1, Member m2) { 2037 if (FunUtil.equals(m1, m2)) { 2038 return 0; 2039 } 2040 while (true) { 2041 int depth1 = m1.getDepth(), 2042 depth2 = m2.getDepth(); 2043 if (depth1 < depth2) { 2044 m2 = m2.getParentMember(); 2045 if (FunUtil.equals(m1, m2)) { 2046 return -1; 2047 } 2048 } else if (depth1 > depth2) { 2049 m1 = m1.getParentMember(); 2050 if (FunUtil.equals(m1, m2)) { 2051 return 1; 2052 } 2053 } else { 2054 Member prev1 = m1, prev2 = m2; 2055 m1 = m1.getParentMember(); 2056 m2 = m2.getParentMember(); 2057 if (FunUtil.equals(m1, m2)) { 2058 int c = compareByValue(prev1, prev2); 2060 if (c == 0) { 2061 c = FunUtil.compareSiblingMembers(prev1, prev2); 2062 } 2063 return desc ? -c : c; 2064 } 2065 } 2066 } 2067 } 2068 private int compareByValue(Member m1, Member m2) { 2069 int c; 2070 Member old = evaluator.setContext(m1); 2071 Object v1 = calc.evaluate(evaluator); 2072 evaluator.setContext(m2); 2073 Object v2 = calc.evaluate(evaluator); 2074 evaluator.setContext(old); 2077 c = FunUtil.compareValues(v1, v2); 2078 return c; 2079 } 2080 } 2081 2082 private static class BreakArrayComparator extends ArrayExpComparator { 2083 BreakArrayComparator(Evaluator evaluator, Calc calc, int arity) { 2084 super(evaluator, calc, arity); 2085 } 2086 2087 protected int compare(Member[] a1, Member[] a2) { 2088 evaluator.setContext(a1); 2089 Object v1 = calc.evaluate(evaluator); 2090 evaluator.setContext(a2); 2091 Object v2 = calc.evaluate(evaluator); 2092 return FunUtil.compareValues(v1, v2); 2093 } 2094 } 2095 2096 2100 private static class HierarchizeArrayComparator extends ArrayComparator { 2101 private final boolean post; 2102 2103 HierarchizeArrayComparator(int arity, boolean post) { 2104 super(arity); 2105 this.post = post; 2106 } 2107 2108 protected int compare(Member[] a1, Member[] a2) { 2109 for (int i = 0; i < arity; i++) { 2110 Member m1 = a1[i], 2111 m2 = a2[i]; 2112 int c = FunUtil.compareHierarchically(m1, m2, post); 2113 if (c != 0) { 2114 return c; 2115 } 2116 Util.assertTrue(m1.equals(m2)); 2119 } 2120 return 0; 2121 } 2122 } 2123 2124 2128 private static class HierarchizeComparator implements Comparator { 2129 private final boolean post; 2130 2131 HierarchizeComparator(boolean post) { 2132 this.post = post; 2133 } 2134 public int compare(Object o1, Object o2) { 2135 return FunUtil.compareHierarchically((Member) o1, (Member) o2, post); 2136 } 2137 } 2138 2139 2142 private static class ReverseComparator implements Comparator { 2143 Comparator comparator; 2144 ReverseComparator(Comparator comparator) { 2145 this.comparator = comparator; 2146 } 2147 2148 public int compare(Object o1, Object o2) { 2149 int c = comparator.compare(o1, o2); 2150 return -c; 2151 } 2152 } 2153 2154 static class SetWrapper { 2155 List v = new ArrayList(); 2156 public int errorCount = 0, nullCount = 0; 2157 2158 } 2174 2175 2182 private static class DescendingValueComparator implements Comparator { 2183 2186 static final DescendingValueComparator instance = 2187 new DescendingValueComparator(); 2188 2189 public int compare(Object o1, Object o2) { 2190 return - compareValues(o1, o2); 2191 } 2192 } 2193 2194 2197 private static class NullMember implements Member { 2198 public Member getParentMember() { 2199 throw new UnsupportedOperationException (); 2200 } 2201 2202 public Level getLevel() { 2203 throw new UnsupportedOperationException (); 2204 } 2205 2206 public Hierarchy getHierarchy() { 2207 throw new UnsupportedOperationException (); 2208 } 2209 2210 public String getParentUniqueName() { 2211 throw new UnsupportedOperationException (); 2212 } 2213 2214 public MemberType getMemberType() { 2215 throw new UnsupportedOperationException (); 2216 } 2217 2218 public void setName(String name) { 2219 throw new UnsupportedOperationException (); 2220 } 2221 2222 public boolean isAll() { 2223 return false; 2224 } 2225 2226 public boolean isMeasure() { 2227 throw new UnsupportedOperationException (); 2228 } 2229 2230 public boolean isNull() { 2231 return true; 2232 } 2233 2234 public boolean isChildOrEqualTo(Member member) { 2235 throw new UnsupportedOperationException (); 2236 } 2237 2238 public boolean isCalculated() { 2239 throw new UnsupportedOperationException (); 2240 } 2241 2242 public int getSolveOrder() { 2243 throw new UnsupportedOperationException (); 2244 } 2245 2246 public Exp getExpression() { 2247 throw new UnsupportedOperationException (); 2248 } 2249 2250 public Member[] getAncestorMembers() { 2251 throw new UnsupportedOperationException (); 2252 } 2253 2254 public boolean isCalculatedInQuery() { 2255 throw new UnsupportedOperationException (); 2256 } 2257 2258 public Object getPropertyValue(String propertyName) { 2259 throw new UnsupportedOperationException (); 2260 } 2261 2262 public Object getPropertyValue(String propertyName, boolean matchCase) { 2263 throw new UnsupportedOperationException (); 2264 } 2265 2266 public String getPropertyFormattedValue(String propertyName) { 2267 throw new UnsupportedOperationException (); 2268 } 2269 2270 public void setProperty(String name, Object value) { 2271 throw new UnsupportedOperationException (); 2272 } 2273 2274 public Property[] getProperties() { 2275 throw new UnsupportedOperationException (); 2276 } 2277 2278 public int getOrdinal() { 2279 throw new UnsupportedOperationException (); 2280 } 2281 2282 public Comparable getOrderKey() { 2283 throw new UnsupportedOperationException (); 2284 } 2285 2286 public boolean isHidden() { 2287 throw new UnsupportedOperationException (); 2288 } 2289 2290 public int getDepth() { 2291 throw new UnsupportedOperationException (); 2292 } 2293 2294 public Member getDataMember() { 2295 throw new UnsupportedOperationException (); 2296 } 2297 2298 public String getUniqueName() { 2299 throw new UnsupportedOperationException (); 2300 } 2301 2302 public String getName() { 2303 throw new UnsupportedOperationException (); 2304 } 2305 2306 public String getDescription() { 2307 throw new UnsupportedOperationException (); 2308 } 2309 2310 public OlapElement lookupChild(SchemaReader schemaReader, String s) { 2311 throw new UnsupportedOperationException (); 2312 } 2313 2314 public OlapElement lookupChild( 2315 SchemaReader schemaReader, String s, MatchType matchType) { 2316 throw new UnsupportedOperationException (); 2317 } 2318 2319 public String getQualifiedName() { 2320 throw new UnsupportedOperationException (); 2321 } 2322 2323 public String getCaption() { 2324 throw new UnsupportedOperationException (); 2325 } 2326 2327 public Dimension getDimension() { 2328 throw new UnsupportedOperationException (); 2329 } 2330 2331 public int compareTo(Object o) { 2332 throw new UnsupportedOperationException (); 2333 } 2334 } 2335 2336 public static void main(String [] args) { 2337 System.out.println("done"); 2338 } 2339} 2340 2341 | Popular Tags |