1 package com.icl.saxon.pattern; 2 import com.icl.saxon.expr.*; 3 import com.icl.saxon.*; 4 import com.icl.saxon.om.*; 5 import com.icl.saxon.om.Axis; 6 import com.icl.saxon.expr.XPathException; 7 8 12 13 public final class LocationPathPattern extends Pattern { 14 15 17 public Pattern parentPattern = null; 18 public Pattern ancestorPattern = null; 19 public NodeTest nodeTest = AnyNodeTest.getInstance(); 20 protected Expression[] filters = null; 21 protected int numberOfFilters = 0; 22 protected Expression equivalentExpr = null; 23 protected boolean firstElementPattern = false; 24 protected boolean lastElementPattern = false; 25 protected boolean specialFilter = false; 26 27 31 32 public void addFilter(Expression filter) { 33 if (filters==null) { 34 filters = new Expression[3]; 35 } else if (numberOfFilters == filters.length) { 36 Expression[] f2 = new Expression[numberOfFilters * 2]; 37 System.arraycopy(filters, 0, f2, 0, numberOfFilters); 38 filters = f2; 39 } 40 filters[numberOfFilters++] = filter; 41 } 42 43 46 47 public Pattern simplify() throws XPathException { 48 49 51 if ( parentPattern == null && 52 ancestorPattern == null && 53 filters == null) { 54 nodeTest.setStaticContext(getStaticContext()); 55 return nodeTest; 56 } 57 58 60 if (parentPattern != null) parentPattern = parentPattern.simplify(); 61 if (ancestorPattern != null) ancestorPattern = ancestorPattern.simplify(); 62 if (filters != null) { 63 for (int i=numberOfFilters-1; i>=0; i--) { 64 Expression filter = filters[i].simplify(); 65 filters[i] = filter; 66 if ((filter instanceof BooleanValue) && (((Value)filter).asBoolean())) { 68 if (i==numberOfFilters-1) { 69 numberOfFilters--; 70 } } 72 } 73 } 74 75 77 if (nodeTest.getNodeType() == NodeInfo.ELEMENT && 78 numberOfFilters==1 && 79 (filters[0] instanceof NumericValue) && 80 (int)((NumericValue)filters[0]).asNumber()==1 ) { 81 firstElementPattern = true; 82 specialFilter = true; 83 numberOfFilters = 0; 84 filters = null; 85 } 86 87 90 if (nodeTest.getNodeType() == NodeInfo.ELEMENT && 91 numberOfFilters==1 && 92 filters[0] instanceof IsLastExpression && 93 ((IsLastExpression)filters[0]).getCondition()) { 94 lastElementPattern = true; 95 specialFilter = true; 96 numberOfFilters = 0; 97 filters = null; 98 } 99 100 if (isRelative()) { 101 makeEquivalentExpression(); 102 specialFilter = true; 103 } 104 105 return this; 106 } 107 108 109 112 113 private void makeEquivalentExpression() throws XPathException { 114 byte axis = (nodeTest.getNodeType()==NodeInfo.ATTRIBUTE ? 115 Axis.ATTRIBUTE : 116 Axis.CHILD ); 117 Step step = new Step(axis, nodeTest); 118 step.setFilters(filters, numberOfFilters); 119 equivalentExpr = new PathExpression(new ParentNodeExpression(), step); 120 } 121 122 127 128 public boolean matchesX(NodeInfo node, Context context) throws XPathException { 130 System.err.println("Matching node " + node + " against LP pattern " + this); 131 System.err.println("Node types " + node.getNodeType() + " / " + this.getNodeType()); 132 boolean b = matches(node, context); 133 System.err.println((b ? "matches" : "no match")); 134 return b; 135 } 136 137 public boolean matches(NodeInfo node, Context context) throws XPathException { 138 139 if (!nodeTest.matches(node)) return false; 140 141 if (parentPattern!=null) { 142 NodeInfo par = node.getParent(); 143 if (par==null) return false; 144 if (!(parentPattern.matches(par, context))) return false; 145 } 146 147 if (ancestorPattern!=null) { 148 NodeInfo anc = node.getParent(); 149 while (true) { 150 if (ancestorPattern.matches(anc, context)) break; 151 anc = anc.getParent(); 152 if (anc==null) return false; 153 } 154 } 155 156 if (specialFilter) { 157 if (firstElementPattern) { 158 NodeEnumeration enum = node.getEnumeration(Axis.PRECEDING_SIBLING, nodeTest); 159 return !enum.hasMoreElements(); 160 } 161 162 if (lastElementPattern) { 163 NodeEnumeration enum = node.getEnumeration(Axis.FOLLOWING_SIBLING, nodeTest); 164 return !enum.hasMoreElements(); 165 } 166 167 if (equivalentExpr!=null) { 168 169 173 Context c = context.newContext(); 174 c.setContextNode(node); 175 c.setPosition(1); 176 c.setLast(1); 177 NodeEnumeration nsv = equivalentExpr.enumerate(c, false); 178 while (nsv.hasMoreElements()) { 179 NodeInfo n = nsv.nextElement(); 180 if (n.isSameNode(node)) { 181 return true; 182 } 183 } 184 return false; 185 } 186 } 187 188 if (filters!=null) { 189 Context c = context.newContext(); 190 c.setContextNode(node); 191 c.setPosition(1); c.setLast(1); 193 194 for (int i=0; i<numberOfFilters; i++) { 195 if (!filters[i].evaluateAsBoolean(c)) return false; 196 } 197 } 198 199 return true; 200 } 201 202 207 208 public short getNodeType() { 209 return nodeTest.getNodeType(); 210 } 211 212 217 218 public int getFingerprint() { 219 return nodeTest.getFingerprint(); 220 } 221 222 227 228 public boolean isRelative() throws XPathException { 229 if (filters==null) return false; 230 for (int i=0; i<numberOfFilters; i++) { 231 int type = filters[i].getDataType(); 232 if (type==Value.NUMBER || type==Value.ANY) return true; 233 if ((filters[i].getDependencies() & 234 (Context.POSITION | Context.LAST)) != 0) return true; 235 } 236 return false; 237 } 238 } 239 240 | Popular Tags |