View Javadoc

1   // BSD License (http://www.galagosearch.org/license)
2   package org.galagosearch.core.retrieval.traversal;
3   
4   import java.util.ArrayList;
5   import org.galagosearch.core.retrieval.query.Node;
6   import org.galagosearch.core.retrieval.query.NodeType;
7   import org.galagosearch.core.retrieval.query.Traversal;
8   import org.galagosearch.core.retrieval.structured.CountIterator;
9   import org.galagosearch.core.retrieval.structured.ScoreIterator;
10  import org.galagosearch.core.retrieval.structured.StructuredRetrieval;
11  
12  /***
13   * For many kinds of queries, it may be preferable to not have to type
14   * an explicit #feature operator around a count or extents term.  For example,
15   * we want #combine(#feature:dirichlet(#counts:dog())) to be the same as
16   * #combine(dog).  This transformation automatically adds the #feature:dirichlet
17   * operator.
18   * 
19   * @author trevor
20   */
21  public class ImplicitFeatureCastTraversal implements Traversal {
22      StructuredRetrieval retrieval;
23  
24      public ImplicitFeatureCastTraversal(StructuredRetrieval retrieval) {
25          this.retrieval = retrieval;
26      }
27      
28      Node createSmoothingNode(Node child) {
29          ArrayList<Node> data = new ArrayList<Node>();
30          data.add(child);
31          return new Node("feature", "dirichlet", data, child.getPosition());
32      }
33      
34      public boolean isCountNode(Node node) throws Exception {
35          NodeType nodeType = retrieval.getNodeType(node);
36          if (nodeType == null) return false;
37          Class outputClass = nodeType.getIteratorClass();
38          return CountIterator.class.isAssignableFrom(outputClass);
39      }
40  
41      public void beforeNode(Node node) throws Exception {
42      }
43  
44      public Node afterNode(Node node) throws Exception {
45          ArrayList<Node> newChildren = new ArrayList<Node>();
46          NodeType nodeType = retrieval.getNodeType(node);
47          if (nodeType == null) return node;
48          ArrayList<Node> children = node.getInternalNodes();
49          // Given that we're going to pass children.size() + 1 parameters to
50          // this constructor, what types should those parameters have?
51          Class[] types = nodeType.getParameterTypes(children.size() + 1);
52          if (types == null) return node;
53  
54          for (int i = 1; i < types.length; ++i) {
55              Node child = children.get(i-1);
56              // If the parent will expect a ScoreIterator at this position, but
57              // we've got a CountIterator here, we'll perform a conversion step.
58              if (ScoreIterator.class.isAssignableFrom(types[i]) &&
59                  isCountNode(children.get(i-1))) {
60                  Node feature = createSmoothingNode(child);
61                  newChildren.add(feature);
62              } else {
63                  newChildren.add(child);
64              }
65          }
66  
67          return new Node(node.getOperator(), node.getParameters(),
68                          newChildren, node.getPosition());
69      }
70  }