KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > jcr > item > NodeImpl


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.jcr.item;
18
19 import java.io.InputStream JavaDoc;
20 import java.io.Serializable JavaDoc;
21 import java.util.ArrayList JavaDoc;
22 import java.util.Calendar JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Map JavaDoc;
25 import java.util.Set JavaDoc;
26
27 import javax.jcr.AccessDeniedException;
28 import javax.jcr.InvalidItemStateException;
29 import javax.jcr.Item;
30 import javax.jcr.ItemExistsException;
31 import javax.jcr.ItemNotFoundException;
32 import javax.jcr.ItemVisitor;
33 import javax.jcr.MergeException;
34 import javax.jcr.NoSuchWorkspaceException;
35 import javax.jcr.Node;
36 import javax.jcr.NodeIterator;
37 import javax.jcr.PathNotFoundException;
38 import javax.jcr.Property;
39 import javax.jcr.PropertyIterator;
40 import javax.jcr.RepositoryException;
41 import javax.jcr.UnsupportedRepositoryOperationException;
42 import javax.jcr.Value;
43 import javax.jcr.ValueFormatException;
44 import javax.jcr.lock.Lock;
45 import javax.jcr.lock.LockException;
46 import javax.jcr.nodetype.ConstraintViolationException;
47 import javax.jcr.nodetype.NoSuchNodeTypeException;
48 import javax.jcr.nodetype.NodeDefinition;
49 import javax.jcr.nodetype.NodeType;
50 import javax.jcr.version.Version;
51 import javax.jcr.version.VersionException;
52 import javax.jcr.version.VersionHistory;
53
54 import org.alfresco.error.AlfrescoRuntimeException;
55 import org.alfresco.jcr.api.JCRNodeRef;
56 import org.alfresco.jcr.dictionary.ClassMap;
57 import org.alfresco.jcr.dictionary.NodeDefinitionImpl;
58 import org.alfresco.jcr.dictionary.NodeTypeImpl;
59 import org.alfresco.jcr.item.property.PropertyResolver;
60 import org.alfresco.jcr.session.SessionImpl;
61 import org.alfresco.jcr.util.JCRProxyFactory;
62 import org.alfresco.jcr.version.VersionHistoryImpl;
63 import org.alfresco.jcr.version.VersionImpl;
64 import org.alfresco.model.ContentModel;
65 import org.alfresco.repo.version.VersionModel;
66 import org.alfresco.service.cmr.dictionary.AspectDefinition;
67 import org.alfresco.service.cmr.dictionary.ChildAssociationDefinition;
68 import org.alfresco.service.cmr.dictionary.ClassDefinition;
69 import org.alfresco.service.cmr.dictionary.DictionaryService;
70 import org.alfresco.service.cmr.lock.LockService;
71 import org.alfresco.service.cmr.lock.LockStatus;
72 import org.alfresco.service.cmr.lock.LockType;
73 import org.alfresco.service.cmr.repository.ChildAssociationRef;
74 import org.alfresco.service.cmr.repository.NodeRef;
75 import org.alfresco.service.cmr.repository.NodeService;
76 import org.alfresco.service.cmr.repository.Path;
77 import org.alfresco.service.cmr.repository.StoreRef;
78 import org.alfresco.service.cmr.repository.Path.Element;
79 import org.alfresco.service.cmr.search.SearchService;
80 import org.alfresco.service.cmr.version.VersionService;
81 import org.alfresco.service.namespace.QName;
82 import org.alfresco.service.namespace.RegexQNamePattern;
83 import org.alfresco.util.ParameterCheck;
84
85
86 /**
87  * Alfresco Implementation of a JCR Node
88  *
89  * @author David Caruana
90  */

91 public class NodeImpl extends ItemImpl implements Node
92 {
93     /** Node Reference to wrap */
94     private NodeRef nodeRef;
95
96     /** Proxy */
97     private Node proxy = null;
98     
99     
100     /**
101      * Construct
102      *
103      * @param context session context
104      * @param nodeRef node reference to wrap
105      */

106     public NodeImpl(SessionImpl context, NodeRef nodeRef)
107     {
108         super(context);
109         this.nodeRef = nodeRef;
110     }
111
112     /**
113      * Get Node Proxy
114      *
115      * @param nodeImpl
116      * @return
117      */

118     @Override JavaDoc
119     public Node getProxy()
120     {
121         if (proxy == null)
122         {
123             proxy = (Node)JCRProxyFactory.create(this, Node.class, session);
124         }
125         return proxy;
126     }
127     
128     /* (non-Javadoc)
129      * @see javax.jcr.Node#addNode(java.lang.String)
130      */

131     public Node addNode(String JavaDoc relPath) throws ItemExistsException, PathNotFoundException, VersionException, ConstraintViolationException, LockException, RepositoryException
132     {
133         return addNode(relPath, null);
134     }
135
136     /* (non-Javadoc)
137      * @see javax.jcr.Node#addNode(java.lang.String, java.lang.String)
138      */

139     public Node addNode(String JavaDoc relPath, String JavaDoc primaryNodeTypeName) throws ItemExistsException, PathNotFoundException, NoSuchNodeTypeException, LockException, VersionException, ConstraintViolationException, RepositoryException
140     {
141         ParameterCheck.mandatoryString("relPath", relPath);
142         NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
143         DictionaryService dictionaryService = session.getRepositoryImpl().getServiceRegistry().getDictionaryService();
144         
145         // Determine parent node reference and new node name
146
Path path = new JCRPath(session.getNamespaceResolver(), relPath).getPath();
147         QName nodeName = null;
148         NodeRef parentRef = null;
149         if (path.size() == 1)
150         {
151             parentRef = nodeRef;
152             nodeName = ((JCRPath.SimpleElement)path.get(0)).getQName();
153         }
154         else
155         {
156             Path parentPath = path.subPath(path.size() -2);
157             parentRef = ItemResolver.getNodeRef(session, nodeRef, parentPath.toPrefixString(session.getNamespaceResolver()));
158             if (parentRef == null)
159             {
160                 throw new PathNotFoundException("Path '" + relPath + "' does not exist from node " + nodeRef);
161             }
162             nodeName = ((JCRPath.SimpleElement)path.get(path.size() -1)).getQName();
163         }
164
165         // Check for invalid node name
166
// TODO: Replace with proper name validation
167
if (nodeName.getLocalName().indexOf('[') != -1 || nodeName.getLocalName().indexOf(']') != -1)
168         {
169             throw new RepositoryException("Node name '" + nodeName + "' is invalid");
170         }
171
172         // Determine child association to add node under
173
ChildAssociationDefinition childAssocDef = null;
174         QName nodeType = null;
175         if (primaryNodeTypeName == null || primaryNodeTypeName.length() == 0)
176         {
177             childAssocDef = getDefaultChildAssocDefForParent(nodeService, dictionaryService, parentRef);
178             nodeType = childAssocDef.getTargetClass().getName();
179         }
180         else
181         {
182             nodeType = QName.createQName(primaryNodeTypeName, session.getNamespaceResolver());
183             childAssocDef = getNodeTypeChildAssocDefForParent(nodeService, dictionaryService, parentRef, nodeType);
184         }
185
186         // Create node
187
// Note: Integrity exception will be thrown when the node is saved
188
ChildAssociationRef childRef = nodeService.createNode(parentRef, childAssocDef.getName(), nodeName, nodeType);
189         NodeImpl nodeImpl = new NodeImpl(session, childRef.getChildRef());
190         return nodeImpl.getProxy();
191     }
192
193     /**
194      * Get the default child association definition for the specified node
195      *
196      * @param nodeService node service
197      * @param dictionaryService dictionary service
198      * @param nodeRef node reference
199      * @return child association definition
200      */

201     private ChildAssociationDefinition getDefaultChildAssocDefForParent(NodeService nodeService, DictionaryService dictionaryService, NodeRef nodeRef)
202     {
203         QName type = nodeService.getType(nodeRef);
204         Set JavaDoc<QName> aspects = nodeService.getAspects(nodeRef);
205         ClassDefinition classDef = dictionaryService.getAnonymousType(type, aspects);
206         Map JavaDoc<QName, ChildAssociationDefinition> childAssocs = classDef.getChildAssociations();
207         if (childAssocs.size() != 1)
208         {
209             throw new AlfrescoRuntimeException("Cannot determine node type for child within parent " + nodeRef);
210         }
211         ChildAssociationDefinition childAssocDef = childAssocs.values().iterator().next();
212         return childAssocDef;
213     }
214     
215     /**
216      * Get the child association definition whose target matches the specified node type for the specified node
217      *
218      * @param nodeService node service
219      * @param dictionaryService dictionary service
220      * @param nodeRef node reference
221      * @param nodeType node type to find child association definition for
222      * @return child association definition
223      */

224     private ChildAssociationDefinition getNodeTypeChildAssocDefForParent(NodeService nodeService, DictionaryService dictionaryService, NodeRef nodeRef, QName nodeType)
225     {
226         ChildAssociationDefinition nodeTypeChildAssocDef = null;
227         QName type = nodeService.getType(nodeRef);
228         Set JavaDoc<QName> aspects = nodeService.getAspects(nodeRef);
229         ClassDefinition classDef = dictionaryService.getAnonymousType(type, aspects);
230         Map JavaDoc<QName, ChildAssociationDefinition> childAssocs = classDef.getChildAssociations();
231         for (ChildAssociationDefinition childAssocDef : childAssocs.values())
232         {
233             if (dictionaryService.isSubClass(nodeType, childAssocDef.getTargetClass().getName()))
234             {
235                 if (nodeTypeChildAssocDef != null)
236                 {
237                     throw new AlfrescoRuntimeException("Cannot determine child association for node type '" + nodeType + " within parent " + nodeRef);
238                 }
239                 nodeTypeChildAssocDef = childAssocDef;
240             }
241         }
242         if (nodeTypeChildAssocDef == null)
243         {
244             throw new AlfrescoRuntimeException("Cannot determine child association for node type '" + nodeType + " within parent " + nodeRef);
245         }
246         return nodeTypeChildAssocDef;
247     }
248     
249     /* (non-Javadoc)
250      * @see javax.jcr.Item#remove()
251      */

252     public void remove() throws VersionException, LockException, ConstraintViolationException, RepositoryException
253     {
254         NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
255         
256         // Note: remove the primary child association, therefore forcing a delete of the node (including any secondary child
257
// associations)
258
ChildAssociationRef assocRef = nodeService.getPrimaryParent(nodeRef);
259         NodeRef parentRef = assocRef.getParentRef();
260         if (parentRef == null)
261         {
262             throw new ConstraintViolationException("Cannot remove the root node");
263         }
264         nodeService.removeChild(parentRef, nodeRef);
265     }
266     
267     /* (non-Javadoc)
268      * @see javax.jcr.Node#orderBefore(java.lang.String, java.lang.String)
269      */

270     public void orderBefore(String JavaDoc srcChildRelPath, String JavaDoc destChildRelPath) throws UnsupportedRepositoryOperationException, VersionException, ConstraintViolationException, ItemNotFoundException, LockException, RepositoryException
271     {
272         throw new UnsupportedRepositoryOperationException();
273     }
274
275     /* (non-Javadoc)
276      * @see javax.jcr.Node#setProperty(java.lang.String, javax.jcr.Value)
277      */

278     public Property setProperty(String JavaDoc name, Value value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException
279     {
280         QName propertyName = QName.createQName(name, session.getNamespaceResolver());
281         PropertyImpl property = new PropertyImpl(this, propertyName);
282         property.setPropertyValue(value, -1);
283         return (value == null ) ? null : property;
284     }
285
286     /* (non-Javadoc)
287      * @see javax.jcr.Node#setProperty(java.lang.String, javax.jcr.Value, int)
288      */

289     public Property setProperty(String JavaDoc name, Value value, int type) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException
290     {
291         QName propertyName = QName.createQName(name, session.getNamespaceResolver());
292         PropertyImpl property = new PropertyImpl(this, propertyName);
293         property.setPropertyValue(value, type);
294         return (value == null ) ? null : property;
295     }
296
297     /* (non-Javadoc)
298      * @see javax.jcr.Node#setProperty(java.lang.String, javax.jcr.Value[])
299      */

300     public Property setProperty(String JavaDoc name, Value[] values) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException
301     {
302         QName propertyName = QName.createQName(name, session.getNamespaceResolver());
303         PropertyImpl property = new PropertyImpl(this, propertyName);
304         property.setPropertyValue(values, -1);
305         return (values == null ) ? null : property;
306     }
307
308     /* (non-Javadoc)
309      * @see javax.jcr.Node#setProperty(java.lang.String, javax.jcr.Value[], int)
310      */

311     public Property setProperty(String JavaDoc name, Value[] values, int type) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException
312     {
313         QName propertyName = QName.createQName(name, session.getNamespaceResolver());
314         PropertyImpl property = new PropertyImpl(this, propertyName);
315         property.setPropertyValue(values, type);
316         return (values == null ) ? null : property;
317     }
318
319     /* (non-Javadoc)
320      * @see javax.jcr.Node#setProperty(java.lang.String, java.lang.String[])
321      */

322     public Property setProperty(String JavaDoc name, String JavaDoc[] values) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException
323     {
324         QName propertyName = QName.createQName(name, session.getNamespaceResolver());
325         PropertyImpl property = new PropertyImpl(this, propertyName);
326         property.setPropertyValue(values, -1);
327         return (values == null ) ? null : property;
328     }
329
330     /* (non-Javadoc)
331      * @see javax.jcr.Node#setProperty(java.lang.String, java.lang.String[], int)
332      */

333     public Property setProperty(String JavaDoc name, String JavaDoc[] values, int type) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException
334     {
335         QName propertyName = QName.createQName(name, session.getNamespaceResolver());
336         PropertyImpl property = new PropertyImpl(this, propertyName);
337         property.setPropertyValue(values, type);
338         return (values == null ) ? null : property;
339     }
340
341     /* (non-Javadoc)
342      * @see javax.jcr.Node#setProperty(java.lang.String, java.lang.String)
343      */

344     public Property setProperty(String JavaDoc name, String JavaDoc value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException
345     {
346         QName propertyName = QName.createQName(name, session.getNamespaceResolver());
347         PropertyImpl property = new PropertyImpl(this, propertyName);
348         property.setPropertyValue(value, -1);
349         return (value == null ) ? null : property;
350     }
351
352     /* (non-Javadoc)
353      * @see javax.jcr.Node#setProperty(java.lang.String, java.lang.String, int)
354      */

355     public Property setProperty(String JavaDoc name, String JavaDoc value, int type) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException
356     {
357         QName propertyName = QName.createQName(name, session.getNamespaceResolver());
358         PropertyImpl property = new PropertyImpl(this, propertyName);
359         property.setPropertyValue(value, type);
360         return (value == null ) ? null : property;
361     }
362
363     /* (non-Javadoc)
364      * @see javax.jcr.Node#setProperty(java.lang.String, java.io.InputStream)
365      */

366     public Property setProperty(String JavaDoc name, InputStream JavaDoc value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException
367     {
368         QName propertyName = QName.createQName(name, session.getNamespaceResolver());
369         PropertyImpl property = new PropertyImpl(this, propertyName);
370         property.setPropertyValue(value, -1);
371         return (value == null ) ? null : property;
372     }
373
374     /* (non-Javadoc)
375      * @see javax.jcr.Node#setProperty(java.lang.String, boolean)
376      */

377     public Property setProperty(String JavaDoc name, boolean value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException
378     {
379         QName propertyName = QName.createQName(name, session.getNamespaceResolver());
380         PropertyImpl property = new PropertyImpl(this, propertyName);
381         property.setPropertyValue(value, -1);
382         return property;
383     }
384
385     /* (non-Javadoc)
386      * @see javax.jcr.Node#setProperty(java.lang.String, double)
387      */

388     public Property setProperty(String JavaDoc name, double value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException
389     {
390         QName propertyName = QName.createQName(name, session.getNamespaceResolver());
391         PropertyImpl property = new PropertyImpl(this, propertyName);
392         property.setPropertyValue(value, -1);
393         return property;
394     }
395
396     /* (non-Javadoc)
397      * @see javax.jcr.Node#setProperty(java.lang.String, long)
398      */

399     public Property setProperty(String JavaDoc name, long value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException
400     {
401         QName propertyName = QName.createQName(name, session.getNamespaceResolver());
402         PropertyImpl property = new PropertyImpl(this, propertyName);
403         property.setPropertyValue(value, -1);
404         return property;
405     }
406
407     /* (non-Javadoc)
408      * @see javax.jcr.Node#setProperty(java.lang.String, java.util.Calendar)
409      */

410     public Property setProperty(String JavaDoc name, Calendar JavaDoc value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException
411     {
412         QName propertyName = QName.createQName(name, session.getNamespaceResolver());
413         PropertyImpl property = new PropertyImpl(this, propertyName);
414         property.setPropertyValue((value == null) ? null : value.getTime(), -1);
415         return (value == null ) ? null : property;
416     }
417
418     /* (non-Javadoc)
419      * @see javax.jcr.Node#setProperty(java.lang.String, javax.jcr.Node)
420      */

421     public Property setProperty(String JavaDoc name, Node value) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException
422     {
423         QName propertyName = QName.createQName(name, session.getNamespaceResolver());
424         PropertyImpl property = new PropertyImpl(this, propertyName);
425         property.setPropertyValue((value == null) ? null : JCRNodeRef.getNodeRef(value), -1);
426         return (value == null ) ? null : property;
427     }
428
429     /* (non-Javadoc)
430      * @see javax.jcr.Node#getNode(java.lang.String)
431      */

432     public Node getNode(String JavaDoc relPath) throws PathNotFoundException, RepositoryException
433     {
434         NodeImpl nodeImpl = ItemResolver.findNode(session, nodeRef, relPath);
435         return nodeImpl.getProxy();
436     }
437
438     /* (non-Javadoc)
439      * @see javax.jcr.Node#getNodes()
440      */

441     public NodeIterator getNodes() throws RepositoryException
442     {
443         NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
444         List JavaDoc<ChildAssociationRef> childAssocs = nodeService.getChildAssocs(nodeRef);
445         NodeIterator iterator = new ChildAssocNodeIteratorImpl(session, childAssocs);
446         return iterator;
447     }
448
449     /* (non-Javadoc)
450      * @see javax.jcr.Node#getNodes(java.lang.String)
451      */

452     public NodeIterator getNodes(String JavaDoc namePattern) throws RepositoryException
453     {
454         NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
455         JCRPatternMatch match = new JCRPatternMatch(namePattern, session.getNamespaceResolver());
456         List JavaDoc<ChildAssociationRef> childAssocs = nodeService.getChildAssocs(nodeRef, RegexQNamePattern.MATCH_ALL, match);
457         NodeIterator iterator = new ChildAssocNodeIteratorImpl(session, childAssocs);
458         return iterator;
459     }
460
461     /* (non-Javadoc)
462      * @see javax.jcr.Node#getProperty(java.lang.String)
463      */

464     public Property getProperty(String JavaDoc relPath) throws PathNotFoundException, RepositoryException
465     {
466         JCRPath jcrPath = new JCRPath(session.getNamespaceResolver(), relPath);
467         Path path = jcrPath.getPath();
468         if (path.size() == 1)
469         {
470             QName propertyName = ((JCRPath.SimpleElement)path.get(0)).getQName();
471             return PropertyResolver.createProperty(this, propertyName).getProxy();
472         }
473
474         ItemImpl itemImpl = ItemResolver.findItem(session, nodeRef, relPath);
475         if (itemImpl == null || !(itemImpl instanceof PropertyImpl))
476         {
477             throw new PathNotFoundException("Property path " + relPath + " not found from node " + nodeRef);
478         }
479         return ((PropertyImpl)itemImpl).getProxy();
480     }
481
482     /* (non-Javadoc)
483      * @see javax.jcr.Node#getProperties()
484      */

485     public PropertyIterator getProperties() throws RepositoryException
486     {
487         List JavaDoc<PropertyImpl> properties = PropertyResolver.createProperties(this, null);
488         PropertyIterator iterator = new PropertyListIterator(properties);
489         return iterator;
490     }
491
492     /* (non-Javadoc)
493      * @see javax.jcr.Node#getProperties(java.lang.String)
494      */

495     public PropertyIterator getProperties(String JavaDoc namePattern) throws RepositoryException
496     {
497         JCRPatternMatch match = new JCRPatternMatch(namePattern, session.getNamespaceResolver());
498         List JavaDoc<PropertyImpl> properties = PropertyResolver.createProperties(this, match);
499         PropertyIterator iterator = new PropertyListIterator(properties);
500         return iterator;
501     }
502
503     /* (non-Javadoc)
504      * @see javax.jcr.Node#getPrimaryItem()
505      */

506     public Item getPrimaryItem() throws ItemNotFoundException, RepositoryException
507     {
508         // Note: Alfresco does not support the notion of primary item
509
throw new ItemNotFoundException();
510     }
511
512     /* (non-Javadoc)
513      * @see javax.jcr.Node#getUUID()
514      */

515     public String JavaDoc getUUID() throws UnsupportedRepositoryOperationException, RepositoryException
516     {
517         return nodeRef.getId();
518     }
519
520     /* (non-Javadoc)
521      * @see javax.jcr.Node#getIndex()
522      */

523     public int getIndex() throws RepositoryException
524     {
525         int index = 1;
526         String JavaDoc name = getName();
527         if (name != null)
528         {
529             // TODO: Look at more efficient approach
530
SearchService searchService = session.getRepositoryImpl().getServiceRegistry().getSearchService();
531             List JavaDoc<NodeRef> siblings = searchService.selectNodes(nodeRef, "../" + name, null, session.getNamespaceResolver(), false);
532             for (NodeRef sibling : siblings)
533             {
534                 if (sibling.equals(nodeRef))
535                 {
536                     break;
537                 }
538                 index++;
539             }
540         }
541         return index;
542     }
543
544     /* (non-Javadoc)
545      * @see javax.jcr.Node#getReferences()
546      */

547     public PropertyIterator getReferences() throws RepositoryException
548     {
549         // Note: Lookup for references not supported for now
550
return new PropertyListIterator(new ArrayList JavaDoc<PropertyImpl>());
551     }
552
553     /* (non-Javadoc)
554      * @see javax.jcr.Node#hasNode(java.lang.String)
555      */

556     public boolean hasNode(String JavaDoc relPath) throws RepositoryException
557     {
558         return ItemResolver.nodeExists(session, nodeRef, relPath);
559     }
560
561     /* (non-Javadoc)
562      * @see javax.jcr.Node#hasProperty(java.lang.String)
563      */

564     public boolean hasProperty(String JavaDoc relPath) throws RepositoryException
565     {
566         JCRPath jcrPath = new JCRPath(session.getNamespaceResolver(), relPath);
567         Path path = jcrPath.getPath();
568         if (path.size() == 1)
569         {
570             QName propertyName = ((JCRPath.SimpleElement)path.get(0)).getQName();
571             return PropertyResolver.hasProperty(this, propertyName);
572         }
573
574         return ItemResolver.itemExists(session, nodeRef, relPath);
575     }
576
577     /* (non-Javadoc)
578      * @see javax.jcr.Node#hasNodes()
579      */

580     public boolean hasNodes() throws RepositoryException
581     {
582         NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
583         List JavaDoc<ChildAssociationRef> childAssocs = nodeService.getChildAssocs(nodeRef);
584         return childAssocs.size() > 0;
585     }
586
587     /* (non-Javadoc)
588      * @see javax.jcr.Node#hasProperties()
589      */

590     public boolean hasProperties() throws RepositoryException
591     {
592         // Note: nt:base has a mandatory primaryType property for which we don't have security access control
593
return true;
594     }
595
596     /* (non-Javadoc)
597      * @see javax.jcr.Node#getPrimaryNodeType()
598      */

599     public NodeType getPrimaryNodeType() throws RepositoryException
600     {
601         NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
602         QName type = nodeService.getType(nodeRef);
603         return session.getTypeManager().getNodeTypeImpl(type);
604     }
605
606     /* (non-Javadoc)
607      * @see javax.jcr.Node#getMixinNodeTypes()
608      */

609     public NodeType[] getMixinNodeTypes() throws RepositoryException
610     {
611         // Add aspects defined by node
612
NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
613         Set JavaDoc<QName> aspects = nodeService.getAspects(nodeRef);
614         NodeType[] nodeTypes = new NodeType[aspects.size() + 1];
615         int i = 0;
616         for (QName aspect : aspects)
617         {
618             nodeTypes[i++] = session.getTypeManager().getNodeTypeImpl(aspect);
619             QName mixin = ClassMap.convertClassToType(aspect);
620             if (mixin != null)
621             {
622                 nodeTypes[i++] = session.getTypeManager().getNodeTypeImpl(mixin);
623             }
624         }
625         
626         return nodeTypes;
627     }
628
629     /* (non-Javadoc)
630      * @see javax.jcr.Node#isNodeType(java.lang.String)
631      */

632     public boolean isNodeType(String JavaDoc nodeTypeName) throws RepositoryException
633     {
634         QName nodeType = QName.createQName(nodeTypeName, session.getNamespaceResolver());
635         
636         // is it one of standard types
637
if (nodeType.equals(NodeTypeImpl.MIX_REFERENCEABLE) || nodeType.equals(NodeTypeImpl.NT_BASE))
638         {
639             return true;
640         }
641
642         // map JCR mixins to Alfresco mixins
643
QName nodeClass = ClassMap.convertTypeToClass(nodeType);
644         if (nodeClass == null)
645         {
646             nodeClass = nodeType;
647         }
648         
649         // determine via class hierarchy
650
NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
651         DictionaryService dictionaryService = session.getRepositoryImpl().getServiceRegistry().getDictionaryService();
652
653         // first, check the type
654
QName type = nodeService.getType(nodeRef);
655         if (dictionaryService.isSubClass(nodeClass, type))
656         {
657             return true;
658         }
659         
660         // second, check the aspects
661
Set JavaDoc<QName> aspects = nodeService.getAspects(nodeRef);
662         for (QName aspect : aspects)
663         {
664             if (dictionaryService.isSubClass(nodeClass, aspect))
665             {
666                 return true;
667             }
668         }
669
670         // no, its definitely not of the specified type
671
return false;
672     }
673
674     /* (non-Javadoc)
675      * @see javax.jcr.Node#addMixin(java.lang.String)
676      */

677     public void addMixin(String JavaDoc mixinName) throws NoSuchNodeTypeException, VersionException, ConstraintViolationException, LockException, RepositoryException
678     {
679         // map JCR mixins to Alfresco mixins
680
QName mixin = QName.createQName(mixinName, session.getNamespaceResolver());
681         QName aspect = ClassMap.convertTypeToClass(mixin);
682         if (aspect == null)
683         {
684             aspect = mixin;
685         }
686         
687         // retrieve aspect definition
688
DictionaryService dictionaryService = session.getRepositoryImpl().getServiceRegistry().getDictionaryService();
689         AspectDefinition aspectDef = dictionaryService.getAspect(aspect);
690         if (aspectDef == null)
691         {
692             throw new NoSuchNodeTypeException("Unknown mixin name '" + mixinName + "'");
693         }
694
695         // apply aspect
696
ClassMap.AddMixin addMixin = ClassMap.getAddMixin(aspect);
697         Map JavaDoc<QName, Serializable JavaDoc> initialProperties = addMixin.preAddMixin(session, nodeRef);
698         NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
699         nodeService.addAspect(nodeRef, aspect, initialProperties);
700         addMixin.postAddMixin(session, nodeRef);
701     }
702
703     /* (non-Javadoc)
704      * @see javax.jcr.Node#removeMixin(java.lang.String)
705      */

706     public void removeMixin(String JavaDoc mixinName) throws NoSuchNodeTypeException, VersionException, ConstraintViolationException, LockException, RepositoryException
707     {
708         // map JCR mixins to Alfresco mixins
709
QName mixin = QName.createQName(mixinName, session.getNamespaceResolver());
710         QName aspect = ClassMap.convertTypeToClass(mixin);
711         if (aspect == null)
712         {
713             aspect = mixin;
714         }
715         
716         // retrieve aspect definition
717
DictionaryService dictionaryService = session.getRepositoryImpl().getServiceRegistry().getDictionaryService();
718         AspectDefinition aspectDef = dictionaryService.getAspect(aspect);
719         if (aspectDef == null)
720         {
721             throw new NoSuchNodeTypeException("Unknown mixin name '" + mixinName + "'");
722         }
723
724         // check the node actually has the mixin
725
NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
726         Set JavaDoc<QName> nodeAspects = nodeService.getAspects(nodeRef);
727         if (!nodeAspects.contains(aspect))
728         {
729             throw new NoSuchNodeTypeException("Node " + nodeRef.getId() + " does not have the mixin " + mixin);
730         }
731         
732         // remove aspect
733
ClassMap.RemoveMixin removeMixin = ClassMap.getRemoveMixin(aspect);
734         removeMixin.preRemoveMixin(session, nodeRef);
735         nodeService.removeAspect(nodeRef, aspect);
736         removeMixin.postRemoveMixin(session, nodeRef);
737     }
738
739     /* (non-Javadoc)
740      * @see javax.jcr.Node#canAddMixin(java.lang.String)
741      */

742     public boolean canAddMixin(String JavaDoc mixinName) throws NoSuchNodeTypeException, RepositoryException
743     {
744         // map JCR mixins to Alfresco mixins
745
QName mixin = QName.createQName(mixinName, session.getNamespaceResolver());
746         QName aspect = ClassMap.convertTypeToClass(mixin);
747         if (aspect == null)
748         {
749             aspect = mixin;
750         }
751         
752         // retrieve aspect definition
753
DictionaryService dictionaryService = session.getRepositoryImpl().getServiceRegistry().getDictionaryService();
754         AspectDefinition aspectDef = dictionaryService.getAspect(aspect);
755         if (aspectDef == null)
756         {
757             throw new NoSuchNodeTypeException("Unknown mixin name '" + mixinName + "'");
758         }
759
760         // TODO: check for write permission
761

762         // check for locked node
763
LockService lockService = session.getRepositoryImpl().getServiceRegistry().getLockService();
764         LockStatus lockStatus = lockService.getLockStatus(nodeRef);
765         if (lockStatus == LockStatus.LOCKED)
766         {
767             return false;
768         }
769         
770         // mixin addition is allowed
771
return true;
772     }
773
774     /* (non-Javadoc)
775      * @see javax.jcr.Node#getDefinition()
776      */

777     public NodeDefinition getDefinition() throws RepositoryException
778     {
779         NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
780         DictionaryService dictionaryService = session.getRepositoryImpl().getServiceRegistry().getDictionaryService();
781         ChildAssociationRef childAssocRef = nodeService.getPrimaryParent(this.nodeRef);
782         ChildAssociationDefinition childAssocDef = (ChildAssociationDefinition)dictionaryService.getAssociation(childAssocRef.getTypeQName());
783         NodeDefinition nodeDef = new NodeDefinitionImpl(session.getTypeManager(), childAssocDef);
784         return nodeDef;
785     }
786
787     /* (non-Javadoc)
788      * @see javax.jcr.Node#checkin()
789      */

790     public Version checkin() throws VersionException, UnsupportedRepositoryOperationException, InvalidItemStateException, LockException, RepositoryException
791     {
792         // check this node is versionable
793
NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
794         if (!nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE))
795         {
796             throw new UnsupportedRepositoryOperationException("Node " + nodeRef + " is not versionable");
797         }
798
799         Version version = null;
800         if (!isCheckedOut())
801         {
802             // return current version
803
version = getBaseVersion();
804         }
805         else
806         {
807             // create a new version snapshot
808
VersionService versionService = session.getRepositoryImpl().getServiceRegistry().getVersionService();
809             org.alfresco.service.cmr.version.Version versionNode = versionService.createVersion(nodeRef, null);
810             org.alfresco.service.cmr.version.VersionHistory versionHistory = versionService.getVersionHistory(nodeRef);
811             version = new VersionImpl(new VersionHistoryImpl(session, versionHistory), versionNode).getProxy();
812             
813             // set to 'read only'
814
LockService lockService = session.getRepositoryImpl().getServiceRegistry().getLockService();
815             lockService.lock(nodeRef, LockType.READ_ONLY_LOCK);
816         }
817         
818         return version;
819     }
820
821     /* (non-Javadoc)
822      * @see javax.jcr.Node#checkout()
823      */

824     public void checkout() throws UnsupportedRepositoryOperationException, LockException, RepositoryException
825     {
826         // check this node is versionable
827
NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
828         if (!nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE))
829         {
830             throw new UnsupportedRepositoryOperationException("Node " + nodeRef + " is not versionable");
831         }
832
833         // remove 'read only' lock
834
if (!isCheckedOut())
835         {
836             LockService lockService = session.getRepositoryImpl().getServiceRegistry().getLockService();
837             lockService.unlock(nodeRef);
838         }
839     }
840
841     /* (non-Javadoc)
842      * @see javax.jcr.Node#doneMerge(javax.jcr.version.Version)
843      */

844     public void doneMerge(Version version) throws VersionException, InvalidItemStateException, UnsupportedRepositoryOperationException, RepositoryException
845     {
846         throw new UnsupportedRepositoryOperationException();
847     }
848
849     /* (non-Javadoc)
850      * @see javax.jcr.Node#cancelMerge(javax.jcr.version.Version)
851      */

852     public void cancelMerge(Version version) throws VersionException, InvalidItemStateException, UnsupportedRepositoryOperationException, RepositoryException
853     {
854         throw new UnsupportedRepositoryOperationException();
855     }
856
857     /* (non-Javadoc)
858      * @see javax.jcr.Node#update(java.lang.String)
859      */

860     public void update(String JavaDoc srcWorkspaceName) throws NoSuchWorkspaceException, AccessDeniedException, LockException, InvalidItemStateException, RepositoryException
861     {
862         throw new UnsupportedRepositoryOperationException();
863     }
864
865     /* (non-Javadoc)
866      * @see javax.jcr.Node#merge(java.lang.String, boolean)
867      */

868     public NodeIterator merge(String JavaDoc srcWorkspace, boolean bestEffort) throws NoSuchWorkspaceException, AccessDeniedException, MergeException, LockException, InvalidItemStateException, RepositoryException
869     {
870         throw new UnsupportedRepositoryOperationException();
871     }
872
873     /* (non-Javadoc)
874      * @see javax.jcr.Node#getCorrespondingNodePath(java.lang.String)
875      */

876     public String JavaDoc getCorrespondingNodePath(String JavaDoc workspaceName) throws ItemNotFoundException, NoSuchWorkspaceException, AccessDeniedException, RepositoryException
877     {
878         throw new UnsupportedRepositoryOperationException();
879     }
880
881     /* (non-Javadoc)
882      * @see javax.jcr.Node#isCheckedOut()
883      */

884     public boolean isCheckedOut() throws RepositoryException
885     {
886         NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
887         if (!nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE))
888         {
889             // it's not versionable, therefore it's checked-out and writable
890
// TODO: Do not yet take into consideration versionable ancestor
891
return true;
892         }
893
894         // it's versionable, use the lock to determine if it's checked-out
895
LockService lockService = session.getRepositoryImpl().getServiceRegistry().getLockService();
896         LockType lockType = lockService.getLockType(nodeRef);
897         if (lockType == null)
898         {
899             // it's not locked at all
900
return true;
901         }
902
903         // it's only checked-in when a read-only locked
904
return (lockType.equals(LockType.READ_ONLY_LOCK)) ? false : true;
905     }
906
907     /* (non-Javadoc)
908      * @see javax.jcr.Node#restore(java.lang.String, boolean)
909      */

910     public void restore(String JavaDoc versionName, boolean removeExisting) throws VersionException, ItemExistsException, UnsupportedRepositoryOperationException, LockException, InvalidItemStateException, RepositoryException
911     {
912         // check this node is versionable
913
NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
914         if (!nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE))
915         {
916             throw new UnsupportedRepositoryOperationException("Node " + nodeRef + " is not versionable");
917         }
918
919         // retrieve version for label
920
VersionService versionService = session.getRepositoryImpl().getServiceRegistry().getVersionService();
921         org.alfresco.service.cmr.version.VersionHistory versionHistory = versionService.getVersionHistory(nodeRef);
922         org.alfresco.service.cmr.version.Version version = versionHistory.getVersion(versionName);
923         if (version == null)
924         {
925             throw new VersionException("Version name " + versionName + " does not exist in the version history of node " + nodeRef);
926         }
927
928         // unlock if necessary
929
LockService lockService = session.getRepositoryImpl().getServiceRegistry().getLockService();
930         LockType lockType = lockService.getLockType(nodeRef);
931         if (lockType != null)
932         {
933             lockService.unlock(nodeRef);
934         }
935         
936         // revert to version
937
versionService.revert(nodeRef, version);
938         lockService.lock(nodeRef, LockType.READ_ONLY_LOCK);
939     }
940
941     /* (non-Javadoc)
942      * @see javax.jcr.Node#restore(javax.jcr.version.Version, boolean)
943      */

944     public void restore(Version version, boolean removeExisting) throws VersionException, ItemExistsException, UnsupportedRepositoryOperationException, LockException, RepositoryException
945     {
946         restore(version.getName(), removeExisting);
947     }
948
949     /* (non-Javadoc)
950      * @see javax.jcr.Node#restore(javax.jcr.version.Version, java.lang.String, boolean)
951      */

952     public void restore(Version version, String JavaDoc relPath, boolean removeExisting) throws PathNotFoundException, ItemExistsException, VersionException, ConstraintViolationException, UnsupportedRepositoryOperationException, LockException, InvalidItemStateException, RepositoryException
953     {
954         throw new UnsupportedRepositoryOperationException();
955     }
956
957     /* (non-Javadoc)
958      * @see javax.jcr.Node#restoreByLabel(java.lang.String, boolean)
959      */

960     public void restoreByLabel(String JavaDoc versionLabel, boolean removeExisting) throws VersionException, ItemExistsException, UnsupportedRepositoryOperationException, LockException, InvalidItemStateException, RepositoryException
961     {
962         throw new UnsupportedRepositoryOperationException();
963     }
964
965     /* (non-Javadoc)
966      * @see javax.jcr.Node#getVersionHistory()
967      */

968     public VersionHistory getVersionHistory() throws UnsupportedRepositoryOperationException, RepositoryException
969     {
970         // check this node is versionable
971
NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
972         if (!nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE))
973         {
974             throw new UnsupportedRepositoryOperationException("Node " + nodeRef + " is not versionable");
975         }
976
977         // construct version history
978
VersionService versionService = session.getRepositoryImpl().getServiceRegistry().getVersionService();
979         org.alfresco.service.cmr.version.VersionHistory versionHistory = versionService.getVersionHistory(nodeRef);
980         return new VersionHistoryImpl(session, versionHistory).getProxy();
981     }
982
983     /* (non-Javadoc)
984      * @see javax.jcr.Node#getBaseVersion()
985      */

986     public Version getBaseVersion() throws UnsupportedRepositoryOperationException, RepositoryException
987     {
988         // check this node is versionable
989
NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
990         if (!nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE))
991         {
992             throw new UnsupportedRepositoryOperationException("Node " + nodeRef + " is not versionable");
993         }
994
995         // construct version
996
VersionService versionService = session.getRepositoryImpl().getServiceRegistry().getVersionService();
997         org.alfresco.service.cmr.version.VersionHistory versionHistory = versionService.getVersionHistory(nodeRef);
998         org.alfresco.service.cmr.version.Version version = versionService.getCurrentVersion(nodeRef);
999         return new VersionImpl(new VersionHistoryImpl(session, versionHistory), version).getProxy();
1000    }
1001
1002    /* (non-Javadoc)
1003     * @see javax.jcr.Node#lock(boolean, boolean)
1004     */

1005    public Lock lock(boolean isDeep, boolean isSessionScoped) throws UnsupportedRepositoryOperationException, LockException, AccessDeniedException, InvalidItemStateException, RepositoryException
1006    {
1007        // note: alfresco does not yet support session scoped locks
1008
if (isSessionScoped)
1009        {
1010            throw new UnsupportedRepositoryOperationException("Session scope locking is not supported.");
1011        }
1012        
1013        // check this node is lockable
1014
NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
1015        if (!nodeService.hasAspect(nodeRef, ContentModel.ASPECT_LOCKABLE))
1016        {
1017            throw new LockException("Node " + nodeRef + " does is not lockable.");
1018        }
1019        
1020        // lock the node
1021
LockService lockService = session.getRepositoryImpl().getServiceRegistry().getLockService();
1022        lockService.lock(nodeRef, LockType.WRITE_LOCK, 0, isDeep);
1023
1024        // return lock
1025
return new LockImpl(this).getProxy();
1026    }
1027
1028    /* (non-Javadoc)
1029     * @see javax.jcr.Node#getLock()
1030     */

1031    public Lock getLock() throws UnsupportedRepositoryOperationException, LockException, AccessDeniedException, RepositoryException
1032    {
1033        // check this node is lockable
1034
NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
1035        if (!nodeService.hasAspect(nodeRef, ContentModel.ASPECT_LOCKABLE))
1036        {
1037            throw new LockException("Node " + nodeRef + " does is not lockable.");
1038        }
1039
1040        // return lock
1041
return new LockImpl(this).getProxy();
1042    }
1043
1044    /* (non-Javadoc)
1045     * @see javax.jcr.Node#unlock()
1046     */

1047    public void unlock() throws UnsupportedRepositoryOperationException, LockException, AccessDeniedException, InvalidItemStateException, RepositoryException
1048    {
1049        // check this node is lockable
1050
NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
1051        if (!nodeService.hasAspect(nodeRef, ContentModel.ASPECT_LOCKABLE))
1052        {
1053            throw new LockException("Node " + nodeRef + " does is not lockable.");
1054        }
1055
1056        // unlock
1057
LockService lockService = session.getRepositoryImpl().getServiceRegistry().getLockService();
1058        lockService.unlock(nodeRef, true);
1059    }
1060
1061    /* (non-Javadoc)
1062     * @see javax.jcr.Node#holdsLock()
1063     */

1064    public boolean holdsLock() throws RepositoryException
1065    {
1066        // note: for now, alfresco doesn't distinguish between lock holder and locked
1067
return isLocked();
1068    }
1069
1070    /* (non-Javadoc)
1071     * @see javax.jcr.Node#isLocked()
1072     */

1073    public boolean isLocked() throws RepositoryException
1074    {
1075        LockService lockService = session.getRepositoryImpl().getServiceRegistry().getLockService();
1076        LockStatus lockStatus = lockService.getLockStatus(getNodeRef());
1077        return lockStatus.equals(LockStatus.LOCK_OWNER) || lockStatus.equals(LockStatus.LOCKED);
1078    }
1079
1080    /* (non-Javadoc)
1081     * @see javax.jcr.Item#getName()
1082     */

1083    public String JavaDoc getName() throws RepositoryException
1084    {
1085        NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
1086        ChildAssociationRef parentAssoc = nodeService.getPrimaryParent(nodeRef);
1087        QName childName = parentAssoc.getQName();
1088        return (childName == null) ? "" : childName.toPrefixString(session.getNamespaceResolver());
1089    }
1090
1091    /* (non-Javadoc)
1092     * @see javax.jcr.Item#isNode()
1093     */

1094    public boolean isNode()
1095    {
1096        return true;
1097    }
1098
1099    /* (non-Javadoc)
1100     * @see javax.jcr.Item#getParent()
1101     */

1102    public Node getParent() throws ItemNotFoundException, AccessDeniedException, RepositoryException
1103    {
1104        NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
1105        ChildAssociationRef parentAssoc = nodeService.getPrimaryParent(nodeRef);
1106        if (parentAssoc == null || parentAssoc.getParentRef() == null)
1107        {
1108            // TODO: Distinguish between ItemNotFound and AccessDenied
1109
throw new ItemNotFoundException("Parent of node " + nodeRef + " does not exist.");
1110        }
1111        NodeImpl nodeImpl = new NodeImpl(session, parentAssoc.getParentRef());
1112        return nodeImpl.getProxy();
1113    }
1114
1115    /* (non-Javadoc)
1116     * @see javax.jcr.Item#getPath()
1117     */

1118    public String JavaDoc getPath() throws RepositoryException
1119    {
1120        NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
1121        SearchService searchService = session.getRepositoryImpl().getServiceRegistry().getSearchService();
1122        Path path = nodeService.getPath(nodeRef);
1123        
1124        // Add indexes for same name siblings
1125
// TODO: Look at more efficient approach
1126
for (int i = path.size() - 1; i >= 0; i--)
1127        {
1128            Path.Element pathElement = path.get(i);
1129            if (i > 0 && pathElement instanceof Path.ChildAssocElement)
1130            {
1131                int index = 1;
1132                String JavaDoc searchPath = path.subPath(i).toPrefixString(session.getNamespaceResolver());
1133                List JavaDoc<NodeRef> siblings = searchService.selectNodes(nodeRef, searchPath, null, session.getNamespaceResolver(), false);
1134                if (siblings.size() > 1)
1135                {
1136                    ChildAssociationRef childAssoc = ((Path.ChildAssocElement)pathElement).getRef();
1137                    NodeRef childRef = childAssoc.getChildRef();
1138                    for (NodeRef sibling : siblings)
1139                    {
1140                        if (sibling.equals(childRef))
1141                        {
1142                            childAssoc.setNthSibling(index);
1143                            break;
1144                        }
1145                        index++;
1146                    }
1147                }
1148            }
1149        }
1150        
1151        return path.toPrefixString(session.getNamespaceResolver());
1152    }
1153
1154    /* (non-Javadoc)
1155     * @see javax.jcr.Item#getDepth()
1156     */

1157    public int getDepth() throws RepositoryException
1158    {
1159        NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
1160        Path path = nodeService.getPath(nodeRef);
1161        // Note: Root is at depth 0
1162
return path.size() -1;
1163    }
1164
1165    /* (non-Javadoc)
1166     * @see javax.jcr.Item#getAncestor(int)
1167     */

1168    public Item getAncestor(int depth) throws ItemNotFoundException, AccessDeniedException, RepositoryException
1169    {
1170        // Retrieve primary parent path for node
1171
NodeService nodeService = session.getRepositoryImpl().getServiceRegistry().getNodeService();
1172        Path path = nodeService.getPath(nodeRef);
1173        if (depth < 0 || depth > (path.size() - 1))
1174        {
1175            throw new ItemNotFoundException("Ancestor at depth " + depth + " not found for node " + nodeRef);
1176        }
1177
1178        // Extract path element at requested depth
1179
Element element = path.get(depth);
1180        if (!(element instanceof Path.ChildAssocElement))
1181        {
1182            throw new RepositoryException("Path element at depth " + depth + " is not a node");
1183        }
1184        Path.ChildAssocElement childAssocElement = (Path.ChildAssocElement)element;
1185        
1186        // Create node
1187
NodeRef ancestorNodeRef = childAssocElement.getRef().getChildRef();
1188        NodeImpl nodeImpl = new NodeImpl(session, ancestorNodeRef);
1189        return nodeImpl.getProxy();
1190    }
1191
1192    /* (non-Javadoc)
1193     * @see javax.jcr.Item#isSame(javax.jcr.Item)
1194     */

1195    public boolean isSame(Item otherItem) throws RepositoryException
1196    {
1197        return getProxy().equals(otherItem);
1198    }
1199    
1200    /* (non-Javadoc)
1201     * @see javax.jcr.Item#accept(javax.jcr.ItemVisitor)
1202     */

1203    public void accept(ItemVisitor visitor) throws RepositoryException
1204    {
1205        visitor.visit(getProxy());
1206    }
1207    
1208    /**
1209     * Gets the Alfresco Node Reference
1210     *
1211     * @return the node reference
1212     */

1213    public NodeRef getNodeRef()
1214    {
1215        return nodeRef;
1216    }
1217
1218    @Override JavaDoc
1219    public boolean equals(Object JavaDoc obj)
1220    {
1221        if (obj == this)
1222        {
1223            return true;
1224        }
1225        if (!(obj instanceof NodeImpl))
1226        {
1227            return false;
1228        }
1229        NodeImpl other = (NodeImpl)obj;
1230        return this.nodeRef.equals(other.nodeRef);
1231    }
1232
1233    @Override JavaDoc
1234    public int hashCode()
1235    {
1236        return nodeRef.hashCode();
1237    }
1238    
1239}
1240
Popular Tags