| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| NodeType |
|
| 0.0;0 |
| 1 | // BSD License (http://www.galagosearch.org/license) | |
| 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 | 76 | public NodeType(Class<? extends StructuredIterator> nodeClass) { |
| 26 | 76 | this.nodeClass = nodeClass; |
| 27 | 76 | } |
| 28 | ||
| 29 | public Class<? extends StructuredIterator> getIteratorClass() { | |
| 30 | 24 | return nodeClass; |
| 31 | } | |
| 32 | ||
| 33 | public Class[] getInputs() throws Exception { | |
| 34 | 24 | Constructor constructor = null; |
| 35 | try { | |
| 36 | 24 | constructor = getConstructor(); |
| 37 | 0 | } catch(Exception e) { |
| 38 | 0 | return new Class[0]; |
| 39 | 24 | } |
| 40 | 24 | return constructor.getParameterTypes(); |
| 41 | } | |
| 42 | ||
| 43 | public Class[] getParameterTypes(int length) throws Exception { | |
| 44 | 20 | Class[] inputs = getInputs(); |
| 45 | 20 | if (inputs == null) return new Class[0]; |
| 46 | 20 | if (inputs.length == 0) return new Class[0]; |
| 47 | 20 | if (inputs[inputs.length-1].isArray()) { |
| 48 | 12 | if (length < inputs.length-1) { |
| 49 | // Not enough parameters. | |
| 50 | 0 | return null; |
| 51 | } else { | |
| 52 | 12 | Class[] result = new Class[length]; |
| 53 | // Copy in classes for the first few parameters. | |
| 54 | 28 | for (int i = 0; i < inputs.length-1; ++i) { |
| 55 | 16 | result[i] = inputs[i]; |
| 56 | } | |
| 57 | // Apply the array class type to the remaining slots. | |
| 58 | 36 | for (int i = inputs.length-1; i < result.length; ++i) { |
| 59 | 24 | result[i] = inputs[inputs.length-1].getComponentType(); |
| 60 | } | |
| 61 | 12 | return result; |
| 62 | } | |
| 63 | } else { | |
| 64 | 8 | if (length != inputs.length) { |
| 65 | 0 | return null; |
| 66 | } else { | |
| 67 | 8 | return inputs; |
| 68 | } | |
| 69 | } | |
| 70 | } | |
| 71 | ||
| 72 | public boolean isStructuredIteratorOrArray(Class c) { | |
| 73 | 76 | if (c.isArray() && StructuredIterator.class.isAssignableFrom(c.getComponentType())) |
| 74 | 32 | return true; |
| 75 | 44 | if (StructuredIterator.class.isAssignableFrom(c)) |
| 76 | 36 | return true; |
| 77 | 8 | return false; |
| 78 | } | |
| 79 | ||
| 80 | public Constructor getConstructor() throws Exception { | |
| 81 | 44 | for (Constructor constructor : nodeClass.getConstructors()) { |
| 82 | 44 | Class[] types = constructor.getParameterTypes(); |
| 83 | ||
| 84 | // The constructor needs at least one parameter. | |
| 85 | 44 | if (types.length < 1) |
| 86 | 0 | continue; |
| 87 | // The first class needs to be a Parameters object. | |
| 88 | 44 | if (!Parameters.class.isAssignableFrom(types[0])) |
| 89 | 0 | continue; |
| 90 | // Check arguments for valid argument types. | |
| 91 | 44 | boolean validTypes = true; |
| 92 | 100 | for (int i = 1; i < types.length; ++i) { |
| 93 | 56 | if (!isStructuredIteratorOrArray(types[i])) { |
| 94 | 0 | validTypes = false; |
| 95 | 0 | break; |
| 96 | } | |
| 97 | } | |
| 98 | // If everything looks good, return this constructor. | |
| 99 | 44 | if (validTypes) { |
| 100 | 44 | return constructor; |
| 101 | } | |
| 102 | } | |
| 103 | ||
| 104 | 0 | throw new Exception("No reasonable constructors were found for " + nodeClass.toString()); |
| 105 | } | |
| 106 | } |