1 package com.icl.saxon.functions; 2 import com.icl.saxon.Controller; 3 import com.icl.saxon.Context; 4 import com.icl.saxon.KeyManager; 5 import com.icl.saxon.om.NodeInfo; 6 import com.icl.saxon.om.DocumentInfo; 7 import com.icl.saxon.om.NodeEnumeration; 8 import com.icl.saxon.om.EmptyEnumeration; 9 import com.icl.saxon.expr.Function; 10 import com.icl.saxon.expr.XPathException; 11 import com.icl.saxon.expr.Value; 12 import com.icl.saxon.expr.NodeSetExtent; 13 import com.icl.saxon.expr.NodeSetValue; 14 import com.icl.saxon.expr.Expression; 15 import com.icl.saxon.expr.FragmentValue; 16 import com.icl.saxon.expr.TextFragmentValue; 17 import com.icl.saxon.expr.UnionEnumeration; 18 import com.icl.saxon.sort.LocalOrderComparer; 19 20 public class Key extends Function { 21 22 private DocumentInfo boundDocument = null; 23 private Controller boundController = null; 24 25 public String getName() { 26 return "key"; 27 }; 28 29 33 34 public int getDataType() { 35 return Value.NODESET; 36 } 37 38 43 44 public boolean isContextDocumentNodeSet() { 45 return true; 46 } 47 48 51 52 public Expression simplify() throws XPathException { 53 if (!getStaticContext().allowsKeyFunction()) { 55 throw new XPathException("key() function cannot be used here"); 56 } 57 checkArgumentCount(2, 2); 58 argument[0] = argument[0].simplify(); 59 argument[1] = argument[1].simplify(); 60 return this; 61 } 62 63 66 67 public Value evaluate(Context context) throws XPathException { 68 NodeSetExtent nse = new NodeSetExtent(enumerate(context, true), 69 LocalOrderComparer.getInstance()); 70 nse.setSorted(true); 71 return nse; 72 } 73 74 77 78 public NodeEnumeration enumerate(Context context, boolean sorted) throws XPathException { 79 String givenkeyname = argument[0].evaluateAsString(context); 80 Value keyvalue = argument[1].evaluate(context); 81 82 Controller controller = boundController; 83 if (controller==null) controller = context.getController(); 84 85 DocumentInfo doc = boundDocument; 86 if (doc==null) doc = (context.getContextNodeInfo()).getDocumentRoot(); 87 88 int fingerprint = getStaticContext().getFingerprint(givenkeyname, false); 89 if (fingerprint==-1) { 90 throw new XPathException("Key '" + givenkeyname + "' has not been defined"); 91 } 92 return findKey(controller, doc, fingerprint, keyvalue); 93 } 94 95 102 103 private NodeEnumeration findKey( 104 Controller controller, 105 DocumentInfo doc, 106 int fingerprint, 107 Value arg1) throws XPathException { 108 109 KeyManager keyManager = controller.getKeyManager(); 110 111 boolean sorted; 112 113 if ((arg1 instanceof NodeSetValue) && 114 !(arg1 instanceof FragmentValue || arg1 instanceof TextFragmentValue)) { 115 116 NodeSetValue keyvals = (NodeSetValue)arg1; 117 118 NodeEnumeration supplied = keyvals.enumerate(); 119 NodeEnumeration result = null; 120 121 int inNodes = 0; 122 while (supplied.hasMoreElements()) { 123 inNodes++; 124 NodeEnumeration onekeyresult = 125 keyManager.selectByKey(fingerprint, 126 doc, 127 supplied.nextElement().getStringValue(), 128 controller); 129 if (inNodes==1) { 130 result = onekeyresult; 131 } else { 132 result = new UnionEnumeration(result, onekeyresult, 133 controller); 134 } 135 } 136 if (inNodes==0) { 137 return EmptyEnumeration.getInstance(); 138 } else { 139 return result; 140 } 141 142 } else { 143 return keyManager.selectByKey(fingerprint, doc, arg1.asString(), controller); 144 } 145 } 146 147 152 153 public int getDependencies() { 154 int dependencies = argument[0].getDependencies(); 155 dependencies |= argument[1].getDependencies(); 156 if (boundDocument == null) { 157 dependencies |= (Context.CONTEXT_NODE | Context.CONTEXT_DOCUMENT); 158 } 159 if (boundController == null) { 160 dependencies |= Context.CONTROLLER; 161 } 162 return dependencies; 163 } 164 165 168 169 public Expression reduce(int dep, Context context) 170 throws XPathException { 171 Key key = new Key(); 172 key.addArgument(argument[0].reduce(dep, context)); 173 key.addArgument(argument[1].reduce(dep, context)); 174 if (boundDocument==null && 175 ((dep & (Context.CONTEXT_NODE | Context.CONTEXT_DOCUMENT))!=0)) { 176 key.boundDocument = (context.getContextNodeInfo()).getDocumentRoot(); 177 } else { 178 key.boundDocument = boundDocument; 179 } 180 if (boundController==null && ((dep & Context.CONTROLLER)!=0)) { 181 key.boundController = context.getController(); 182 } else { 183 key.boundController = boundController; 184 } 185 key.setStaticContext(getStaticContext()); 186 return key.simplify(); 187 188 } 189 190 } 191 192 193 194 195 196 | Popular Tags |