KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > icl > saxon > functions > Key


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 JavaDoc getName() {
26         return "key";
27     };
28
29     /**
30     * Determine the data type of the expression
31     * @return Value.NODESET
32     */

33
34     public int getDataType() {
35         return Value.NODESET;
36     }
37
38     /**
39     * Determine, in the case of an expression whose data type is Value.NODESET,
40     * whether all the nodes in the node-set are guaranteed to come from the same
41     * document as the context node. Used for optimization.
42     */

43     
44     public boolean isContextDocumentNodeSet() {
45         return true;
46     }
47
48     /**
49     * Simplify and validate
50     */

51
52     public Expression simplify() throws XPathException {
53         // check that key() function is allowed in this context
54
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     /**
64     * Evaluate the expression
65     */

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     /**
75     * Enumerate the expression
76     */

77
78     public NodeEnumeration enumerate(Context context, boolean sorted) throws XPathException {
79         String JavaDoc 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     /**
96     * Construct an enumeration of nodes that satisfy the given key
97     * @param controller The controller (to get the key definitions)
98     * @param doc The document to search
99     * @param keyname The absolute (expanded) name of the key
100     * @param arg1 The value of the key (or nodeset containing the values)
101     */

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     /**
148     * Determine which aspects of the context the expression depends on. The result is
149     * a bitwise-or'ed value composed from constants such as Context.VARIABLES and
150     * Context.CURRENT_NODE
151     */

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     /**
166     * Remove specified dependencies.
167     */

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 //
197
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
198
// you may not use this file except in compliance with the License. You may obtain a copy of the
199
// License at http://www.mozilla.org/MPL/
200
//
201
// Software distributed under the License is distributed on an "AS IS" basis,
202
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
203
// See the License for the specific language governing rights and limitations under the License.
204
//
205
// The Original Code is: all this file.
206
//
207
// The Initial Developer of the Original Code is
208
// Michael Kay of International Computers Limited (mhkay@iclway.co.uk).
209
//
210
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
211
//
212
// Contributor(s): none.
213
//
214
Popular Tags