View Javadoc

1   /*
2    * Copyright 2001-2005 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package net.sf.nxqd.xmldb;
17  
18  import java.io.File;
19  import java.io.StringReader;
20  import java.util.Iterator;
21  import java.util.List;
22  import java.util.Map;
23  import java.util.HashMap;
24  import java.util.ArrayList;
25  import java.util.Enumeration;
26  import java.util.logging.Level;
27  import java.util.logging.Logger;
28  
29  import javax.xml.transform.TransformerException;
30  import javax.xml.transform.sax.SAXSource;
31  import javax.xml.transform.stream.StreamSource;
32  
33  import org.xml.sax.InputSource;
34  import org.xmldb.api.base.Collection;
35  import org.xmldb.api.base.ErrorCodes;
36  import org.xmldb.api.base.Resource;
37  import org.xmldb.api.base.ResourceSet;
38  import org.xmldb.api.base.XMLDBException;
39  import org.xmldb.api.modules.XPathQueryService;
40  import org.xmldb.api.reference.ResourceSetImpl;
41  import org.xmldb.api.reference.modules.XMLResourceImpl;
42  import org.xmldb.api.base.Resource;
43  import org.xmldb.api.modules.XMLResource;
44  
45  import net.sf.nxqd.NxqdContainer;
46  import net.sf.nxqd.NxqdException;
47  
48  /**
49   * The class <code>NxqdXPathQueryService</code> is an implemenation of
50   * <code>org.xmldb.api.modules.XPathQueryService</code>.
51   *
52   * @see org.xmldb.api.modules.XPathQueryService
53   *
54   * @author <a href="mailto:webhiker@sourceforge.net">webhiker</a>
55   * @version 1.0
56   */
57  public class NxqdXPathQueryService extends NxqdService implements XPathQueryService {
58      private static Logger logger = Logger.getLogger(NxqdXPathQueryService.class.getName());
59  
60      /**
61       *  
62       */
63      public NxqdXPathQueryService(NxqdCollection parent) throws XMLDBException {
64  	super(NxqdXPathQueryService.class.getName(),"1.0");
65  	setCollection(parent);
66      }
67  
68      /**
69       * @see org.xmldb.api.modules.XPathQueryService#setNamespace(java.lang.String,
70       *      java.lang.String)
71       */
72      public void setNamespace(String prefix, String uri) throws XMLDBException {
73          setProperty(prefix, uri);
74      }
75  
76      /**
77       * @see org.xmldb.api.modules.XPathQueryService#getNamespace(java.lang.String)
78       */
79      public String getNamespace(String prefix) throws XMLDBException {
80          return getProperty(prefix);
81      }
82  
83      /**
84       * @see org.xmldb.api.modules.XPathQueryService#removeNamespace(java.lang.String)
85       */
86      public void removeNamespace(String prefix) throws XMLDBException {
87          removeProperty(prefix);
88      }
89  
90      /**
91       * @see org.xmldb.api.modules.XPathQueryService#clearNamespaces()
92       */
93      public void clearNamespaces() throws XMLDBException {
94  	String key;
95          for (Enumeration e = keys(); e.hasMoreElements() ;) {
96  	    key = e.nextElement().toString();
97  	    if ((!key.equals(NAME))&&
98  		(!key.equals(VERSION))) {
99  		removeProperty(key);
100 	    }
101 	}
102     }
103 
104     private Map getNamespaceMap() {
105 	Map namespaceMap = new HashMap();
106 	String key;
107         for (Enumeration e = keys(); e.hasMoreElements() ;) {
108 	    key = e.nextElement().toString();
109 	    if ((!key.equals(NAME))&&
110 		(!key.equals(VERSION))) {
111 		namespaceMap.put(key, getProperty(key));
112 	    }
113 	}
114 	return namespaceMap;
115     }
116 
117     /**
118      * @see org.xmldb.api.modules.XPathQueryService#query(java.lang.String)
119      * 
120      */
121     public ResourceSet query(String query) throws XMLDBException {
122         logger.fine("query("+query+")");
123         ResourceSet result = new ResourceSetImpl(getCollection());
124 	queryCollection(query,
125 			(NxqdCollection)getCollection(),
126 			getNamespaceMap(),
127 			result,
128 			true);
129         return result;
130     }
131 
132     public static void queryCollection(final String query, 
133 				       final NxqdCollection collection,
134 				       final Map namespaces,
135 				       ResourceSet results,
136 				       final boolean recurseChildren)
137 	throws XMLDBException {
138 	try {
139 	    // query this collection's documents
140 	    NxqdContainer container = collection.getContainer();
141 	    List currRes = internalQuery(collection.getContainer(),
142 					 query,
143 					 namespaces);
144 	    Resource resource;
145 	    for (int i = 0; i < currRes.size(); i++) {
146 		resource = new NxqdXMLResource(collection,
147 					       collection.getName()+Integer.toString(i),
148 					       XMLResource.RESOURCE_TYPE);
149 		results.addResource(resource);
150 	    }
151 	    if (recurseChildren) {
152 		// now query the children of this collection and add each result
153 		// to the growing list of results
154 		// TODO - trim off a level from the XPath statements???
155 		String resNames[] = collection.listChildCollections();
156 		Collection child;
157 		//logger.info("checking children>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
158 		for (int i = 0; i < resNames.length; i++) {
159 		    //logger.info("checking child>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"+resNames[i]);
160 		    queryCollection(query,
161 				    (NxqdCollection)collection.getChildCollection(resNames[i]),
162 				    namespaces,
163 				    results,
164 				    recurseChildren);
165 		    // logger.info("got result>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"+results.getSize());
166 		}
167 	    }
168 	}
169 	catch (NxqdException ne) {
170 	    ne.printStackTrace();
171 	    throw new XMLDBException(ErrorCodes.VENDOR_ERROR,
172 				     "Error querying Collection :" + ne.getMessage(),
173 				     ne);
174 	}
175     }
176 
177     /**
178      * @see org.xmldb.api.modules.XPathQueryService#queryResource(java.lang.String,
179      *      java.lang.String)
180      */
181     public ResourceSet queryResource(String id, String query)
182 	throws XMLDBException {
183         ResourceSet result = new ResourceSetImpl(getCollection());
184 	queryCollection("doc(\""+((NxqdCollection)getCollection()).getContainer().getName()+"/"+id+"\")"+query,
185 			(NxqdCollection)getCollection(),
186 			getNamespaceMap(),
187 			result,
188 			false);
189         return result;
190     }
191 
192     /**
193      * The <code>internalQuery</code> method executes the specified queryExpression
194      * on this container. If not already containing a collection(...) or
195      * document(...) portion, it will be automatically appended.
196      *
197      * @param queryExpression a <code>String</code> value
198      * @return a <code>List</code> value which will contain XML fragments
199      * as <code>String</code> objects.
200      * @exception NxqdException if an error occurs
201      */
202     private static List internalQuery(NxqdContainer container,
203 				      final String queryExpression) throws NxqdException {
204 	return internalQuery(container, queryExpression, null);
205     }
206 
207 
208     /**
209      * The <code>internalQuery</code> method executes the specified XPath queryExpression
210      * on this container. If not already containing a collection(...) or
211      * document(...) portion, it will be automatically appended.
212      *
213      * @param queryExpression a <code>String</code> value
214      * @param nameSpaces a <code>Map</code> value
215      * @return a <code>List</code> value which will contain XML fragments
216      * as <code>String</code> objects.
217      * @exception NxqdException if an error occurs
218      */
219     private static List internalQuery(NxqdContainer container,
220 				      final String queryExpression,
221 		      final Map nameSpaces) throws NxqdException {
222 	// convert regular query into Sleepycat form, unless the user already used
223 	// this form
224 	String sleepycatQuery;
225 	if ((queryExpression.toLowerCase().indexOf("collection(")>=0)||
226 	    ((queryExpression.toLowerCase().indexOf("doc(")>=0))) {
227 	    sleepycatQuery = queryExpression;
228 	}
229 	else {
230 	    sleepycatQuery = "(collection(\"" + container.getName() + "\"))"+queryExpression;
231 	}
232 	
233 	return container.getNxqdManager().query(sleepycatQuery, nameSpaces);
234     }
235 
236 }