KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > repo > search > impl > NodeSearcher


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.repo.search.impl;
18
19 import java.io.Serializable JavaDoc;
20 import java.util.ArrayList JavaDoc;
21 import java.util.Collections JavaDoc;
22 import java.util.Comparator JavaDoc;
23 import java.util.HashSet JavaDoc;
24 import java.util.List JavaDoc;
25
26 import org.alfresco.repo.search.DocumentNavigator;
27 import org.alfresco.repo.search.NodeServiceXPath;
28 import org.alfresco.service.cmr.dictionary.DictionaryService;
29 import org.alfresco.service.cmr.repository.ChildAssociationRef;
30 import org.alfresco.service.cmr.repository.NodeRef;
31 import org.alfresco.service.cmr.repository.NodeService;
32 import org.alfresco.service.cmr.repository.XPathException;
33 import org.alfresco.service.cmr.search.QueryParameterDefinition;
34 import org.alfresco.service.cmr.search.SearchService;
35 import org.alfresco.service.namespace.NamespacePrefixResolver;
36 import org.alfresco.service.namespace.QName;
37 import org.jaxen.JaxenException;
38
39 /**
40  * Helper class that walks a node hierarchy.
41  * <p>
42  * Some searcher methods on
43  * {@link org.alfresco.service.cmr.search.SearchService} can use this directly
44  * as its only dependencies are
45  * {@link org.alfresco.service.cmr.repository.NodeService},
46  * {@link org.alfresco.service.cmr.dictionary.DictionaryService} and a
47  * {@link org.alfresco.service.cmr.search.SearchService}
48  *
49  * @author Derek Hulley
50  */

51 public class NodeSearcher
52 {
53     private NodeService nodeService;
54
55     private DictionaryService dictionaryService;
56
57     private SearchService searchService;
58
59     public NodeSearcher(NodeService nodeService, DictionaryService dictionaryService, SearchService searchService)
60     {
61         this.nodeService = nodeService;
62         this.dictionaryService = dictionaryService;
63         this.searchService = searchService;
64     }
65
66     /**
67      * @see NodeServiceXPath
68      */

69     public synchronized List JavaDoc<NodeRef> selectNodes(NodeRef contextNodeRef, String JavaDoc xpathIn,
70             QueryParameterDefinition[] paramDefs, NamespacePrefixResolver namespacePrefixResolver,
71             boolean followAllParentLinks, String JavaDoc language)
72     {
73         try
74         {
75             String JavaDoc xpath = xpathIn;
76             boolean useJCRXPath = language.equalsIgnoreCase(SearchService.LANGUAGE_JCR_XPATH);
77
78             List JavaDoc<AttributeOrder> order = null;
79
80             // replace element
81
if (useJCRXPath)
82             {
83                 order = new ArrayList JavaDoc<AttributeOrder>();
84                 // We do not allow variable substitution with this pattern
85
xpath = xpath.replaceAll("element\\(\\s*(\\*|\\w*:\\w*)\\s*,\\s*(\\*|\\w*:\\w*)\\s*\\)",
86                         "$1[subtypeOf(\"$2\")]");
87                 String JavaDoc split[] = xpath.split("order\\s*by\\s*", 2);
88                 xpath = split[0];
89
90                 if (split.length > 1 && split[1].length() > 0)
91                 {
92                     String JavaDoc clauses[] = split[1].split("\\s,\\s");
93
94                     for (String JavaDoc clause : clauses)
95                     {
96                         if (clause.startsWith("@"))
97                         {
98                             String JavaDoc attribute = clause.replaceFirst("@(\\p{Alpha}[\\w:]*)(?:\\s+(.*))?", "$1");
99                             String JavaDoc sort = clause.replaceFirst("@(\\p{Alpha}[\\w:]*)(?:\\s+(.*))?", "$2");
100
101                             if (sort.length() == 0)
102                             {
103                                 sort = "ascending";
104                             }
105
106                             QName attributeQName = QName.createQName(attribute, namespacePrefixResolver);
107                             order.add(new AttributeOrder(attributeQName, sort.equalsIgnoreCase("ascending")));
108                         }
109                         else if (clause.startsWith("jcr:score"))
110                         {
111                             // ignore jcr:score ordering
112
}
113                         else
114                         {
115                             throw new IllegalArgumentException JavaDoc("Malformed order by expression " + split[1]);
116                         }
117                     }
118
119                 }
120
121             }
122
123             DocumentNavigator documentNavigator = new DocumentNavigator(dictionaryService, nodeService, searchService,
124                     namespacePrefixResolver, followAllParentLinks, useJCRXPath);
125             NodeServiceXPath nsXPath = new NodeServiceXPath(xpath, documentNavigator, paramDefs);
126             for (String JavaDoc prefix : namespacePrefixResolver.getPrefixes())
127             {
128                 nsXPath.addNamespace(prefix, namespacePrefixResolver.getNamespaceURI(prefix));
129             }
130             List JavaDoc list = nsXPath.selectNodes(nodeService.getPrimaryParent(contextNodeRef));
131             HashSet JavaDoc<NodeRef> unique = new HashSet JavaDoc<NodeRef>(list.size());
132             for (Object JavaDoc o : list)
133             {
134                 if (o instanceof ChildAssociationRef)
135                 {
136                     unique.add(((ChildAssociationRef) o).getChildRef());
137                 }
138                 else if (o instanceof DocumentNavigator.Property)
139                 {
140                     unique.add(((DocumentNavigator.Property) o).parent);
141                 }
142                 else
143                 {
144                     throw new XPathException("Xpath expression must only select nodes");
145                 }
146             }
147
148             List JavaDoc<NodeRef> answer = new ArrayList JavaDoc<NodeRef>(unique.size());
149             answer.addAll(unique);
150             if (order != null)
151             {
152                 orderNodes(answer, order);
153                 for(NodeRef node : answer)
154                 {
155                     StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
156                     for (AttributeOrder attOrd : order)
157                     {
158                         buffer.append(" ").append(nodeService.getProperty(node, attOrd.attribute));
159                     }
160                 }
161             }
162             return answer;
163         }
164         catch (JaxenException e)
165         {
166             throw new XPathException("Error executing xpath: \n" + " xpath: " + xpathIn, e);
167         }
168     }
169
170     private void orderNodes(List JavaDoc<NodeRef> answer, List JavaDoc<AttributeOrder> order)
171     {
172         Collections.sort(answer, new NodeRefComparator(nodeService, order));
173     }
174
175     static class NodeRefComparator implements Comparator JavaDoc<NodeRef>
176     {
177         List JavaDoc<AttributeOrder> order;
178         NodeService nodeService;
179         
180         NodeRefComparator(NodeService nodeService, List JavaDoc<AttributeOrder> order)
181         {
182             this.nodeService = nodeService;
183             this.order = order;
184         }
185         
186         @SuppressWarnings JavaDoc("unchecked")
187         public int compare(NodeRef n1, NodeRef n2)
188         {
189             for (AttributeOrder attributeOrder : order)
190             {
191                 Serializable JavaDoc o1 = nodeService.getProperty(n1, attributeOrder.attribute);
192                 Serializable JavaDoc o2 = nodeService.getProperty(n2, attributeOrder.attribute);
193
194                 if (o1 == null)
195                 {
196                     if (o2 == null)
197                     {
198                         continue;
199                     }
200                     else
201                     {
202                         return attributeOrder.ascending ? -1 : 1;
203                     }
204                 }
205                 else
206                 {
207                     if (o2 == null)
208                     {
209                         return attributeOrder.ascending ? 1 : -1;
210                     }
211                     else
212                     {
213                         if ((o1 instanceof Comparable JavaDoc) && (o2 instanceof Comparable JavaDoc))
214                         {
215                             return (attributeOrder.ascending ? 1 : -1) * ((Comparable JavaDoc)o1).compareTo((Comparable JavaDoc) o2);
216                         }
217                         else
218                         {
219                             continue;
220                         }
221                     }
222                 }
223
224             }
225             return 0;
226         }
227     }
228
229     /**
230      * @see NodeServiceXPath
231      */

232     public List JavaDoc<Serializable JavaDoc> selectProperties(NodeRef contextNodeRef, String JavaDoc xpath,
233             QueryParameterDefinition[] paramDefs, NamespacePrefixResolver namespacePrefixResolver,
234             boolean followAllParentLinks, String JavaDoc language)
235     {
236         try
237         {
238             boolean useJCRXPath = language.equalsIgnoreCase(SearchService.LANGUAGE_JCR_XPATH);
239
240             DocumentNavigator documentNavigator = new DocumentNavigator(dictionaryService, nodeService, searchService,
241                     namespacePrefixResolver, followAllParentLinks, useJCRXPath);
242             NodeServiceXPath nsXPath = new NodeServiceXPath(xpath, documentNavigator, paramDefs);
243             for (String JavaDoc prefix : namespacePrefixResolver.getPrefixes())
244             {
245                 nsXPath.addNamespace(prefix, namespacePrefixResolver.getNamespaceURI(prefix));
246             }
247             List JavaDoc list = nsXPath.selectNodes(nodeService.getPrimaryParent(contextNodeRef));
248             List JavaDoc<Serializable JavaDoc> answer = new ArrayList JavaDoc<Serializable JavaDoc>(list.size());
249             for (Object JavaDoc o : list)
250             {
251                 if (!(o instanceof DocumentNavigator.Property))
252                 {
253                     throw new XPathException("Xpath expression must only select nodes");
254                 }
255                 answer.add(((DocumentNavigator.Property) o).value);
256             }
257             return answer;
258         }
259         catch (JaxenException e)
260         {
261             throw new XPathException("Error executing xpath", e);
262         }
263     }
264
265     private static class AttributeOrder
266     {
267         QName attribute;
268
269         boolean ascending;
270
271         AttributeOrder(QName attribute, boolean ascending)
272         {
273             this.attribute = attribute;
274             this.ascending = ascending;
275         }
276     }
277 }
278
Popular Tags