1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
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
153
154
155 String resNames[] = collection.listChildCollections();
156 Collection child;
157
158 for (int i = 0; i < resNames.length; i++) {
159
160 queryCollection(query,
161 (NxqdCollection)collection.getChildCollection(resNames[i]),
162 namespaces,
163 results,
164 recurseChildren);
165
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
223
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 }