1
2
3 package org.galagosearch.core.retrieval.query;
4
5 import java.lang.reflect.Constructor;
6 import org.galagosearch.core.retrieval.structured.StructuredIterator;
7 import org.galagosearch.tupleflow.Parameters;
8
9 /***
10 * <p>A NodeType describes the class type and input types of an iterator.</p>
11 *
12 * <p>Traversals that modify a tree may want to know what type of iterator will be generated
13 * when a Node is converted into a StructuredIterator. For instance, a Node with a
14 * "counts" operator will turn into a ExtentListIterator. This is important to know because
15 * a ScoreCombinationIterator can't take an ExtentListIterator as an argument; it needs an
16 * iterator between them to convert extents into scores. A Traversal can check the types
17 * of "counts" and "combine", notice the type mismatch, and add a "#feature" node between
18 * them so that the types match.</p>
19 *
20 * @author trevor
21 */
22 public class NodeType {
23 private Class<? extends StructuredIterator> nodeClass;
24
25 public NodeType(Class<? extends StructuredIterator> nodeClass) {
26 this.nodeClass = nodeClass;
27 }
28
29 public Class<? extends StructuredIterator> getIteratorClass() {
30 return nodeClass;
31 }
32
33 public Class[] getInputs() throws Exception {
34 Constructor constructor = null;
35 try {
36 constructor = getConstructor();
37 } catch(Exception e) {
38 return new Class[0];
39 }
40 return constructor.getParameterTypes();
41 }
42
43 public Class[] getParameterTypes(int length) throws Exception {
44 Class[] inputs = getInputs();
45 if (inputs == null) return new Class[0];
46 if (inputs.length == 0) return new Class[0];
47 if (inputs[inputs.length-1].isArray()) {
48 if (length < inputs.length-1) {
49
50 return null;
51 } else {
52 Class[] result = new Class[length];
53
54 for (int i = 0; i < inputs.length-1; ++i) {
55 result[i] = inputs[i];
56 }
57
58 for (int i = inputs.length-1; i < result.length; ++i) {
59 result[i] = inputs[inputs.length-1].getComponentType();
60 }
61 return result;
62 }
63 } else {
64 if (length != inputs.length) {
65 return null;
66 } else {
67 return inputs;
68 }
69 }
70 }
71
72 public boolean isStructuredIteratorOrArray(Class c) {
73 if (c.isArray() && StructuredIterator.class.isAssignableFrom(c.getComponentType()))
74 return true;
75 if (StructuredIterator.class.isAssignableFrom(c))
76 return true;
77 return false;
78 }
79
80 public Constructor getConstructor() throws Exception {
81 for (Constructor constructor : nodeClass.getConstructors()) {
82 Class[] types = constructor.getParameterTypes();
83
84
85 if (types.length < 1)
86 continue;
87
88 if (!Parameters.class.isAssignableFrom(types[0]))
89 continue;
90
91 boolean validTypes = true;
92 for (int i = 1; i < types.length; ++i) {
93 if (!isStructuredIteratorOrArray(types[i])) {
94 validTypes = false;
95 break;
96 }
97 }
98
99 if (validTypes) {
100 return constructor;
101 }
102 }
103
104 throw new Exception("No reasonable constructors were found for " + nodeClass.toString());
105 }
106 }