Coverage Report - org.galagosearch.core.retrieval.query.Node
 
Classes in this File Line Coverage Branch Coverage Complexity
Node
77%
68/88
64%
37/58
0
 
 1  
 // BSD License (http://www.galagosearch.org/license)
 2  
 package org.galagosearch.core.retrieval.query;
 3  
 
 4  
 import java.util.ArrayList;
 5  
 import java.util.List;
 6  
 import java.util.Map;
 7  
 import org.galagosearch.tupleflow.Parameters.Value;
 8  
 import org.galagosearch.tupleflow.Parameters;
 9  
 
 10  
 /**
 11  
  * <p>Node represents a single node in a query parse tree.</p>
 12  
  * 
 13  
  * <p>In Galago, queries are parsed into a tree of Nodes.  The query tree can then
 14  
  * be modified using StructuredQuery.copy, or analyzed by using StructuredQuery.walk.
 15  
  * Once the query is in the proper form, the query is converted into a tree of iterators
 16  
  * that can be evaluated.</p>
 17  
  * 
 18  
  * @author trevor
 19  
  */
 20  
 public class Node {
 21  
     /// The query operator represented by this node, like "combine", "weight", "syn", etc.
 22  
     private String operator;
 23  
 
 24  
     /// Child nodes of the operator, e.g. in #combine(a b), 'a' and 'b' are internal nodes of #combine.
 25  
     private ArrayList<Node> internalNodes;
 26  
 
 27  
     /// The position in the text string where this operator starts.  Useful for parse error messages.
 28  
     private int position;
 29  
 
 30  
     /// Additional parameters for this operator; usually these are term statistics and smoothing parameters.
 31  
     private Parameters parameters;
 32  
 
 33  0
     public Node() {
 34  0
         internalNodes = new ArrayList<Node>();
 35  0
         parameters = new Parameters();
 36  0
     }
 37  
 
 38  
     public Node(String operator, ArrayList<Node> internalNodes) {
 39  40
         this(operator, (String) null, internalNodes, 0);
 40  40
     }
 41  
 
 42  
     public Node(String operator, ArrayList<Node> internalNodes, int position) {
 43  76
         this(operator, (String) null, internalNodes, position);
 44  76
     }
 45  
 
 46  
     public Node(String operator, String argument) {
 47  96
         this(operator, argument, 0);
 48  96
     }
 49  
 
 50  
     public Node(String operator, String argument, int position) {
 51  276
         this(operator, argument, new ArrayList<Node>(), position);
 52  276
     }
 53  
 
 54  
     public Node(String operator, String argument, ArrayList<Node> internalNodes) {
 55  40
         this(operator, argument, internalNodes, 0);
 56  40
     }
 57  
 
 58  456
     public Node(String operator, String argument, ArrayList<Node> internalNodes, int position) {
 59  456
         Parameters p = new Parameters();
 60  
 
 61  456
         if (argument != null) {
 62  340
             p.add("default", argument);
 63  
         }
 64  456
         this.operator = operator;
 65  456
         this.internalNodes = internalNodes;
 66  456
         this.position = position;
 67  456
         this.parameters = p;
 68  456
     }
 69  
 
 70  152
     public Node(String operator, Parameters parameters, ArrayList<Node> internalNodes, int position) {
 71  152
         this.operator = operator;
 72  152
         this.internalNodes = internalNodes;
 73  152
         this.position = position;
 74  152
         this.parameters = parameters;
 75  152
     }
 76  
 
 77  
     public String getOperator() {
 78  332
         return operator;
 79  
     }
 80  
     
 81  
     public String getDefaultParameter() {
 82  36
         return parameters.get("default", (String)null);
 83  
     }
 84  
     
 85  
     public String getDefaultParameter(String key) {
 86  8
         return parameters.get(key, getDefaultParameter());
 87  
     }
 88  
 
 89  
     public ArrayList<Node> getInternalNodes() {
 90  312
         return internalNodes;
 91  
     }
 92  
 
 93  
     public int getPosition() {
 94  112
         return position;
 95  
     }
 96  
 
 97  
     public Parameters getParameters() {
 98  144
         return parameters;
 99  
     }
 100  
     
 101  
     public boolean needsToBeEscaped(String text) {
 102  244
         return text.contains("@") || text.contains(",") ||
 103  
                text.contains(".") || text.contains(" ") ||
 104  
                text.contains("\t") || text.contains("\r") ||
 105  
                text.contains("\n");
 106  
     }
 107  
     
 108  
     public String escapeAsNecessary(String text) {
 109  244
         if (!needsToBeEscaped(text)) {
 110  224
             return text; 
 111  
         } else {
 112  20
             String[] preferredDelimiters = { "/", "|", "#", "!", "%" };
 113  
             
 114  20
             for (String delimiter : preferredDelimiters) {
 115  20
                 if (!text.contains(delimiter)) {
 116  20
                     return "@" + delimiter + text + delimiter;
 117  
                 }
 118  
             }
 119  
             
 120  
             // give up
 121  0
             return text;
 122  
         }
 123  
     }
 124  
 
 125  
     @Override
 126  
     public String toString() {
 127  344
         StringBuilder builder = new StringBuilder();
 128  
 
 129  344
         builder.append('#');
 130  344
         builder.append(operator);
 131  
 
 132  344
         if (parameters.containsKey("default")) {
 133  244
             String value = parameters.get("default");
 134  244
             builder.append(':');
 135  244
             builder.append(escapeAsNecessary(value));
 136  
         }
 137  
 
 138  344
         Map<String, List<Value>> parameterMap = parameters.value().map();
 139  
 
 140  344
         if (parameterMap != null) {
 141  244
             for (String key : parameterMap.keySet()) {
 142  244
                 if (key.equals("default")) {
 143  244
                     continue;
 144  
                 }
 145  0
                 String value = parameterMap.get(key).get(0).toString();
 146  
                 
 147  0
                 builder.append(':');
 148  0
                 builder.append(escapeAsNecessary(key));
 149  0
                 builder.append('=');
 150  0
                 builder.append(escapeAsNecessary(value));
 151  0
             }
 152  
         }
 153  
 
 154  344
         if (internalNodes.size() == 0) {
 155  212
             builder.append("()");
 156  
         } else {
 157  132
             builder.append("( ");
 158  132
             for (Node child : internalNodes) {
 159  268
                 builder.append(child.toString());
 160  268
                 builder.append(' ');
 161  
             }
 162  132
             builder.append(")");
 163  
         }
 164  
         
 165  344
         return builder.toString();
 166  
     }
 167  
 
 168  
     @Override
 169  
     public boolean equals(Object o) {
 170  48
         if (!(o instanceof Node)) {
 171  0
             return false;
 172  
         }
 173  48
         if (o == this) {
 174  4
             return true;
 175  
         }
 176  44
         Node other = (Node) o;
 177  
 
 178  44
         if ((operator == null) != (other.getOperator() == null)) {
 179  0
             return false;
 180  
         }
 181  44
         if (operator != null && !other.getOperator().equals(operator)) {
 182  0
             return false;
 183  
         }
 184  44
         if (internalNodes.size() != other.getInternalNodes().size()) {
 185  0
             return false;
 186  
         }
 187  76
         for (int i = 0; i < internalNodes.size(); i++) {
 188  32
             if (!internalNodes.get(i).equals(other.getInternalNodes().get(i))) {
 189  0
                 return false;
 190  
             }
 191  
         }
 192  
 
 193  44
         return true;
 194  
     }
 195  
 
 196  
     @Override
 197  
     public int hashCode() {
 198  0
         int hash = 7;
 199  0
         hash = 67 * hash + (this.operator != null ? this.operator.hashCode() : 0);
 200  0
         hash = 67 * hash + (this.internalNodes != null ? this.internalNodes.hashCode() : 0);
 201  0
         return hash;
 202  
     }
 203  
 }