1 package com.icl.saxon; 2 import com.icl.saxon.pattern.Pattern; 3 import com.icl.saxon.pattern.NoNodeTest; 4 import com.icl.saxon.om.NodeInfo; 5 import com.icl.saxon.om.Navigator; 6 import java.util.*; 7 import javax.xml.transform.TransformerException ; 8 import com.icl.saxon.expr.XPathException; 9 10 16 17 public class Mode { 18 private Rule[] ruleDict = new Rule[101 + NodeInfo.NUMBER_OF_TYPES]; 19 private int nameCode = -1; private int sequence = 0; 22 23 public Mode() { 24 } 28 29 32 33 public void setNameCode(int nameCode) { 34 this.nameCode = nameCode; 35 } 36 37 40 41 public int getNameCode() { 42 return nameCode; 43 } 44 45 46 53 54 public void addRule(Pattern p, Object obj, int precedence, double priority) { 55 56 58 60 if (p instanceof NoNodeTest) { 61 return; 62 } 63 64 69 int fingerprint = p.getFingerprint(); 70 short type = p.getNodeType(); 71 72 int key = getList(fingerprint, type); 73 75 Rule newRule = new Rule(p, obj, precedence, priority, sequence++); 76 77 Rule rule = ruleDict[key]; 78 if (rule==null) { 79 ruleDict[key] = newRule; 80 return; 81 } 82 83 85 Rule prev = null; 86 while (rule != null) { 87 if ((rule.precedence < precedence) || 88 ( rule.precedence == precedence && rule.priority <= priority)) { 89 newRule.next = rule; 90 if (prev==null) { 91 ruleDict[key] = newRule; 92 } else { 93 prev.next = newRule; 94 } 95 break; 96 } else { 97 prev = rule; 98 rule = rule.next; 99 } 100 } 101 if (rule==null) { 102 prev.next = newRule; 103 newRule.next = null; 104 } 105 } 106 107 110 111 public int getList(int fingerprint, int type) { 112 113 if (type==NodeInfo.ELEMENT) { 114 if (fingerprint==-1) { 115 return NodeInfo.NODE; } else { 117 return NodeInfo.NUMBER_OF_TYPES + 118 (fingerprint % 101); 119 } 120 } else { 121 return type; 122 } 123 } 124 125 130 131 public Object getRule(NodeInfo node, Context context) throws TransformerException { 132 int fingerprint = node.getFingerprint(); 134 int type = node.getNodeType(); 135 int key = getList(fingerprint, type); 136 int policy = context.getController().getRecoveryPolicy(); 137 138 Rule specificRule = null; 139 Rule generalRule = null; 140 int specificPrecedence = -1; 141 double specificPriority = Double.NEGATIVE_INFINITY; 142 143 145 147 if (key!=NodeInfo.NODE) { 148 Rule r = ruleDict[key]; 149 while(r!=null) { 150 if (specificRule != null) { 153 if (r.precedence < specificPrecedence || 154 (r.precedence==specificPrecedence && r.priority < specificPriority)) { 155 break; 156 } 157 } 158 if (r.pattern.matches(node, context)) { 160 162 if (specificRule != null) { 164 if (r.precedence==specificPrecedence && r.priority==specificPriority) { 165 reportAmbiguity(node, specificRule.pattern, r.pattern, context); 166 } 167 break; 168 } 169 specificRule = r; 170 specificPrecedence = r.precedence; 171 specificPriority = r.priority; 172 if (policy==Controller.RECOVER_SILENTLY) { 173 break; } 175 } 176 r = r.next; 177 } 178 } 179 180 182 Rule r2 = ruleDict[NodeInfo.NODE]; 183 while (r2 != null) { 184 if (r2.precedence < specificPrecedence || 185 (r2.precedence == specificPrecedence && r2.priority < specificPriority)) { 186 break; } 188 if (r2.pattern.matches(node, context)) { 189 if (generalRule != null) { 191 if (r2.precedence == generalRule.precedence && r2.priority ==generalRule.priority) { 192 reportAmbiguity(node, r2.pattern, generalRule.pattern, context); 193 } 194 break; 195 } else { 196 generalRule = r2; 197 if (policy==Controller.RECOVER_SILENTLY) { 198 break; } 200 } 201 } 202 r2 = r2.next; 203 } 204 205 if (specificRule!=null && generalRule==null) 206 return specificRule.object; 207 if (specificRule==null && generalRule!=null) 208 return generalRule.object; 209 if (specificRule!=null && generalRule!=null) { 210 if (specificRule.precedence == generalRule.precedence && 211 specificRule.priority == generalRule.priority ) { 212 Object result = (specificRule.sequence > generalRule.sequence ? 217 specificRule.object : 218 generalRule.object); 219 220 if (policy!=Controller.RECOVER_SILENTLY) { 221 reportAmbiguity(node, specificRule.pattern, generalRule.pattern, context); 222 } 223 return result; 224 } 225 if (specificRule.precedence > generalRule.precedence || 226 (specificRule.precedence == generalRule.precedence && 227 specificRule.priority >= generalRule.priority)) { 228 return specificRule.object; 229 } else { 230 return generalRule.object; 231 } 232 } 233 return null; 234 } 235 236 242 243 public Object getRule(NodeInfo node, int min, int max, Context context) throws XPathException { 244 int fing = node.getFingerprint(); 245 int type = node.getNodeType(); 246 int key = getList(fing, type); 247 248 Rule specificRule = null; 249 Rule generalRule = null; 250 251 253 if (key!=NodeInfo.NODE) { 254 Rule r = ruleDict[key]; 255 while (r!=null) { 256 if (r.precedence >= min && r.precedence <= max && 257 r.pattern.matches(node, context)) { 258 specificRule = r; 259 break; } 261 r = r.next; 262 } 263 } 264 265 267 Rule r2 = ruleDict[NodeInfo.NODE]; 268 while (r2!=null) { 269 if (r2.precedence >= min && r2.precedence <= max && r2.pattern.matches(node, context)) { 270 generalRule = r2; 271 break; } 273 r2 = r2.next; 274 } 275 if (specificRule!=null && generalRule==null) 276 return specificRule.object; 277 if (specificRule==null && generalRule!=null) 278 return generalRule.object; 279 if (specificRule!=null && generalRule!=null) { 280 if (specificRule.precedence > generalRule.precedence || 281 (specificRule.precedence == generalRule.precedence && 282 specificRule.priority >= generalRule.priority)) { 283 return specificRule.object; 284 } else { 285 return generalRule.object; 286 } 287 } 288 return null; 289 } 290 291 294 295 private void reportAmbiguity(NodeInfo node, Pattern pat1, Pattern pat2, Context c) 296 throws TransformerException 297 { 298 if (pat1.getStaticContext()==pat2.getStaticContext()) { 301 return; 302 } 303 c.getController().reportRecoverableError( 304 "Ambiguous rule match for " + Navigator.getPath(node) + "\n" + 305 "Matches both \"" + pat1 + "\" on line " + pat1.getLineNumber() + " of " + pat1.getSystemId() + 306 "\nand \"" + pat2 + "\" on line " + pat2.getLineNumber() + " of " + pat2.getSystemId(), null); 307 308 } 309 310 311 314 315 private static class Rule { 316 public Pattern pattern; 317 public Object object; 318 public int precedence; 319 public double priority; 320 public int sequence; 321 public Rule next; 322 323 public Rule( Pattern p, Object o, int prec, double prio, int seq ) { 324 pattern = p; 325 object = o; 326 precedence = prec; 327 priority = prio; 328 sequence = seq; 329 next = null; 330 } 331 332 } 333 334 } 335 336 | Popular Tags |