1 10 11 package org.mmbase.bridge.util; 12 import java.util.*; 13 14 import org.mmbase.bridge.*; 15 import org.mmbase.bridge.implementation.BasicQuery; 16 import org.mmbase.module.core.ClusterBuilder; 17 import org.mmbase.module.core.MMBase; 18 import org.mmbase.storage.search.*; 19 import org.mmbase.storage.search.legacy.ConstraintParser; 20 import org.mmbase.util.*; 21 import org.mmbase.util.logging.*; 22 23 33 abstract public class Queries { 34 35 public static final int OPERATOR_BETWEEN = -1; public static final int OPERATOR_IN = 10000; public static final int OPERATOR_NULL = 10001; 39 private static final Logger log = Logging.getLoggerInstance(Queries.class); 40 41 48 public static int getRelationStepDirection(String search) { 49 if (search == null) { 50 return RelationStep.DIRECTIONS_BOTH; 51 } 52 search = search.toUpperCase(); 53 if ("DESTINATION".equals(search)) { 54 return RelationStep.DIRECTIONS_DESTINATION; 55 } else if ("SOURCE".equals(search)) { 56 return RelationStep.DIRECTIONS_SOURCE; 57 } else if ("BOTH".equals(search)) { 58 return RelationStep.DIRECTIONS_BOTH; 59 } else if ("ALL".equals(search)) { 60 return RelationStep.DIRECTIONS_ALL; 61 } else if ("EITHER".equals(search)) { 62 return RelationStep.DIRECTIONS_EITHER; 63 } else { 64 throw new BridgeException("'" + search + "' cannot be converted to a relation-step direction constant"); 65 } 66 } 67 68 87 public static Query createQuery(Cloud cloud, String startNodes, String nodePath, String fields, String constraints, String orderby, String directions, String searchDir, boolean distinct) { 88 89 if ("".equals(startNodes) || "-1".equals(startNodes)) { 91 startNodes = null; 92 } 93 if ("".equals(fields)) { 94 fields = null; 95 } 96 if ("".equals(constraints)) { 97 constraints = null; 98 } 99 if ("".equals(searchDir)) { 100 searchDir = null; 101 } 102 if ("".equals(orderby)) { 103 orderby = null; 104 } 105 106 if ("".equals(directions)) { 107 directions = null; 108 } 109 Encode encoder = new Encode("ESCAPE_SINGLE_QUOTE"); 111 if (orderby != null) { 115 orderby = encoder.encode(orderby); 116 } 117 if (directions != null) { 118 directions = encoder.encode(directions); 119 } 120 if (searchDir != null) { 121 searchDir = encoder.encode(searchDir); 122 } 123 if (constraints != null) { 124 constraints = ConstraintParser.convertClauseToDBS(constraints); 125 if (! ConstraintParser.validConstraints(constraints)) { 126 throw new BridgeException("invalid constraints:" + constraints); 127 } 128 if (! constraints.substring(0, 5).equalsIgnoreCase("WHERE")) { 129 constraints = "WHERE " + constraints; 131 } 132 } 133 134 135 138 140 ClusterBuilder clusterBuilder = MMBase.getMMBase().getClusterBuilder(); 141 int search = -1; 142 if (searchDir != null) { 143 search = ClusterBuilder.getSearchDir(searchDir); 144 } 145 146 List snodes = StringSplitter.split(startNodes); 147 List tables = StringSplitter.split(nodePath); 148 List f = StringSplitter.split(fields); 149 List orderVec = StringSplitter.split(orderby); 150 List d = StringSplitter.split(directions); 151 try { 152 Query query = new BasicQuery(cloud, clusterBuilder.getMultiLevelSearchQuery(snodes, f, distinct ? "YES" : "NO", tables, constraints, orderVec, d, search)); 156 return query; 157 } catch (IllegalArgumentException iae) { 158 throw new BridgeException(iae.getMessage() + ". (arguments: startNodes='" + startNodes + "', path='" + nodePath + "', fields='" + fields + "', constraints='" + constraints + "' orderby='" + orderby + "', directions='" + directions + "', searchdir='" + searchDir + "')" , iae); 159 } 160 } 161 162 163 171 public static Constraint addConstraints(Query query, String constraints) { 172 if (constraints == null || constraints.equals("")) { 173 return null; 174 } 175 176 Constraint newConstraint = new ConstraintParser(query).toConstraint(constraints); 178 addConstraint(query, newConstraint); 179 return newConstraint; 180 } 181 182 188 public static Constraint addConstraint(Query query, Constraint newConstraint) { 189 if (newConstraint == null) { 190 return null; 191 } 192 193 Constraint constraint = query.getConstraint(); 194 195 if (constraint != null) { 196 log.debug("compositing constraint"); 197 Constraint compConstraint = query.createConstraint(constraint, CompositeConstraint.LOGICAL_AND, newConstraint); 198 query.setConstraint(compConstraint); 199 } else { 200 query.setConstraint(newConstraint); 201 } 202 return newConstraint; 203 } 204 205 212 public static int getOperator(String s) { 213 String op = s.toUpperCase(); 214 if (op.equals("<") || op.equals("LESS")) { 216 return FieldCompareConstraint.LESS; 217 } else if (op.equals("<=") || op.equals("LESS_EQUAL")) { 218 return FieldCompareConstraint.LESS_EQUAL; 219 } else if (op.equals("=") || op.equals("EQUAL") || op.equals("")) { 220 return FieldCompareConstraint.EQUAL; 221 } else if (op.equals("!=") || op.equals("NOT_EQUAL")) { 222 return FieldCompareConstraint.NOT_EQUAL; 223 } else if (op.equals(">") || op.equals("GREATER")) { 224 return FieldCompareConstraint.GREATER; 225 } else if (op.equals(">=") || op.equals("GREATER_EQUAL")) { 226 return FieldCompareConstraint.GREATER_EQUAL; 227 } else if (op.equals("LIKE")) { 228 return FieldCompareConstraint.LIKE; 229 } else if (op.equals("BETWEEN")) { 230 return OPERATOR_BETWEEN; 231 } else if (op.equals("IN")) { 232 return OPERATOR_IN; 233 } else if (op.equals("NULL")) { 234 return OPERATOR_NULL; 235 } else { 238 throw new BridgeException("Unknown Field Compare Operator '" + op + "'"); 239 } 240 } 241 242 248 public static int getDateTimePart(String s) { 249 String sPart = s.toUpperCase(); 250 if (sPart.equals("")) { 251 return -1; 252 } else if (sPart.equals("CENTURY")) { 253 return FieldValueDateConstraint.CENTURY; 254 } else if (sPart.equals("YEAR")) { 255 return FieldValueDateConstraint.YEAR; 256 } else if (sPart.equals("QUARTER")) { 257 return FieldValueDateConstraint.QUARTER; 258 } else if (sPart.equals("MONTH")) { 259 return FieldValueDateConstraint.MONTH; 260 } else if (sPart.equals("WEEK")) { 261 return FieldValueDateConstraint.WEEK; 262 } else if (sPart.equals("DAYOFYEAR")) { 263 return FieldValueDateConstraint.DAY_OF_YEAR; 264 } else if (sPart.equals("DAY") || sPart.equals("DAYOFMONTH")) { 265 return FieldValueDateConstraint.DAY_OF_MONTH; 266 } else if (sPart.equals("DAYOFWEEK")) { 267 return FieldValueDateConstraint.DAY_OF_WEEK; 268 } else if (sPart.equals("HOUR")) { 269 return FieldValueDateConstraint.HOUR; 270 } else if (sPart.equals("MINUTE")) { 271 return FieldValueDateConstraint.MINUTE; 272 } else if (sPart.equals("SECOND")) { 273 return FieldValueDateConstraint.SECOND; 274 } else if (sPart.equals("MILLISECOND")) { 275 return FieldValueDateConstraint.MILLISECOND; 276 } else { 277 throw new BridgeException("Unknown datetime part '" + sPart + "'"); 278 } 279 } 280 281 287 protected static Number getNumberValue(String stringValue) throws BridgeException { 288 if (stringValue == null) return null; 289 try { 290 return new Integer (stringValue); 291 } catch (NumberFormatException e) { 292 try { 293 return new Double (stringValue); 294 } catch (NumberFormatException e2) { 295 throw new BridgeException("Operator requires number value ('" + stringValue + "' is not)"); 296 } 297 } 298 } 299 300 307 protected static Object getCompareValue(int fieldType, int operator, Object value) { 308 return getCompareValue(fieldType, operator, value, -1, null); 309 } 310 311 320 protected static Object getCompareValue(int fieldType, int operator, Object value, int datePart, Cloud cloud) { 321 if (operator == OPERATOR_IN) { 322 SortedSet set; 323 if (value instanceof SortedSet) { 324 set = (SortedSet)value; 325 } else if (value instanceof NodeList) { 326 set = new TreeSet(); 327 NodeIterator i = ((NodeList)value).nodeIterator(); 328 while (i.hasNext()) { 329 Node node = i.nextNode(); 330 set.add(getCompareValue(fieldType, FieldCompareConstraint.EQUAL, new Integer (node.getNumber()))); 331 } 332 } else if (value instanceof Collection) { 333 set = new TreeSet(); 334 Iterator i = ((Collection)value).iterator(); 335 while (i.hasNext()) { 336 Object o = i.next(); 337 set.add(getCompareValue(fieldType, FieldCompareConstraint.EQUAL, o)); 338 } 339 } else { 340 set = new TreeSet(); 341 if (!(value == null || value.equals(""))) { 342 set.add(getCompareValue(fieldType, FieldCompareConstraint.EQUAL, value)); 343 } 344 } 345 return set; 346 } 347 switch(fieldType) { 348 case Field.TYPE_STRING: 349 return value == null ? null : Casting.toString(value); 350 case Field.TYPE_INTEGER: 351 case Field.TYPE_FLOAT: 352 case Field.TYPE_LONG: 353 case Field.TYPE_DOUBLE: 354 case Field.TYPE_NODE: 355 if (value instanceof Number ) { 356 return value; 357 } else { 358 return getNumberValue(value == null ? null : Casting.toString(value)); 359 } 360 case Field.TYPE_DATETIME: 361 if (datePart > -1) { 363 return Casting.toInteger(value); 364 } else { 365 return Casting.toDate(value); 366 } 367 case Field.TYPE_BOOLEAN: 368 return Casting.toBoolean(value) ? Boolean.TRUE : Boolean.FALSE; 369 default: 370 return value; 371 } 372 } 373 374 383 public static Constraint createConstraint(Query query, String fieldName, int operator, Object value) { 384 return createConstraint(query, fieldName, operator, value, null, false, -1); 385 } 386 387 398 public static Constraint createConstraint(Query query, String fieldName, int operator, Object value, Object value2, boolean caseSensitive) { 399 return createConstraint(query, fieldName, operator, value, value2, caseSensitive, -1); 400 } 401 402 416 public static Constraint createConstraint(Query query, String fieldName, int operator, Object value, Object value2, boolean caseSensitive, int datePart) { 417 418 StepField stepField = query.createStepField(fieldName); 419 if (stepField == null) { 420 throw new BridgeException("Could not create stepfield with '" + fieldName + "'"); 421 } 422 423 Cloud cloud = query.getCloud(); 424 FieldConstraint newConstraint; 425 426 if (value instanceof StepField) { 427 newConstraint = query.createConstraint(stepField, operator, (StepField)value); 428 } else if (operator == OPERATOR_NULL || value == null) { 429 newConstraint = query.createConstraint(stepField); 430 } else { 431 Field field = cloud.getNodeManager(stepField.getStep().getTableName()).getField(stepField.getFieldName()); 432 int fieldType = field.getType(); 433 434 if (fieldName.equals("number") || fieldType == Field.TYPE_NODE) { 435 if (value instanceof String ) { if (cloud.hasNode((String ) value)) { 437 Node node = cloud.getNode((String )value); 438 value = new Integer (node.getNumber()); 439 } else { 440 value = new Integer (-1); 441 } 442 } else if (value instanceof Collection) { Iterator i = ((Collection) value).iterator(); 444 value = new ArrayList(); 445 List list = (List) value; 446 while (i.hasNext()) { 447 Object v = i.next(); 448 if (v instanceof Number ) { 449 list.add(v); 450 } else { 451 String s = Casting.toString(v); 452 if (cloud.hasNode(s)) { 453 Node node = cloud.getNode(s); 454 list.add(new Integer (node.getNumber())); 455 } else { 456 list.add(new Integer (-1)); 457 } 458 459 } 460 } 461 462 } 463 } 464 if (operator != OPERATOR_IN) { 466 if (fieldType == Field.TYPE_XML) { 467 value = Casting.toString(value); 470 } else { 471 value = field.getDataType().cast(value, null, field); 472 473 } 474 } 475 Object compareValue = getCompareValue(fieldType, operator, value, datePart, cloud); 476 477 if (operator > 0 && operator < OPERATOR_IN) { 478 if (fieldType == Field.TYPE_DATETIME && datePart> -1) { 479 newConstraint = query.createConstraint(stepField, operator, compareValue, datePart); 480 } else { 481 if (operator == FieldCompareConstraint.EQUAL && compareValue == null) { 482 newConstraint = query.createConstraint(stepField); 483 } else { 484 newConstraint = query.createConstraint(stepField, operator, compareValue); 485 } 486 } 487 } else { 488 if (fieldType == Field.TYPE_DATETIME && datePart> -1) { 489 throw new RuntimeException ("Cannot apply IN or BETWEEN to a partial date field"); 490 } 491 switch (operator) { 492 case OPERATOR_BETWEEN : 493 Object compareValue2 = getCompareValue(fieldType, operator, value2); 494 newConstraint = query.createConstraint(stepField, compareValue, compareValue2); 495 break; 496 case OPERATOR_IN : 497 newConstraint = query.createConstraint(stepField, (SortedSet)compareValue); 498 break; 499 default : 500 throw new RuntimeException ("Unknown value for operation " + operator); 501 } 502 } 503 } 504 query.setCaseSensitive(newConstraint, caseSensitive); 505 return newConstraint; 506 507 } 508 509 526 public static Constraint copyConstraint(Constraint c, Step sourceStep, Query query, Step step) { 527 if (c == null) return null; 528 529 if (c instanceof CompositeConstraint) { 530 CompositeConstraint constraint = (CompositeConstraint) c; 531 List constraints = new ArrayList(); 532 Iterator i = constraint.getChilds().iterator(); 533 while (i.hasNext()) { 534 Constraint cons = copyConstraint((Constraint) i.next(), sourceStep, query, step); 535 if (cons != null) constraints.add(cons); 536 } 537 int size = constraints.size(); 538 if (size == 0) return null; 539 if (size == 1) return (Constraint) constraints.get(0); 540 i = constraints.iterator(); 541 int op = constraint.getLogicalOperator(); 542 Constraint newConstraint = query.createConstraint((Constraint) i.next(), op, (Constraint) i.next()); 543 while (i.hasNext()) { 544 newConstraint = query.createConstraint(newConstraint, op, (Constraint) i.next()); 545 } 546 query.setInverse(newConstraint, constraint.isInverse()); 547 return newConstraint; 548 } else if (c instanceof CompareFieldsConstraint) { 549 throw new UnsupportedOperationException ("Cannot copy comparison between fields"); } 551 552 553 FieldConstraint fieldConstraint = (FieldConstraint) c; 554 if (! fieldConstraint.getField().getStep().equals(sourceStep)) return null; 556 StepField field = query.createStepField(step, fieldConstraint.getField().getFieldName()); 557 558 FieldConstraint newConstraint; 559 if (c instanceof FieldValueConstraint) { 560 newConstraint = query.createConstraint(field, ((FieldValueConstraint) c).getOperator(), ((FieldValueConstraint) c).getValue()); 561 } else if (c instanceof FieldNullConstraint) { 562 newConstraint = query.createConstraint(field); 563 } else if (c instanceof FieldValueBetweenConstraint) { 564 FieldValueBetweenConstraint constraint = (FieldValueBetweenConstraint) c; 565 try { 566 newConstraint = query.createConstraint(field, constraint.getLowerLimit(), constraint.getUpperLimit()); 567 } catch (NumberFormatException e) { 568 newConstraint = query.createConstraint(field, constraint.getLowerLimit(), constraint.getUpperLimit()); 569 } 570 } else if (c instanceof FieldValueInConstraint) { 571 FieldValueInConstraint constraint = (FieldValueInConstraint) c; 572 573 SortedSet set = new TreeSet(); 575 int type = field.getType(); 576 Iterator k = constraint.getValues().iterator(); 577 while (k.hasNext()) { 578 Object value = k.next(); 579 switch(type) { 580 case Field.TYPE_INTEGER: 581 case Field.TYPE_LONG: 582 case Field.TYPE_NODE: 583 value = new Long (Casting.toLong(value)); 584 break; 585 case Field.TYPE_FLOAT: 586 case Field.TYPE_DOUBLE: 587 value = new Double (Casting.toDouble(value)); 588 break; 589 case Field.TYPE_DATETIME: 590 value = new Date((long) 1000 * Integer.parseInt("" + value)); 591 break; 592 default: 593 log.debug("Unknown type " + type); 594 break; 595 } 596 set.add(value); 597 } 598 newConstraint = query.createConstraint(field, set); 599 } else if (c instanceof LegacyConstraint) { 600 throw new UnsupportedOperationException ("Cannot copy legacy constraint to other step"); 601 } else { 602 throw new RuntimeException ("Could not copy constraint " + c); 603 } 604 query.setInverse(newConstraint, fieldConstraint.isInverse()); 605 query.setCaseSensitive(newConstraint, fieldConstraint.isCaseSensitive()); 606 return newConstraint; 607 608 } 609 619 public static void copySortOrders(List sortOrders, Step sourceStep, Query query, Step step) { 620 Iterator i = sortOrders.iterator(); 621 while (i.hasNext()) { 622 SortOrder sortOrder = (SortOrder) i.next(); 623 StepField sourceField = sortOrder.getField(); 624 if (! sourceField.getStep().equals(sourceStep)) continue; query.addSortOrder(query.createStepField(step, sourceField.getFieldName()), sortOrder.getDirection()); 626 } 627 } 628 629 635 public static int getSortOrder(String dir) { 636 dir = dir.toUpperCase(); 637 if (dir.equals("")) { 638 return SortOrder.ORDER_ASCENDING; 639 } else if (dir.equals("DOWN")) { 640 return SortOrder.ORDER_DESCENDING; 641 } else if (dir.equals("UP")) { 642 return SortOrder.ORDER_ASCENDING; 643 } else if (dir.equals("ASCENDING")) { 644 return SortOrder.ORDER_ASCENDING; 645 } else if (dir.equals("DESCENDING")) { 646 return SortOrder.ORDER_DESCENDING; 647 } else { 648 throw new BridgeException("Unknown sort-order '" + dir + "'"); 649 } 650 } 651 652 661 public static List addSortOrders(Query query, String sorted, String directions) { 662 if (sorted == null) { 664 return query.getSortOrders().subList(0, 0); 665 } 666 if (directions == null) { 667 directions = ""; 668 } 669 List list = query.getSortOrders(); 670 int initialSize = list.size(); 671 672 StringTokenizer sortedTokenizer = new StringTokenizer(sorted, ","); 673 StringTokenizer directionsTokenizer = new StringTokenizer(directions, ","); 674 675 while (sortedTokenizer.hasMoreTokens()) { 676 String fieldName = sortedTokenizer.nextToken().trim(); 677 int dot = fieldName.indexOf('.'); 678 679 StepField sf; 680 if (dot == -1 && query instanceof NodeQuery) { 681 NodeManager nodeManager = ((NodeQuery)query).getNodeManager(); 682 sf = ((NodeQuery)query).getStepField(nodeManager.getField(fieldName)); 683 } else { 684 sf = query.createStepField(fieldName); 685 } 686 687 int dir = SortOrder.ORDER_ASCENDING; 688 if (directionsTokenizer.hasMoreTokens()) { 689 String direction = directionsTokenizer.nextToken().trim(); 690 dir = getSortOrder(direction); 691 } 692 query.addSortOrder(sf, dir); 693 } 694 695 return list.subList(initialSize, list.size()); 696 } 697 698 703 protected static String removeDigits(String complete) { 704 int end = complete.length() - 1; 705 while (Character.isDigit(complete.charAt(end))) { 706 --end; 707 } 708 return complete.substring(0, end + 1); 709 } 710 711 719 public static List addPath(Query query, String path, String searchDirs) { 720 if (path == null || path.equals("")) { 721 return query.getSteps().subList(0, 0); 722 } 723 if (searchDirs == null) { 724 searchDirs = ""; 725 } 726 727 List list = query.getSteps(); 728 int initialSize = list.size(); 729 730 StringTokenizer pathTokenizer = new StringTokenizer(path, ","); 731 StringTokenizer searchDirsTokenizer = new StringTokenizer(searchDirs, ","); 732 733 Cloud cloud = query.getCloud(); 734 735 if (query.getSteps().size() == 0) { String completeFirstToken = pathTokenizer.nextToken().trim(); 737 String firstToken = removeDigits(completeFirstToken); 738 Step step = query.addStep(cloud.getNodeManager(firstToken)); 743 if (!firstToken.equals(completeFirstToken)) { 744 query.setAlias(step, completeFirstToken); 745 } 746 } 747 748 String searchDir = null; while (pathTokenizer.hasMoreTokens()) { 750 String completeToken = pathTokenizer.nextToken().trim(); 751 String token = removeDigits(completeToken); 752 753 if (searchDirsTokenizer.hasMoreTokens()) { 754 searchDir = searchDirsTokenizer.nextToken(); 755 } 756 757 if (cloud.hasRole(token)) { 758 if (!pathTokenizer.hasMoreTokens()) { 759 throw new BridgeException("Path cannot end with a role (" + path + "/" + searchDirs + ")"); 760 } 761 String nodeManagerAlias = pathTokenizer.nextToken().trim(); 762 String nodeManagerName = removeDigits(nodeManagerAlias); 763 NodeManager nodeManager = cloud.getNodeManager(nodeManagerName); 764 RelationStep relationStep = query.addRelationStep(nodeManager, token, searchDir); 765 766 if (!cloud.hasRole(completeToken)) { 768 query.setAlias(relationStep, completeToken); 769 } 770 if (!nodeManagerName.equals(nodeManagerAlias)) { 771 Step next = relationStep.getNext(); 772 query.setAlias(next, nodeManagerAlias); 773 } 774 } else { 775 NodeManager nodeManager = cloud.getNodeManager(token); 776 RelationStep step = query.addRelationStep(nodeManager, null , searchDir); 777 if (!completeToken.equals(nodeManager.getName())) { 778 Step next = step.getNext(); 779 query.setAlias(next, completeToken); 780 } 781 } 782 } 783 if (searchDirsTokenizer.hasMoreTokens()) { 784 throw new BridgeException("Too many search directions (" + path + "/" + searchDirs + ")"); 785 } 786 return list.subList(initialSize, list.size()); 787 } 788 789 795 public static List addFields(Query query, String fields) { 796 List result = new ArrayList(); 797 if (fields == null || fields.equals("")) { 798 return result; 799 } 800 List list = StringSplitter.split(fields); 801 Iterator i = list.iterator(); 802 while (i.hasNext()) { 803 String fieldName = (String )i.next(); 804 result.add(query.addField(fieldName)); 805 } 806 return result; 807 808 } 809 810 811 812 824 public static void addStartNodes(Query query, String startNodes) { 825 if (startNodes == null || "".equals(startNodes) || "-1".equals(startNodes)) { 826 return; 827 } 828 829 Step firstStep = null; 831 Iterator nodes = StringSplitter.split(startNodes).iterator(); 832 while (nodes.hasNext()) { 833 String nodeAlias = (String ) nodes.next(); Step step; String nodeNumber; { 837 int dot = nodeAlias.indexOf('.'); if (dot == -1) { 839 step = firstStep; 840 nodeNumber = nodeAlias; 841 } else { 842 step = query.getStep(nodeAlias.substring(0, dot)); 843 nodeNumber = nodeAlias.substring(dot + 1); 844 } 845 } 846 847 if (firstStep == null) { Node node; 849 try { 850 node = query.getCloud().getNode(nodeNumber); 851 } catch (NotFoundException nfe) { node = query.getCloud().getNode(nodeAlias); 853 } 854 NodeManager nodeManager = node.getNodeManager(); 855 Iterator i = query.getSteps().iterator(); 856 while (i.hasNext()) { 857 Step queryStep = (Step) i.next(); 858 NodeManager queryNodeManager = query.getCloud().getNodeManager(queryStep.getTableName()); 859 if (queryNodeManager.equals(nodeManager) || queryNodeManager.getDescendants().contains(nodeManager)) { 860 firstStep = queryStep; 862 break; 863 } 864 } 865 if (firstStep == null) { 866 firstStep = (Step) query.getSteps().get(0); 871 } 872 if (step == null) { 873 step = firstStep; 874 } 875 } 876 877 try { 878 try { 879 query.addNode(step, Integer.parseInt(nodeNumber)); 880 } catch (NumberFormatException nfe) { 881 query.addNode(step, query.getCloud().getNode(nodeNumber)); } 883 } catch (NotFoundException nnfe) { 884 query.addNode(step, query.getCloud().getNode(nodeAlias)); } 886 } 887 } 888 889 894 public static int count(Query query) { 895 Cloud cloud = query.getCloud(); 896 Query count = query.aggregatingClone(); 897 int type = query.isDistinct() ? AggregatedField.AGGREGATION_TYPE_COUNT_DISTINCT : AggregatedField.AGGREGATION_TYPE_COUNT; 898 899 String resultName; 900 if (query instanceof NodeQuery) { 901 resultName = "number"; 903 NodeQuery nq = (NodeQuery) query; 904 count.addAggregatedField(nq.getNodeStep(), nq.getNodeManager().getField(resultName), type); 905 } else { 906 List fields = query.getFields(); 907 if (fields.size() == 0) { throw new IllegalArgumentException ("Cannot count queries with less than one field: " + query); 909 } 910 911 if (query.isDistinct() && fields.size() > 1) { 912 resultName = null; 914 Step step = null; 915 Iterator i = fields.iterator(); 916 while (i.hasNext()) { 917 StepField sf = (StepField) i.next(); 918 if (step == null) { 919 step = sf.getStep(); 920 } else { 921 if (! step.equals(sf.getStep())) { 922 throw new UnsupportedOperationException ("Cannot count distinct queries with fields of more than one step. Current fields: " + fields); 923 } 924 } 925 if (sf.getFieldName().equals("number")) { 926 resultName = sf.getFieldName(); 927 } 928 } 929 if (resultName == null) { 930 throw new UnsupportedOperationException ("Cannot count distinct queries with more than one field if 'number' field is missing. Current fields: " + fields); 931 } 932 count.addAggregatedField(step, cloud.getNodeManager(step.getTableName()).getField(resultName), type); 933 } else { 934 StepField sf = (StepField) fields.get(0); 936 Step step = sf.getStep(); 937 resultName = sf.getFieldName(); 938 count.addAggregatedField(step, cloud.getNodeManager(step.getTableName()).getField(resultName), type); 939 } 940 } 941 NodeList r = cloud.getList(count); 942 if (r.size() != 1) throw new RuntimeException ("Count query " + query + " did not give one result but " + r); 943 Node result = r.getNode(0); 944 return result.getIntValue(resultName); 945 } 946 947 950 protected static Object aggregate(Query query, StepField field, int type) { 951 Cloud cloud = query.getCloud(); 952 Query aggregate = query.aggregatingClone(); 953 String resultName = field.getFieldName(); 954 Step step = field.getStep(); 955 aggregate.addAggregatedField(step, cloud.getNodeManager(step.getTableName()).getField(resultName), type); 956 NodeList r = cloud.getList(aggregate); 957 if (r.size() != 1) throw new RuntimeException ("Aggregated query " + query + " did not give one result but " + r); 958 Node result = r.getNode(0); 959 return result.getValue(resultName); 960 } 961 962 965 public static Object min(Query query, StepField field) { 966 return aggregate(query, field, AggregatedField.AGGREGATION_TYPE_MIN); 967 } 968 971 public static Object max(Query query, StepField field) { 972 return aggregate(query, field, AggregatedField.AGGREGATION_TYPE_MAX); 973 } 974 975 982 public static Step searchStep(List steps, String stepAlias) { 983 if (log.isDebugEnabled()) { 984 log.debug("Searching '" + stepAlias + "' in " + steps); 985 } 986 Iterator i = steps.iterator(); 988 while (i.hasNext()) { 989 Step step = (Step)i.next(); 990 if (stepAlias.equals(step.getAlias())) { 991 return step; 992 } 993 } 994 i = steps.iterator(); 996 while (i.hasNext()) { 997 Step step = (Step)i.next(); 998 if (stepAlias.equals(step.getTableName())) { 999 return step; 1000 } 1001 } 1002 return null; 1003 } 1004 1005 1016 public static NodeQuery createNodeQuery(Node node) { 1017 NodeManager nm = node.getNodeManager(); 1018 NodeQuery query = node.getCloud().createNodeQuery(); Step step = query.addStep(nm); 1020 query.setNodeStep(step); 1021 if (! node.isNew()) { 1022 query.addNode(step, node); 1023 } 1024 return query; 1025 } 1026 1027 1035 public static NodeQuery createRelatedNodesQuery(Node node, NodeManager otherNodeManager, String role, String direction) { 1036 NodeQuery query = createNodeQuery(node); 1037 if (otherNodeManager == null) otherNodeManager = node.getCloud().getNodeManager("object"); 1038 RelationStep step = query.addRelationStep(otherNodeManager, role, direction); 1039 query.setNodeStep(step.getNext()); 1040 return query; 1041 } 1042 1043 1051 public static NodeQuery createRelationNodesQuery(Node node, NodeManager otherNodeManager, String role, String direction) { 1052 NodeQuery query = createNodeQuery(node); 1053 if (otherNodeManager == null) otherNodeManager = node.getCloud().getNodeManager("object"); 1054 RelationStep step = query.addRelationStep(otherNodeManager, role, direction); 1055 query.setNodeStep(step); 1056 return query; 1057 } 1058 1059 1075 public static NodeQuery createRelationNodesQuery(Node node, Node otherNode, String role, String direction) { 1076 NodeQuery query = createNodeQuery(node); 1077 NodeManager otherNodeManager = otherNode.getNodeManager(); 1078 RelationStep step = query.addRelationStep(otherNodeManager, role, direction); 1079 Step nextStep = step.getNext(); 1080 query.addNode(nextStep, otherNode.getNumber()); 1081 query.setNodeStep(step); 1082 return query; 1083 } 1084 1085 1101 public static NodeList getRelatedNodes(Node node, NodeManager otherNodeManager, String role, String direction, String relationFields, String sortOrders) { 1102 NodeQuery q = Queries.createRelatedNodesQuery(node, otherNodeManager, role, direction); 1103 addRelationFields(q, role, relationFields, sortOrders); 1104 return q.getCloud().getList(q); 1105 } 1106 1107 1110 public static NodeQuery addRelationFields(NodeQuery q, String role, String relationFields, String sortOrders) { 1111 List list = StringSplitter.split(relationFields); 1112 List orders = StringSplitter.split(sortOrders); 1113 Iterator i = list.iterator(); 1114 Iterator j = orders.iterator(); 1115 while (i.hasNext()) { 1116 String fieldName = (String )i.next(); 1117 StepField sf = q.addField(role + "." + fieldName); 1118 if (j.hasNext()) { 1119 String so = (String ) j.next(); 1120 q.addSortOrder(sf, getSortOrder(so)); 1121 } 1122 } 1123 return q; 1124 } 1125 1126 1132 public static Query sortUniquely(final Query q) { 1133 List steps = null; 1134 1135 Iterator i = q.getSortOrders().iterator(); 1137 while (i.hasNext()) { 1138 SortOrder sortOrder = (SortOrder)i.next(); 1139 if (sortOrder.getField().getFieldName().equals("number")) { 1140 Step step = sortOrder.getField().getStep(); 1141 if (steps == null) { 1142 steps = new ArrayList(q.getSteps()); 1144 } 1145 steps.remove(step); 1146 } 1147 } 1148 if (steps == null) { 1149 steps = q.getSteps(); 1150 } 1151 i = steps.iterator(); 1153 while (i.hasNext()) { 1154 Step step = (Step)i.next(); 1155 assert step != null; 1156 StepField sf = q.createStepField(step, "number"); 1157 if (sf == null) { 1158 throw new RuntimeException ("Create stepfield for 'number' field returned null!"); 1159 } 1160 q.addSortOrder(sf, SortOrder.ORDER_DESCENDING); 1161 } 1162 return q; 1163 } 1164 1165 1169 public static Query addSortedFields(Query q) { 1170 List fields = q.getFields(); 1171 Iterator i = q.getSortOrders().iterator(); 1172 while (i.hasNext()) { 1173 SortOrder order = (SortOrder) i.next(); 1174 StepField field = order.getField(); 1175 Step s = field.getStep(); 1176 StepField sf = q.createStepField(s, q.getCloud().getNodeManager(s.getTableName()).getField(field.getFieldName())); 1177 if (! fields.contains(sf)) { 1178 q.addField(s, q.getCloud().getNodeManager(s.getTableName()).getField(field.getFieldName())); 1179 } 1180 } 1181 return q; 1182 } 1183 1184 1189 public static Object getSortOrderFieldValue(Node node, SortOrder sortOrder) { 1190 String fieldName = sortOrder.getField().getFieldName(); 1191 if (node == null) throw new IllegalArgumentException ("No node given"); 1192 Object value = node.getValue(fieldName); 1193 if (value == null) { 1194 Step step = sortOrder.getField().getStep(); 1195 String pref = step.getAlias(); 1196 if (pref == null) { 1197 pref = step.getTableName(); 1198 } 1199 value = node.getValue(pref+ "." + fieldName); 1200 1201 } 1202 if (value instanceof Node) { 1203 value = new Integer (((Node)value).getNumber()); 1204 } 1205 return value; 1206 } 1207 1208 1209 1217 public static int compare(Node node1, Node node2, SortOrder sortOrder) { 1218 return compare(getSortOrderFieldValue(node1, sortOrder), 1219 getSortOrderFieldValue(node2, sortOrder), 1220 sortOrder); 1221 1222 } 1223 1226 public static int compare(Object value, Object value2, SortOrder sortOrder) { 1227 int result; 1228 if (value == null) { 1232 if (value2 != null) { 1233 return 1; 1234 } else { 1235 result = 0; 1236 } 1237 } else if (value2 == null) { 1238 return -1; 1239 } else { 1240 try { 1242 result = ((Comparable )value).compareTo(value2); 1243 } catch (ClassCastException cce) { 1244 log.warn("Cannot compare values " + value +" and " + value2 + " in sortorder field " + 1247 sortOrder.getField().getFieldName() + " in step " + sortOrder.getField().getStep().getAlias()); 1248 result = 0; 1249 } 1250 } 1251 if (sortOrder.getDirection() == SortOrder.ORDER_DESCENDING) { 1254 result = -result; 1255 } 1256 return result; 1257 } 1258 1259 1266 public static int compare(Node node1, Node node2, List sortOrders) { 1267 if (node1 == null) return -1; 1268 if (node2 == null) return +1; 1269 int result = 0; 1270 Iterator i = sortOrders.iterator(); 1271 while (result == 0 && i.hasNext()) { 1272 SortOrder order = (SortOrder) i.next(); 1273 result = compare(node1, node2, order); 1274 } 1275 return result; 1277 } 1278 1279 public static void main(String [] argv) { 1280 System.out.println(ConstraintParser.convertClauseToDBS("(([cpsettings.status]='[A]' OR [cpsettings.status]='I') AND [users.account] != '') and (lower([users.account]) LIKE '%t[est%' OR lower([users.email]) LIKE '%te]st%' OR lower([users.firstname]) LIKE '%t[e]st%' OR lower([users.lastname]) LIKE '%]test%')")); 1281 } 1282 1283} 1284 | Popular Tags |