1 15 package org.josql.functions; 16 17 import java.util.List ; 18 import java.util.ArrayList ; 19 import java.util.Collections ; 20 import java.util.Map ; 21 import java.util.HashMap ; 22 import java.util.Iterator ; 23 24 import com.gentlyweb.utils.Getter; 25 26 import org.josql.QueryExecutionException; 27 28 import org.josql.internal.Utilities; 29 30 import org.josql.expressions.Expression; 31 32 import org.josql.Query; 33 34 public class GroupingFunctions extends AbstractFunctionHandler 35 { 36 37 public static final String VALUE = "value"; 38 39 public static final String HANDLER_ID = "_internal_grouping"; 40 41 public Object least (List allobjs, 42 Expression exp, 43 String saveValueName) 44 throws QueryExecutionException 45 { 46 47 if (saveValueName != null) 48 { 49 50 Object o = this.q.getSaveValue (saveValueName); 51 52 if (o != null) 53 { 54 55 return o; 56 57 } 58 59 } 60 61 if (allobjs.size () == 0) 62 { 63 64 return null; 65 66 } 67 68 Object g = null; 69 70 int s = allobjs.size (); 71 72 for (int i = 0; i < s; i++) 73 { 74 75 Object o = allobjs.get (i); 76 77 Object v = null; 78 79 try 80 { 81 82 v = exp.getValue (o, 83 this.q); 84 85 } catch (Exception e) { 86 87 throw new QueryExecutionException ("Unable to get value from expression: " + 88 exp + 89 " for maximum value" + 90 e); 91 92 } 93 94 if (g == null) 95 { 96 97 g = v; 98 99 } else { 100 101 int c = Utilities.compare (v, 102 g); 103 104 if (c < 0) 105 { 106 107 g = v; 108 109 } 110 111 } 112 113 } 114 115 if ((saveValueName != null) 116 && 117 (q != null) 118 ) 119 { 120 121 q.setSaveValue (saveValueName, 122 g); 123 124 } 125 126 return g; 127 128 } 129 130 public Object minObject (Expression exp) 131 throws QueryExecutionException 132 { 133 134 return this.minObject ((List ) this.q.getVariable (Query.ALL_OBJS_VAR_NAME), 135 exp); 136 137 } 138 139 public Object minObject (List allobjs, 140 Expression exp) 141 throws QueryExecutionException 142 { 143 144 return this.leastObject (allobjs, 145 exp); 146 147 } 148 149 public Object leastObject (List allobjs, 150 Expression exp) 151 throws QueryExecutionException 152 { 153 154 if (allobjs.size () == 0) 155 { 156 157 return null; 158 159 } 160 161 Object l = null; 162 Object lo = null; 163 164 int s = allobjs.size (); 165 166 for (int i = 0; i < s; i++) 167 { 168 169 Object o = allobjs.get (i); 170 171 Object v = null; 172 173 try 174 { 175 176 v = exp.getValue (o, 177 this.q); 178 179 } catch (Exception e) { 180 181 throw new QueryExecutionException ("Unable to get value from expression: " + 182 exp + 183 " for maximum value" + 184 e); 185 186 } 187 188 if (l == null) 189 { 190 191 l = v; 192 lo = o; 193 194 } else { 195 196 int c = Utilities.compare (v, 197 l); 198 199 if (c < 0) 200 { 201 202 l = v; 203 lo = o; 204 205 } 206 207 } 208 209 } 210 211 return lo; 212 213 } 214 215 public Object maxObject (List allobjs, 216 Expression exp) 217 throws QueryExecutionException 218 { 219 220 return this.greatestObject (allobjs, 221 exp); 222 223 } 224 225 public Object maxObject (Expression exp) 226 throws QueryExecutionException 227 { 228 229 return this.maxObject ((List ) this.q.getVariable (Query.ALL_OBJS_VAR_NAME), 230 exp); 231 232 } 233 234 public Object greatestObject (List allobjs, 235 Expression exp) 236 throws QueryExecutionException 237 { 238 239 if (allobjs.size () == 0) 240 { 241 242 return null; 243 244 } 245 246 Object g = null; 247 Object go = null; 248 249 int s = allobjs.size (); 250 251 for (int i = 0; i < s; i++) 252 { 253 254 Object o = allobjs.get (i); 255 256 Object v = null; 257 258 try 259 { 260 261 v = exp.getValue (o, 262 this.q); 263 264 } catch (Exception e) { 265 266 throw new QueryExecutionException ("Unable to get value from expression: " + 267 exp + 268 " for maximum value" + 269 e); 270 271 } 272 273 if (g == null) 274 { 275 276 g = v; 277 go = o; 278 279 } else { 280 281 int c = Utilities.compare (v, 282 g); 283 284 if (c > 0) 285 { 286 287 g = v; 288 go = o; 289 290 } 291 292 } 293 294 } 295 296 return go; 297 298 } 299 300 public Object least (List allobjs, 301 Expression exp) 302 throws QueryExecutionException 303 { 304 305 return this.least (allobjs, 306 exp, 307 null); 308 309 } 310 311 public Object min (Expression exp) 312 throws QueryExecutionException 313 { 314 315 return this.min ((List ) this.q.getVariable (Query.ALL_OBJS_VAR_NAME), 316 exp); 317 318 } 319 320 public Object min (List allobjs, 321 Expression exp) 322 throws QueryExecutionException 323 { 324 325 return this.least (allobjs, 326 exp, 327 null); 328 329 } 330 331 public Object min (List allobjs, 332 Expression exp, 333 String saveValueName) 334 throws QueryExecutionException 335 { 336 337 return this.least (allobjs, 338 exp, 339 saveValueName); 340 341 } 342 343 public Map.Entry maxEntry (Map m, 344 String type) 345 { 346 347 int t = 0; 348 349 if (type.equals (GroupingFunctions.VALUE)) 350 { 351 352 t = 1; 353 354 } 355 356 Map.Entry r = null; 357 Map.Entry le = null; 358 359 Iterator iter = m.entrySet ().iterator (); 360 361 while (iter.hasNext ()) 362 { 363 364 r = (Map.Entry ) iter.next (); 365 366 if (le != null) 367 { 368 369 if (t == 0) 370 { 371 372 if (Utilities.isGTEquals (r.getKey (), 373 le.getKey ())) 374 { 375 376 le = r; 377 378 } 379 380 } else { 381 382 if (Utilities.isGTEquals (r.getValue (), 383 le.getValue ())) 384 { 385 386 le = r; 387 388 } 389 390 } 391 392 } else { 393 394 le = r; 395 396 } 397 398 } 399 400 return le; 401 402 } 403 404 public Map.Entry minEntry (Object m, 405 String type) 406 throws QueryExecutionException 407 { 408 409 if (!(m instanceof Map )) 410 { 411 412 throw new QueryExecutionException ("Only instances of: " + 413 Map .class.getName () + 414 " are supported, passed: " + 415 m.getClass ().getName ()); 416 417 } 418 419 return this.minEntry ((Map ) m, 420 type); 421 422 } 423 424 public Map.Entry minEntry (Map m, 425 String type) 426 { 427 428 int t = 0; 429 430 if (type.equals (GroupingFunctions.VALUE)) 431 { 432 433 t = 1; 434 435 } 436 437 Map.Entry r = null; 438 Map.Entry le = null; 439 440 Iterator iter = m.entrySet ().iterator (); 441 442 while (iter.hasNext ()) 443 { 444 445 r = (Map.Entry ) iter.next (); 446 447 if (le != null) 448 { 449 450 if (t == 0) 451 { 452 453 if (Utilities.isLTEquals (r.getKey (), 454 le.getKey ())) 455 { 456 457 le = r; 458 459 } 460 461 } else { 462 463 if (Utilities.isLTEquals (r.getValue (), 464 le.getValue ())) 465 { 466 467 le = r; 468 469 } 470 471 } 472 473 } else { 474 475 le = r; 476 477 } 478 479 } 480 481 return le; 482 483 } 484 485 public Object max (List allobjs, 486 Expression exp, 487 String saveValueName) 488 throws QueryExecutionException 489 { 490 491 return this.greatest (allobjs, 492 exp, 493 saveValueName); 494 495 } 496 497 public Object greatest (List allobjs, 498 Expression exp, 499 String saveValueName) 500 throws QueryExecutionException 501 { 502 503 if (saveValueName != null) 504 { 505 506 Object o = this.q.getSaveValue (saveValueName); 507 508 if (o != null) 509 { 510 511 return (Double ) o; 512 513 } 514 515 } 516 517 if (allobjs.size () == 0) 518 { 519 520 return null; 521 522 } 523 524 Object g = null; 525 526 int s = allobjs.size (); 527 528 for (int i = 0; i < s; i++) 529 { 530 531 Object o = allobjs.get (i); 532 533 Object v = null; 534 535 try 536 { 537 538 v = exp.getValue (o, 539 this.q); 540 541 } catch (Exception e) { 542 543 throw new QueryExecutionException ("Unable to get value from expression: " + 544 exp + 545 " for maximum value" + 546 e); 547 548 } 549 550 if (g == null) 551 { 552 553 g = v; 554 555 } else { 556 557 int c = Utilities.compare (v, 558 g); 559 560 if (c > 0) 561 { 562 563 g = v; 564 565 } 566 567 } 568 569 } 570 571 if (saveValueName != null) 572 { 573 574 this.q.setSaveValue (saveValueName, 575 g); 576 577 } 578 579 return g; 580 581 } 582 583 public Object greatest (List allobjs, 584 Expression exp) 585 throws QueryExecutionException 586 { 587 588 return this.greatest (allobjs, 589 exp, 590 null); 591 592 } 593 594 public Object max (Expression exp) 595 throws QueryExecutionException 596 { 597 598 return this.max ((List ) this.q.getVariable (Query.ALL_OBJS_VAR_NAME), 599 exp); 600 601 } 602 603 public Object max (List allobjs, 604 Expression exp) 605 throws QueryExecutionException 606 { 607 608 return this.greatest (allobjs, 609 exp, 610 null); 611 612 } 613 614 private double getTotal (List allobjs, 615 Expression exp) 616 throws QueryExecutionException 617 { 618 619 Object currObj = this.q.getCurrentObject (); 620 621 double total = 0; 622 623 int size = allobjs.size (); 624 625 for (int i = 0; i < size; i++) 626 { 627 628 Object o = allobjs.get (i); 629 630 this.q.setCurrentObject (o); 631 632 Number n = null; 633 634 try 635 { 636 637 n = (Number ) exp.getValue (o, 638 this.q); 639 640 } catch (Exception e) { 641 642 throw new QueryExecutionException ("Unable to get value from expression: " + 643 exp + 644 " for item: " + 645 i + 646 " from the list of objects.", 647 e); 648 649 } 650 651 total += n.doubleValue (); 652 653 } 654 655 this.q.setCurrentObject (currObj); 656 657 return total; 658 659 } 660 661 public void checkType (Object o, 662 Class expected, 663 Expression exp) 664 throws QueryExecutionException 665 { 666 667 if (!expected.isInstance (o)) 668 { 669 670 throw new QueryExecutionException ("Expression: " + 671 exp + 672 " returns type: " + 673 o.getClass ().getName () + 674 " however must return instance of: " + 675 expected.getName ()); 676 677 } 678 679 } 680 681 public Double sum (List allobjs, 682 Expression exp, 683 String saveValueName) 684 throws QueryExecutionException 685 { 686 687 if (saveValueName != null) 688 { 689 690 Object o = this.q.getSaveValue (saveValueName); 691 692 if (o != null) 693 { 694 695 return (Double ) o; 696 697 } 698 699 } 700 701 if ((allobjs == null) 702 || 703 (allobjs.size () == 0) 704 ) 705 { 706 707 return new Double (0); 708 709 } 710 711 double total = this.getTotal (allobjs, 712 exp); 713 714 Double d = new Double (total); 715 716 if ((saveValueName != null) 717 && 718 (q != null) 719 ) 720 { 721 722 this.q.setSaveValue (saveValueName, 723 d); 724 725 } 726 727 return d; 728 729 } 730 731 public Double sum (Expression exp) 732 throws QueryExecutionException 733 { 734 735 return this.sum ((List ) this.q.getVariable (Query.ALL_OBJS_VAR_NAME), 736 exp); 737 738 } 739 740 public Double sum (List objs, 741 Expression exp) 742 throws QueryExecutionException 743 { 744 745 Class c = null; 746 747 try 748 { 749 750 c = exp.getExpectedReturnType (this.q); 751 752 } catch (Exception e) { 753 754 throw new QueryExecutionException ("Unable to determine expected return type for expression: " + 755 exp, 756 e); 757 758 } 759 760 boolean dyn = false; 761 762 if (!c.getName ().equals (Object .class.getName ())) 763 { 764 765 if (!Utilities.isNumber (c)) 767 { 768 769 throw new QueryExecutionException ("This function expects the expression: " + 770 exp + 771 " to return a number (sub-class of: " + 772 Number .class.getName () + 773 ") but evaluation of the expression will return an instance of: " + 774 c.getName ()); 775 776 } 777 778 } else { 779 780 dyn = true; 781 782 } 783 784 Object co = this.q.getCurrentObject (); 785 786 int s = objs.size () - 1; 787 788 double d = 0; 789 790 for (int i = s; i > -1; i--) 791 { 792 793 Object o = objs.get (i); 794 795 this.q.setCurrentObject (o); 796 797 Object v = null; 798 799 try 800 { 801 802 v = exp.getValue (o, 803 this.q); 804 805 } catch (Exception e) { 806 807 throw new QueryExecutionException ("Unable to evaluate expression: " + 808 exp + 809 " on item: " + 810 i, 811 e); 812 813 } 814 815 if (v == null) 816 { 817 818 continue; 820 821 } 822 823 if (dyn) 824 { 825 826 if (!(Utilities.isNumber (v))) 827 { 828 829 throw new QueryExecutionException ("Expected expression: " + 830 exp + 831 " to return a number (sub-class of: " + 832 Number .class.getName () + 833 ") but returns instance of: " + 834 o.getClass ().getName () + 835 " for item: " + 836 i + 837 " (class: " + 838 v.getClass ().getName () + 839 ")"); 840 841 } 842 843 } 844 845 d += ((Number ) v).doubleValue (); 846 847 } 848 849 this.q.setCurrentObject (co); 850 851 return new Double (d); 852 853 } 854 855 866 public Double sum (List objs, 867 String acc) 868 throws QueryExecutionException 869 { 870 871 if ((objs == null) 872 || 873 (objs.size () == 0) 874 ) 875 { 876 877 return new Double (0); 878 879 } 880 881 Object o = objs.get (0); 883 884 Getter get = null; 885 886 try 887 { 888 889 get = new Getter (acc, 890 o.getClass ()); 891 892 } catch (Exception e) { 893 894 throw new QueryExecutionException ("Unable to create accessor for: " + 895 acc + 896 " with class: " + 897 o.getClass ().getName (), 898 e); 899 900 } 901 902 if (!get.getType ().getName ().equals (Object .class.getName ())) 903 { 904 905 if (!Utilities.isNumber (get.getType ())) 907 { 908 909 throw new QueryExecutionException ("This function expects the accessor (second parm): " + 910 acc + 911 " to return a number (sub-class of: " + 912 Number .class.getName () + 913 ") but evaluation of the accessor will return an instance of: " + 914 get.getType ().getName ()); 915 916 } 917 918 } 919 920 int s = objs.size () - 1; 921 922 double d = 0; 923 924 for (int i = s; i > -1; i--) 925 { 926 927 o = objs.get (i); 928 929 Object v = null; 930 931 try 932 { 933 934 v = get.getValue (o); 935 936 } catch (Exception e) { 937 938 throw new QueryExecutionException ("Unable to evaluate accessor: " + 939 acc + 940 " on item: " + 941 i, 942 e); 943 944 } 945 946 if (v == null) 947 { 948 949 continue; 951 952 } 953 954 d += ((Number ) v).doubleValue (); 955 956 } 957 958 return new Double (d); 959 960 } 961 962 public String concat (List allobjs, 963 Expression exp, 964 String sep, 965 String saveValueName) 966 throws QueryExecutionException 967 { 968 969 if (saveValueName != null) 970 { 971 972 Object o = this.q.getSaveValue (saveValueName); 973 974 if (o != null) 975 { 976 977 return (String ) o; 978 979 } 980 981 } 982 983 StringBuffer buf = new StringBuffer (); 984 985 int size = allobjs.size (); 986 int size1 = size - 1; 987 988 for (int i = 0; i < size; i++) 989 { 990 991 Object o = allobjs.get (i); 992 993 Object v = null; 994 995 try 996 { 997 998 v = exp.getValue (o, 999 this.q); 1000 1001 } catch (Exception e) { 1002 1003 throw new QueryExecutionException ("Unable to get value from expression: " + 1004 exp + 1005 " for item: " + 1006 i + 1007 " from the list of objects.", 1008 e); 1009 1010 } 1011 1012 buf.append (v); 1013 1014 if ((sep != null) 1015 && 1016 (i < size1) 1017 ) 1018 { 1019 1020 buf.append (sep); 1021 1022 } 1023 1024 } 1025 1026 String r = buf.toString (); 1027 1028 if ((saveValueName != null) 1029 && 1030 (q != null) 1031 ) 1032 { 1033 1034 q.setSaveValue (saveValueName, 1035 r); 1036 1037 } 1038 1039 return r; 1040 1041 } 1042 1043 public String concat (List allobjs, 1044 Expression exp, 1045 String sep) 1046 throws QueryExecutionException 1047 { 1048 1049 return this.concat (allobjs, 1050 exp, 1051 sep, 1052 null); 1053 1054 } 1055 1056 public String concat (Expression exp) 1057 throws QueryExecutionException 1058 { 1059 1060 return this.concat ((List ) this.q.getVariable (Query.ALL_OBJS_VAR_NAME), 1061 exp); 1062 1063 } 1064 1065 public String concat (List allobjs, 1066 Expression exp) 1067 throws QueryExecutionException 1068 { 1069 1070 return this.concat (allobjs, 1071 exp, 1072 null, 1073 null); 1074 1075 } 1076 1077 public Double avg (List allobjs, 1078 Expression exp, 1079 String saveValueName) 1080 throws QueryExecutionException 1081 { 1082 1083 if (saveValueName != null) 1084 { 1085 1086 Object o = this.q.getSaveValue (saveValueName); 1087 1088 if (o != null) 1089 { 1090 1091 return (Double ) o; 1092 1093 } 1094 1095 } 1096 1097 if ((allobjs == null) 1098 || 1099 (allobjs.size () == 0) 1100 ) 1101 { 1102 1103 return new Double (0); 1104 1105 } 1106 1107 double total = this.getTotal (allobjs, 1108 exp); 1109 1110 double avg = total / allobjs.size (); 1111 1112 Double d = new Double (avg); 1113 1114 if (saveValueName != null) 1115 { 1116 1117 q.setSaveValue (saveValueName, 1118 d); 1119 1120 } 1121 1122 return d; 1123 1124 } 1125 1126 public Double avg (Expression exp) 1127 throws QueryExecutionException 1128 { 1129 1130 return this.avg ((List ) this.q.getVariable (Query.ALL_OBJS_VAR_NAME), 1131 exp); 1132 1133 } 1134 1135 public Double avg (List allobjs, 1136 Expression exp) 1137 throws QueryExecutionException 1138 { 1139 1140 return this.avg (allobjs, 1141 exp, 1142 null); 1143 1144 } 1145 1146 1154 public Map occurrence (List objs) 1155 throws QueryExecutionException 1156 { 1157 1158 return this.occurrence (objs, 1159 null); 1160 1161 } 1162 1163 1173 1174 1184 public Map occurrence (List objs, 1185 Expression exp) 1186 throws QueryExecutionException 1187 { 1188 1189 Map occs = new HashMap (); 1190 1191 if (objs == null) 1192 { 1193 1194 return occs; 1195 1196 } 1197 1198 int s = objs.size (); 1199 1200 for (int i = 0; i < s; i++) 1201 { 1202 1203 Object o = objs.get (i); 1204 1205 if (exp != null) 1206 { 1207 1208 try 1209 { 1210 1211 o = exp.getValue (o, 1212 this.q); 1213 1214 } catch (Exception e) { 1215 1216 throw new QueryExecutionException ("Unable to get value for expression: " + 1217 exp + 1218 " for object: " + 1219 i + 1220 " from the list of objects.", 1221 e); 1222 1223 } 1224 1225 } 1226 1227 Integer c = (Integer ) occs.get (o); 1228 1229 int co = 1; 1230 1231 if (c != null) 1232 { 1233 1234 co = c.intValue (); 1235 1236 co++; 1237 1238 } 1239 1240 occs.put (o, 1241 new Integer (co)); 1242 1243 } 1244 1245 return occs; 1246 1247 } 1248 1249 1265 public Map occurrence (List objs, 1266 Expression exp, 1267 Expression limitExp) 1268 throws QueryExecutionException 1269 { 1270 1271 Map rs = this.occurrence (objs, 1272 exp); 1273 1274 Object o = limitExp.getValue (this.q.getCurrentObject (), 1276 this.q); 1277 1278 if (!(o instanceof Number )) 1279 { 1280 1281 throw new QueryExecutionException ("Limit expression: " + 1282 limitExp + 1283 " does not evaluate to a number"); 1284 1285 } 1286 1287 int i = ((Number ) o).intValue (); 1288 1289 Map ret = new HashMap (); 1290 1291 Iterator iter = rs.keySet ().iterator (); 1292 1293 while (iter.hasNext ()) 1294 { 1295 1296 Object k = iter.next (); 1297 1298 Integer c = (Integer ) rs.get (k); 1299 1300 if (c.intValue () >= i) 1301 { 1302 1303 ret.put (k, 1304 c); 1305 1306 } 1307 1308 } 1309 1310 return ret; 1311 1312 } 1313 1314} 1315 | Popular Tags |