1 /* Copyright 2004 The Apache Software Foundation 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 package org.apache.xmlbeans.impl.xquery.saxon; 17 18 import java.util.List; 19 import java.util.Map; 20 import java.util.Iterator; 21 import java.util.ListIterator; 22 23 import javax.xml.transform.dom.DOMSource; 24 import javax.xml.transform.TransformerException; 25 26 import org.w3c.dom.Node; 27 28 import net.sf.saxon.Configuration; 29 import net.sf.saxon.dom.NodeOverNodeInfo; 30 import net.sf.saxon.om.NodeInfo; 31 import net.sf.saxon.query.DynamicQueryContext; 32 import net.sf.saxon.query.StaticQueryContext; 33 import net.sf.saxon.query.XQueryExpression; 34 35 import org.apache.xmlbeans.XmlRuntimeException; 36 import org.apache.xmlbeans.XmlTokenSource; 37 import org.apache.xmlbeans.impl.store.QueryDelegate; 38 39 public class XBeansXQuery 40 implements QueryDelegate.QueryInterface 41 { 42 private XQueryExpression xquery; 43 private String contextVar; 44 private Configuration config; 45 46 /** 47 * Construct given an XQuery expression string. 48 * @param query The XQuery expression 49 * @param contextVar The name of the context variable 50 * @param boundary The offset of the end of the prolog 51 */ 52 public XBeansXQuery(String query, String contextVar, Integer boundary) 53 { 54 config = new Configuration(); 55 config.setDOMLevel(2); 56 config.setTreeModel(net.sf.saxon.event.Builder.STANDARD_TREE); 57 StaticQueryContext sc = new StaticQueryContext(config); 58 this.contextVar = contextVar; 59 int bdry = boundary.intValue(); 60 //Saxon requires external variables at the end of the prolog... 61 query = (bdry == 0) ? 62 "declare variable $" + 63 contextVar + " external;" + query : 64 query.substring(0, bdry) + 65 "declare variable $" + 66 contextVar + " external;" + 67 query.substring(bdry); 68 try 69 { 70 xquery = sc.compileQuery(query); 71 } 72 catch (TransformerException e) 73 { 74 throw new XmlRuntimeException(e); 75 } 76 } 77 78 public List execQuery(Object node, Map variableBindings) 79 { 80 try 81 { 82 Node contextNode = (Node)node; 83 NodeInfo contextItem = 84 config.buildDocument(new DOMSource(contextNode)); 85 //config.unravel(new DOMSource(contextNode)); 86 DynamicQueryContext dc = new DynamicQueryContext(config); 87 dc.setContextItem(contextItem); 88 dc.setParameter(contextVar, contextItem); 89 // Set the other variables 90 if (variableBindings != null) 91 { 92 for (Iterator it = variableBindings.entrySet().iterator(); 93 it.hasNext(); ) 94 { 95 Map.Entry entry = (Map.Entry)it.next(); 96 String key = (String)entry.getKey(); 97 Object value = entry.getValue(); 98 if (value instanceof XmlTokenSource) 99 { 100 Node paramObject = ((XmlTokenSource)value).getDomNode(); 101 dc.setParameter(key, paramObject); 102 } 103 else if (value instanceof String) 104 dc.setParameter(key, value); 105 } 106 } 107 108 List saxonNodes = xquery.evaluate(dc); 109 for (ListIterator it = saxonNodes.listIterator(); it.hasNext(); ) 110 { 111 Object o = it.next(); 112 if(o instanceof NodeInfo) 113 { 114 Node n = NodeOverNodeInfo.wrap((NodeInfo)o); 115 it.set(n); 116 } 117 } 118 return saxonNodes; 119 } 120 catch (TransformerException e) 121 { 122 throw new RuntimeException("Error binding " + contextVar, e); 123 } 124 } 125 }