KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > repo > search > DocumentNavigator


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;
18
19 import java.io.Serializable JavaDoc;
20 import java.util.ArrayList JavaDoc;
21 import java.util.Collection JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Map JavaDoc;
25
26 import org.alfresco.model.ContentModel;
27 import org.alfresco.service.cmr.dictionary.DictionaryService;
28 import org.alfresco.service.cmr.repository.ChildAssociationRef;
29 import org.alfresco.service.cmr.repository.NodeRef;
30 import org.alfresco.service.cmr.repository.NodeService;
31 import org.alfresco.service.cmr.repository.StoreRef;
32 import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
33 import org.alfresco.service.cmr.search.SearchParameters;
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.alfresco.service.namespace.QNamePattern;
38 import org.alfresco.service.namespace.RegexQNamePattern;
39 import org.alfresco.util.ISO9075;
40 import org.jaxen.DefaultNavigator;
41 import org.jaxen.JaxenException;
42 import org.jaxen.UnsupportedAxisException;
43 import org.jaxen.XPath;
44
45 /**
46  * An implementation of the Jaxen xpath against the node service API
47  *
48  * This means any node service can do xpath style navigation. Given any context
49  * node we can navigate between nodes using xpath.
50  *
51  * This allows simple path navigation and much more.
52  *
53  * @author Andy Hind
54  *
55  */

56 public class DocumentNavigator extends DefaultNavigator
57 {
58     private static QName JCR_ROOT = QName.createQName("http://www.jcp.org/jcr/1.0", "root");
59     
60     private static QName JCR_PRIMARY_TYPE = QName.createQName("http://www.jcp.org/jcr/1.0", "primaryType");
61     
62     private static QName JCR_MIXIN_TYPES = QName.createQName("http://www.jcp.org/jcr/1.0", "mixinTypes");
63     
64     private static final long serialVersionUID = 3618984485740165427L;
65
66     private DictionaryService dictionaryService;
67
68     private NodeService nodeService;
69
70     private SearchService searchService;
71
72     private NamespacePrefixResolver nspr;
73
74     // Support classes to encapsulate stuff more akin to xml
75

76     public class Property
77     {
78         public final QName qname;
79
80         public final Serializable JavaDoc value;
81
82         public final NodeRef parent;
83
84         public Property(QName qname, Serializable JavaDoc value, NodeRef parent)
85         {
86             this.qname = qname;
87             this.value = value;
88             this.parent = parent;
89         }
90     }
91
92    
93     public class Namespace
94     {
95         public final String JavaDoc prefix;
96
97         public final String JavaDoc uri;
98
99         public Namespace(String JavaDoc prefix, String JavaDoc uri)
100         {
101             this.prefix = prefix;
102             this.uri = uri;
103         }
104     }
105     
106     public class JCRRootNodeChildAssociationRef extends ChildAssociationRef
107     {
108
109         /**
110          * Comment for <code>serialVersionUID</code>
111          */

112         private static final long serialVersionUID = -3890194577752476675L;
113
114         public JCRRootNodeChildAssociationRef(QName assocTypeQName, NodeRef parentRef, QName childQName, NodeRef childRef)
115         {
116             super(assocTypeQName, parentRef, childQName, childRef);
117         }
118         
119         public JCRRootNodeChildAssociationRef(QName assocTypeQName, NodeRef parentRef, QName childQName, NodeRef childRef, boolean isPrimary, int nthSibling)
120         {
121             super(assocTypeQName, parentRef, childQName, childRef, isPrimary, nthSibling);
122         }
123         
124     }
125
126     private boolean followAllParentLinks;
127     
128     private boolean useJCRRootNode;
129
130     /**
131      * @param dictionaryService
132      * used to resolve the <b>subtypeOf</b> function and other
133      * type-related functions
134      * @param nodeService
135      * the <tt>NodeService</tt> against which to execute
136      * @param searchService
137      * the service that helps resolve functions such as <b>like</b>
138      * and <b>contains</b>
139      * @param nspr
140      * resolves namespaces in the xpath
141      * @param followAllParentLinks
142      * true if the XPath should traverse all parent associations when
143      * going up the hierarchy; false if the only the primary
144      * parent-child association should be traversed
145      */

146     public DocumentNavigator(DictionaryService dictionaryService, NodeService nodeService, SearchService searchService,
147             NamespacePrefixResolver nspr, boolean followAllParentLinks, boolean useJCRRootNode)
148     {
149         super();
150         this.dictionaryService = dictionaryService;
151         this.nodeService = nodeService;
152         this.searchService = searchService;
153         this.nspr = nspr;
154         this.followAllParentLinks = followAllParentLinks;
155         this.useJCRRootNode = useJCRRootNode;
156     }
157
158     
159     
160     public NamespacePrefixResolver getNamespacePrefixResolver()
161     {
162         return nspr;
163     }
164
165
166
167     /**
168      * Allow this to be set as it commonly changes from one search to the next
169      *
170      * @param followAllParentLinks
171      * true
172      */

173     public void setFollowAllParentLinks(boolean followAllParentLinks)
174     {
175         this.followAllParentLinks = followAllParentLinks;
176     }
177
178     public String JavaDoc getAttributeName(Object JavaDoc o)
179     {
180         // Get the local name
181
String JavaDoc escapedLocalName = ISO9075.encode(((Property) o).qname.getLocalName());
182         if(escapedLocalName == ((Property) o).qname.getLocalName())
183         {
184             return escapedLocalName;
185         }
186         return escapedLocalName;
187     }
188
189     public String JavaDoc getAttributeNamespaceUri(Object JavaDoc o)
190     {
191         return ((Property) o).qname.getNamespaceURI();
192     }
193
194     public String JavaDoc getAttributeQName(Object JavaDoc o)
195     {
196         QName qName = ((Property) o).qname;
197         String JavaDoc escapedLocalName = ISO9075.encode(qName.getLocalName());
198         if(escapedLocalName == qName.getLocalName())
199         {
200             return qName.toString();
201         }
202         else
203         {
204             return QName.createQName(qName.getNamespaceURI(), escapedLocalName).toString();
205         }
206     }
207
208     public String JavaDoc getAttributeStringValue(Object JavaDoc o)
209     {
210         // Only the first property of multi-valued properties is displayed
211
// A multivalue attribute makes no sense in the xml world
212
return DefaultTypeConverter.INSTANCE.convert(String JavaDoc.class, ((Property) o).value);
213     }
214
215     public String JavaDoc getCommentStringValue(Object JavaDoc o)
216     {
217         // There is no attribute that is a comment
218
throw new UnsupportedOperationException JavaDoc("Comment string values are unsupported");
219     }
220
221     public String JavaDoc getElementName(Object JavaDoc o)
222     {
223         return ISO9075.encode(((ChildAssociationRef) o).getQName().getLocalName());
224     }
225
226     public String JavaDoc getElementNamespaceUri(Object JavaDoc o)
227     {
228         return ((ChildAssociationRef) o).getQName().getNamespaceURI();
229     }
230
231     public String JavaDoc getElementQName(Object JavaDoc o)
232     {
233         QName qName = ((ChildAssociationRef) o).getQName();
234         String JavaDoc escapedLocalName = ISO9075.encode(qName.getLocalName());
235         if(escapedLocalName == qName.getLocalName())
236         {
237             return qName.toString();
238         }
239         else
240         {
241             return QName.createQName(qName.getNamespaceURI(), escapedLocalName).toString();
242         }
243     }
244
245     public String JavaDoc getElementStringValue(Object JavaDoc o)
246     {
247         throw new UnsupportedOperationException JavaDoc("Element string values are unsupported");
248     }
249
250     public String JavaDoc getNamespacePrefix(Object JavaDoc o)
251     {
252         return ((Namespace) o).prefix;
253     }
254
255     public String JavaDoc getNamespaceStringValue(Object JavaDoc o)
256     {
257         return ((Namespace) o).uri;
258     }
259
260     public String JavaDoc getTextStringValue(Object JavaDoc o)
261     {
262         throw new UnsupportedOperationException JavaDoc("Text nodes are unsupported");
263     }
264
265     public boolean isAttribute(Object JavaDoc o)
266     {
267         return (o instanceof Property);
268     }
269
270     public boolean isComment(Object JavaDoc o)
271     {
272         return false;
273     }
274
275     public boolean isDocument(Object JavaDoc o)
276     {
277         if (!(o instanceof ChildAssociationRef))
278         {
279             return false;
280         }
281         ChildAssociationRef car = (ChildAssociationRef) o;
282         return (car.getParentRef() == null) && (car.getQName() == null);
283     }
284
285     public boolean isElement(Object JavaDoc o)
286     {
287         return (o instanceof ChildAssociationRef);
288     }
289
290     public boolean isNamespace(Object JavaDoc o)
291     {
292         return (o instanceof Namespace);
293     }
294
295     public boolean isProcessingInstruction(Object JavaDoc o)
296     {
297         return false;
298     }
299
300     public boolean isText(Object JavaDoc o)
301     {
302         return false;
303     }
304
305     public XPath parseXPath(String JavaDoc o) throws JaxenException
306     {
307         return new NodeServiceXPath(o, this, null);
308     }
309
310     // Basic navigation support
311

312     public Iterator JavaDoc getAttributeAxisIterator(Object JavaDoc o) throws UnsupportedAxisException
313     {
314         ArrayList JavaDoc<Property> properties = new ArrayList JavaDoc<Property>();
315         NodeRef nodeRef = ((ChildAssociationRef) o).getChildRef();
316         Map JavaDoc<QName, Serializable JavaDoc> map = nodeService.getProperties(nodeRef);
317         for (QName qName : map.keySet())
318         {
319             if(map.get(qName) instanceof Collection JavaDoc)
320             {
321                 for(Serializable JavaDoc ob : (Collection JavaDoc<Serializable JavaDoc>) map.get(qName))
322                 {
323                     Property property = new Property(qName, ob, nodeRef);
324                     properties.add(property);
325                 }
326             }
327             else
328             {
329                 Property property = new Property(qName, map.get(qName), nodeRef);
330                 properties.add(property);
331             }
332         }
333         if(useJCRRootNode)
334         {
335             properties.add(new Property(JCR_PRIMARY_TYPE, nodeService.getType(nodeRef), nodeRef));
336             for(QName mixin : nodeService.getAspects(nodeRef))
337             {
338                 properties.add(new Property(JCR_MIXIN_TYPES, mixin, nodeRef));
339             }
340         }
341         
342         return properties.iterator();
343     }
344
345     public Iterator JavaDoc getChildAxisIterator(Object JavaDoc o) throws UnsupportedAxisException
346     {
347         // Iterator of ChildAxisRef
348
ChildAssociationRef assocRef = (ChildAssociationRef) o;
349         NodeRef childRef = assocRef.getChildRef();
350         List JavaDoc<ChildAssociationRef> list;
351         // Add compatability for JCR 170 by including the root node.
352
if(isDocument(o) && useJCRRootNode)
353         {
354             list = new ArrayList JavaDoc<ChildAssociationRef>(1);
355             list.add(new JCRRootNodeChildAssociationRef(ContentModel.ASSOC_CHILDREN, childRef, JCR_ROOT, childRef, true, 0));
356         }
357         else
358         {
359             list = nodeService.getChildAssocs(childRef);
360         }
361         return list.iterator();
362     }
363
364     public Iterator JavaDoc getNamespaceAxisIterator(Object JavaDoc o) throws UnsupportedAxisException
365     {
366         // Iterator of Namespace
367
ArrayList JavaDoc<Namespace> namespaces = new ArrayList JavaDoc<Namespace>();
368         for (String JavaDoc prefix : nspr.getPrefixes())
369         {
370             String JavaDoc uri = nspr.getNamespaceURI(prefix);
371             Namespace ns = new Namespace(prefix, uri);
372             namespaces.add(ns);
373         }
374         return namespaces.iterator();
375     }
376
377     public Iterator JavaDoc getParentAxisIterator(Object JavaDoc o) throws UnsupportedAxisException
378     {
379         ArrayList JavaDoc<ChildAssociationRef> parents = new ArrayList JavaDoc<ChildAssociationRef>(1);
380         // Iterator of ??
381
if (o instanceof ChildAssociationRef)
382         {
383             ChildAssociationRef contextRef = (ChildAssociationRef) o;
384             if (contextRef.getParentRef() != null)
385             {
386                 if (followAllParentLinks)
387                 {
388                     for (ChildAssociationRef car : nodeService.getParentAssocs(contextRef.getChildRef()))
389                     {
390                         parents.add(nodeService.getPrimaryParent(car.getParentRef()));
391                     }
392                 }
393                 else
394                 {
395                     parents.add(nodeService.getPrimaryParent(contextRef.getParentRef()));
396                 }
397             }
398         }
399         if (o instanceof Property)
400         {
401             Property p = (Property) o;
402             parents.add(nodeService.getPrimaryParent(p.parent));
403         }
404         return parents.iterator();
405     }
406
407     public Object JavaDoc getDocumentNode(Object JavaDoc o)
408     {
409         ChildAssociationRef assocRef = (ChildAssociationRef) o;
410         StoreRef storeRef = assocRef.getChildRef().getStoreRef();
411         return new ChildAssociationRef(null, null, null, nodeService.getRootNode(storeRef));
412     }
413
414     public Object JavaDoc getNode(NodeRef nodeRef)
415     {
416         return nodeService.getPrimaryParent(nodeRef);
417     }
418     
419     public List JavaDoc<ChildAssociationRef> getNode(NodeRef nodeRef, QNamePattern qNamePattern)
420     {
421         return nodeService.getParentAssocs(nodeRef, RegexQNamePattern.MATCH_ALL, qNamePattern);
422     }
423
424     public Boolean JavaDoc like(NodeRef childRef, QName qname, String JavaDoc sqlLikePattern, boolean includeFTS)
425     {
426         return searchService.like(childRef, qname, sqlLikePattern, includeFTS);
427     }
428
429     public Boolean JavaDoc contains(NodeRef childRef, QName qname, String JavaDoc sqlLikePattern, SearchParameters.Operator defaultOperator)
430     {
431         return searchService.contains(childRef, qname, sqlLikePattern, defaultOperator);
432     }
433
434     public Boolean JavaDoc isSubtypeOf(NodeRef nodeRef, QName typeQName)
435     {
436         // get the type of the node
437
QName nodeTypeQName = nodeService.getType(nodeRef);
438         return dictionaryService.isSubClass(nodeTypeQName, typeQName);
439     }
440 }
441
Popular Tags