KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > repo > model > filefolder > FileFolderServiceImpl


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.model.filefolder;
18
19 import java.io.Serializable JavaDoc;
20 import java.util.ArrayList JavaDoc;
21 import java.util.Collections JavaDoc;
22 import java.util.HashMap JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.List JavaDoc;
25 import java.util.Map JavaDoc;
26
27 import org.alfresco.error.AlfrescoRuntimeException;
28 import org.alfresco.model.ContentModel;
29 import org.alfresco.repo.search.QueryParameterDefImpl;
30 import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
31 import org.alfresco.service.cmr.dictionary.DictionaryService;
32 import org.alfresco.service.cmr.model.FileExistsException;
33 import org.alfresco.service.cmr.model.FileFolderService;
34 import org.alfresco.service.cmr.model.FileInfo;
35 import org.alfresco.service.cmr.model.FileNotFoundException;
36 import org.alfresco.service.cmr.repository.ChildAssociationRef;
37 import org.alfresco.service.cmr.repository.ContentData;
38 import org.alfresco.service.cmr.repository.ContentReader;
39 import org.alfresco.service.cmr.repository.ContentService;
40 import org.alfresco.service.cmr.repository.ContentWriter;
41 import org.alfresco.service.cmr.repository.CopyService;
42 import org.alfresco.service.cmr.repository.InvalidNodeRefException;
43 import org.alfresco.service.cmr.repository.MimetypeService;
44 import org.alfresco.service.cmr.repository.NodeRef;
45 import org.alfresco.service.cmr.repository.NodeService;
46 import org.alfresco.service.cmr.repository.Path;
47 import org.alfresco.service.cmr.search.QueryParameterDefinition;
48 import org.alfresco.service.cmr.search.SearchService;
49 import org.alfresco.service.namespace.NamespaceService;
50 import org.alfresco.service.namespace.QName;
51 import org.alfresco.util.SearchLanguageConversion;
52 import org.apache.commons.logging.Log;
53 import org.apache.commons.logging.LogFactory;
54
55 /**
56  * Implementation of the file/folder-specific service.
57  *
58  * @author Derek Hulley
59  */

60 public class FileFolderServiceImpl implements FileFolderService
61 {
62     /** Shallow search for all files */
63     private static final String JavaDoc XPATH_QUERY_SHALLOW_FILES =
64         "./*" +
65         "[(subtypeOf('" + ContentModel.TYPE_CONTENT + "'))]";
66     
67     /** Shallow search for all folder */
68     private static final String JavaDoc XPATH_QUERY_SHALLOW_FOLDERS =
69         "./*" +
70         "[not (subtypeOf('" + ContentModel.TYPE_SYSTEM_FOLDER + "'))" +
71         " and (subtypeOf('" + ContentModel.TYPE_FOLDER + "'))]";
72     
73     /** Shallow search for all files and folders */
74     private static final String JavaDoc XPATH_QUERY_SHALLOW_ALL =
75         "./*" +
76         "[like(@cm:name, $cm:name, false)" +
77         " and not (subtypeOf('" + ContentModel.TYPE_SYSTEM_FOLDER + "'))" +
78         " and (subtypeOf('" + ContentModel.TYPE_FOLDER + "') or subtypeOf('" + ContentModel.TYPE_CONTENT + "'))]";
79     
80     /** Deep search for files and folders with a name pattern */
81     private static final String JavaDoc XPATH_QUERY_DEEP_ALL =
82         ".//*" +
83         "[like(@cm:name, $cm:name, false)" +
84         " and not (subtypeOf('" + ContentModel.TYPE_SYSTEM_FOLDER + "'))" +
85         " and (subtypeOf('" + ContentModel.TYPE_FOLDER + "') or subtypeOf('" + ContentModel.TYPE_CONTENT + "'))]";
86     
87     /** empty parameters */
88     private static final QueryParameterDefinition[] PARAMS_EMPTY = new QueryParameterDefinition[0];
89     private static final QueryParameterDefinition[] PARAMS_ANY_NAME = new QueryParameterDefinition[1];
90     
91     private static Log logger = LogFactory.getLog(FileFolderServiceImpl.class);
92
93     private NamespaceService namespaceService;
94     private DictionaryService dictionaryService;
95     private NodeService nodeService;
96     private CopyService copyService;
97     private SearchService searchService;
98     private ContentService contentService;
99     private MimetypeService mimetypeService;
100     
101     // TODO: Replace this with a more formal means of identifying "system" folders (i.e. aspect or UUID)
102
private List JavaDoc systemPaths;
103     
104     /**
105      * Default constructor
106      */

107     public FileFolderServiceImpl()
108     {
109     }
110
111     public void setNamespaceService(NamespaceService namespaceService)
112     {
113         this.namespaceService = namespaceService;
114     }
115
116     public void setDictionaryService(DictionaryService dictionaryService)
117     {
118         this.dictionaryService = dictionaryService;
119     }
120     
121     public void setNodeService(NodeService nodeService)
122     {
123         this.nodeService = nodeService;
124     }
125     
126     public void setCopyService(CopyService copyService)
127     {
128         this.copyService = copyService;
129     }
130
131     public void setSearchService(SearchService searchService)
132     {
133         this.searchService = searchService;
134     }
135     
136     public void setContentService(ContentService contentService)
137     {
138         this.contentService = contentService;
139     }
140
141     public void setMimetypeService(MimetypeService mimetypeService)
142     {
143         this.mimetypeService = mimetypeService;
144     }
145
146     // TODO: Replace this with a more formal means of identifying "system" folders (i.e. aspect or UUID)
147
public void setSystemPaths(List JavaDoc<String JavaDoc> systemPaths)
148     {
149         this.systemPaths = systemPaths;
150     }
151     
152     
153     public void init()
154     {
155         PARAMS_ANY_NAME[0] = new QueryParameterDefImpl(
156                 ContentModel.PROP_NAME,
157                 dictionaryService.getDataType(DataTypeDefinition.TEXT),
158                 true,
159                 "%");
160     }
161
162     /**
163      * Helper method to convert node reference instances to file info
164      *
165      * @param nodeRefs the node references
166      * @return Return a list of file info
167      * @throws InvalidTypeException if the node is not a valid type
168      */

169     private List JavaDoc<FileInfo> toFileInfo(List JavaDoc<NodeRef> nodeRefs) throws InvalidTypeException
170     {
171         List JavaDoc<FileInfo> results = new ArrayList JavaDoc<FileInfo>(nodeRefs.size());
172         for (NodeRef nodeRef : nodeRefs)
173         {
174             FileInfo fileInfo = toFileInfo(nodeRef);
175             results.add(fileInfo);
176         }
177         return results;
178     }
179     
180     /**
181      * Helper method to convert a node reference instance to a file info
182      */

183     private FileInfo toFileInfo(NodeRef nodeRef) throws InvalidTypeException
184     {
185         // get the file attributes
186
Map JavaDoc<QName, Serializable JavaDoc> properties = nodeService.getProperties(nodeRef);
187         // is it a folder
188
QName typeQName = nodeService.getType(nodeRef);
189         boolean isFolder = isFolder(typeQName);
190         
191         // construct the file info and add to the results
192
FileInfo fileInfo = new FileInfoImpl(nodeRef, isFolder, properties);
193         // done
194
return fileInfo;
195     }
196
197     /**
198      * Ensure that a file or folder with the given name does not already exist
199      *
200      * @throws FileExistsException if a same-named file or folder already exists
201      */

202     private void checkExists(NodeRef parentFolderRef, String JavaDoc name)
203             throws FileExistsException
204     {
205         // check for existing file or folder
206
List JavaDoc<FileInfo> existingFileInfos = this.search(parentFolderRef, name, true, true, false);
207         if (existingFileInfos.size() > 0)
208         {
209             throw new FileExistsException(existingFileInfos.get(0));
210         }
211     }
212
213     /**
214      * Exception when the type is not a valid File or Folder type
215      *
216      * @see ContentModel#TYPE_CONTENT
217      * @see ContentModel#TYPE_FOLDER
218      *
219      * @author Derek Hulley
220      */

221     private static class InvalidTypeException extends RuntimeException JavaDoc
222     {
223         private static final long serialVersionUID = -310101369475434280L;
224         
225         public InvalidTypeException(String JavaDoc msg)
226         {
227             super(msg);
228         }
229     }
230     
231     /**
232      * Checks the type for whether it is a file or folder. All invalid types
233      * lead to runtime exceptions.
234      *
235      * @param typeQName the type to check
236      * @return Returns true if the type is a valid folder type, false if it is a file.
237      * @throws AlfrescoRuntimeException if the type is not handled by this service
238      */

239     private boolean isFolder(QName typeQName) throws InvalidTypeException
240     {
241         if (dictionaryService.isSubClass(typeQName, ContentModel.TYPE_FOLDER))
242         {
243             if (dictionaryService.isSubClass(typeQName, ContentModel.TYPE_SYSTEM_FOLDER))
244             {
245                 throw new InvalidTypeException("This service should ignore type " + ContentModel.TYPE_SYSTEM_FOLDER);
246             }
247             return true;
248         }
249         else if (dictionaryService.isSubClass(typeQName, ContentModel.TYPE_CONTENT))
250         {
251             // it is a regular file
252
return false;
253         }
254         else
255         {
256             // unhandled type
257
throw new InvalidTypeException("Type is not handled by this service: " + typeQName);
258         }
259     }
260
261     /**
262      * TODO: Use Lucene search to get file attributes without having to visit the node service
263      */

264     public List JavaDoc<FileInfo> list(NodeRef contextNodeRef)
265     {
266         // execute the query
267
List JavaDoc<NodeRef> nodeRefs = searchService.selectNodes(
268                 contextNodeRef,
269                 XPATH_QUERY_SHALLOW_ALL,
270                 PARAMS_ANY_NAME,
271                 namespaceService,
272                 false);
273         // convert the noderefs
274
List JavaDoc<FileInfo> results = toFileInfo(nodeRefs);
275         // done
276
if (logger.isDebugEnabled())
277         {
278             logger.debug("Shallow search for files and folders: \n" +
279                     " context: " + contextNodeRef + "\n" +
280                     " results: " + results);
281         }
282         return results;
283     }
284
285     /**
286      * TODO: Use Lucene search to get file attributes without having to visit the node service
287      */

288     public List JavaDoc<FileInfo> listFiles(NodeRef contextNodeRef)
289     {
290         // execute the query
291
List JavaDoc<NodeRef> nodeRefs = searchService.selectNodes(
292                 contextNodeRef,
293                 XPATH_QUERY_SHALLOW_FILES,
294                 PARAMS_EMPTY,
295                 namespaceService,
296                 false);
297         // convert the noderefs
298
List JavaDoc<FileInfo> results = toFileInfo(nodeRefs);
299         // done
300
if (logger.isDebugEnabled())
301         {
302             logger.debug("Shallow search for files: \n" +
303                     " context: " + contextNodeRef + "\n" +
304                     " results: " + results);
305         }
306         return results;
307     }
308
309     /**
310      * TODO: Use Lucene search to get file attributes without having to visit the node service
311      */

312     public List JavaDoc<FileInfo> listFolders(NodeRef contextNodeRef)
313     {
314         // execute the query
315
List JavaDoc<NodeRef> nodeRefs = searchService.selectNodes(
316                 contextNodeRef,
317                 XPATH_QUERY_SHALLOW_FOLDERS,
318                 PARAMS_EMPTY,
319                 namespaceService,
320                 false);
321         // convert the noderefs
322
List JavaDoc<FileInfo> results = toFileInfo(nodeRefs);
323         // done
324
if (logger.isDebugEnabled())
325         {
326             logger.debug("Shallow search for folders: \n" +
327                     " context: " + contextNodeRef + "\n" +
328                     " results: " + results);
329         }
330         return results;
331     }
332
333     /**
334      * @see #search(NodeRef, String, boolean, boolean, boolean)
335      */

336     public List JavaDoc<FileInfo> search(NodeRef contextNodeRef, String JavaDoc namePattern, boolean includeSubFolders)
337     {
338         return search(contextNodeRef, namePattern, true, true, includeSubFolders);
339     }
340
341     /**
342      * Full search with all options
343      */

344     public List JavaDoc<FileInfo> search(
345             NodeRef contextNodeRef,
346             String JavaDoc namePattern,
347             boolean fileSearch,
348             boolean folderSearch,
349             boolean includeSubFolders)
350     {
351         // shortcut if the search is requesting nothing
352
if (!fileSearch && !folderSearch)
353         {
354             return Collections.emptyList();
355         }
356         
357         // if the name pattern is null, then we use the ANY pattern
358
QueryParameterDefinition[] params = null;
359         if (namePattern != null)
360         {
361             // the interface specifies the Lucene syntax, so perform a conversion
362
namePattern = SearchLanguageConversion.convert(
363                     SearchLanguageConversion.DEF_LUCENE,
364                     SearchLanguageConversion.DEF_XPATH_LIKE,
365                     namePattern);
366             
367             params = new QueryParameterDefinition[1];
368             params[0] = new QueryParameterDefImpl(
369                     ContentModel.PROP_NAME,
370                     dictionaryService.getDataType(DataTypeDefinition.TEXT),
371                     true,
372                     namePattern);
373         }
374         else
375         {
376             params = PARAMS_ANY_NAME;
377         }
378         // determine the correct query to use
379
String JavaDoc query = null;
380         if (includeSubFolders)
381         {
382             query = XPATH_QUERY_DEEP_ALL;
383         }
384         else
385         {
386             query = XPATH_QUERY_SHALLOW_ALL;
387         }
388         // execute the query
389
List JavaDoc<NodeRef> nodeRefs = searchService.selectNodes(
390                 contextNodeRef,
391                 query,
392                 params,
393                 namespaceService,
394                 false);
395         List JavaDoc<FileInfo> results = toFileInfo(nodeRefs);
396         // eliminate unwanted files/folders
397
Iterator JavaDoc<FileInfo> iterator = results.iterator();
398         while (iterator.hasNext())
399         {
400             FileInfo file = iterator.next();
401             if (file.isFolder() && !folderSearch)
402             {
403                 iterator.remove();
404             }
405             else if (!file.isFolder() && !fileSearch)
406             {
407                 iterator.remove();
408             }
409         }
410         // done
411
if (logger.isDebugEnabled())
412         {
413             logger.debug("Deep search: \n" +
414                     " context: " + contextNodeRef + "\n" +
415                     " pattern: " + namePattern + "\n" +
416                     " files: " + fileSearch + "\n" +
417                     " folders: " + folderSearch + "\n" +
418                     " deep: " + includeSubFolders + "\n" +
419                     " results: " + results);
420         }
421         return results;
422     }
423
424     /**
425      * @see #move(NodeRef, NodeRef, String)
426      */

427     public FileInfo rename(NodeRef sourceNodeRef, String JavaDoc newName) throws FileExistsException, FileNotFoundException
428     {
429         return move(sourceNodeRef, null, newName);
430     }
431
432     /**
433      * @see #moveOrCopy(NodeRef, NodeRef, String, boolean)
434      */

435     public FileInfo move(NodeRef sourceNodeRef, NodeRef targetParentRef, String JavaDoc newName) throws FileExistsException, FileNotFoundException
436     {
437         return moveOrCopy(sourceNodeRef, targetParentRef, newName, true);
438     }
439     
440     /**
441      * @see #moveOrCopy(NodeRef, NodeRef, String, boolean)
442      */

443     public FileInfo copy(NodeRef sourceNodeRef, NodeRef targetParentRef, String JavaDoc newName) throws FileExistsException, FileNotFoundException
444     {
445         return moveOrCopy(sourceNodeRef, targetParentRef, newName, false);
446     }
447
448     /**
449      * Implements both move and copy behaviour
450      *
451      * @param move true to move, otherwise false to copy
452      */

453     private FileInfo moveOrCopy(NodeRef sourceNodeRef, NodeRef targetParentRef, String JavaDoc newName, boolean move) throws FileExistsException, FileNotFoundException
454     {
455         // get file/folder in its current state
456
FileInfo beforeFileInfo = toFileInfo(sourceNodeRef);
457         // check the name - null means keep the existing name
458
if (newName == null)
459         {
460             newName = beforeFileInfo.getName();
461         }
462         
463         // we need the current association type
464
ChildAssociationRef assocRef = nodeService.getPrimaryParent(sourceNodeRef);
465         if (targetParentRef == null)
466         {
467             targetParentRef = assocRef.getParentRef();
468         }
469         
470         // there is nothing to do if both the name and parent folder haven't changed
471
if (targetParentRef.equals(assocRef.getParentRef()) && newName.equals(beforeFileInfo.getName()))
472         {
473             if (logger.isDebugEnabled())
474             {
475                 logger.debug("Doing nothing - neither filename or parent has not changed: \n" +
476                         " parent: " + targetParentRef + "\n" +
477                         " before: " + beforeFileInfo + "\n" +
478                         " new name: " + newName);
479             }
480             return beforeFileInfo;
481         }
482         
483         // check for existing file or folder
484
checkExists(targetParentRef, newName);
485         
486         QName qname = QName.createQName(
487                 NamespaceService.CONTENT_MODEL_1_0_URI,
488                 QName.createValidLocalName(newName));
489         
490         // move or copy
491
NodeRef targetNodeRef = null;
492         if (move)
493         {
494             // TODO: Replace this with a more formal means of identifying "system" folders (i.e. aspect or UUID)
495
if (!isSystemPath(sourceNodeRef))
496             {
497                 // move the node so that the association moves as well
498
ChildAssociationRef newAssocRef = nodeService.moveNode(
499                         sourceNodeRef,
500                         targetParentRef,
501                         assocRef.getTypeQName(),
502                         qname);
503                 targetNodeRef = newAssocRef.getChildRef();
504             }
505             else
506             {
507                 // system path folders do not need to be moved
508
targetNodeRef = sourceNodeRef;
509             }
510         }
511         else
512         {
513             // copy the node
514
targetNodeRef = copyService.copy(
515                     sourceNodeRef,
516                     targetParentRef,
517                     assocRef.getTypeQName(),
518                     qname,
519                     true);
520         }
521         // changed the name property
522
nodeService.setProperty(targetNodeRef, ContentModel.PROP_NAME, newName);
523         
524         // get the details after the operation
525
FileInfo afterFileInfo = toFileInfo(targetNodeRef);
526         // done
527
if (logger.isDebugEnabled())
528         {
529             logger.debug("" + (move ? "Moved" : "Copied") + " node: \n" +
530                     " parent: " + targetParentRef + "\n" +
531                     " before: " + beforeFileInfo + "\n" +
532                     " after: " + afterFileInfo);
533         }
534         return afterFileInfo;
535     }
536     
537     /**
538      * Determine if the specified node is a special "system" folder path based node
539      *
540      * TODO: Replace this with a more formal means of identifying "system" folders (i.e. aspect or UUID)
541      *
542      * @param nodeRef node to check
543      * @return true => system folder path based node
544      */

545     private boolean isSystemPath(NodeRef nodeRef)
546     {
547         Path path = nodeService.getPath(nodeRef);
548         String JavaDoc prefixedPath = path.toPrefixString(namespaceService);
549         return systemPaths.contains(prefixedPath);
550     }
551     
552     public FileInfo create(NodeRef parentNodeRef, String JavaDoc name, QName typeQName) throws FileExistsException
553     {
554         // file or folder
555
boolean isFolder = false;
556         try
557         {
558             isFolder = isFolder(typeQName);
559         }
560         catch (InvalidTypeException e)
561         {
562             throw new AlfrescoRuntimeException("The type is not supported by this service: " + typeQName);
563         }
564         
565         // check for existing file or folder
566
checkExists(parentNodeRef, name);
567         
568         // set up initial properties
569
Map JavaDoc<QName, Serializable JavaDoc> properties = new HashMap JavaDoc<QName, Serializable JavaDoc>(11);
570         properties.put(ContentModel.PROP_NAME, (Serializable JavaDoc) name);
571         if (!isFolder)
572         {
573             // guess a mimetype based on the filename
574
String JavaDoc mimetype = mimetypeService.guessMimetype(name);
575             ContentData contentData = new ContentData(null, mimetype, 0L, "UTF-8");
576             properties.put(ContentModel.PROP_CONTENT, contentData);
577         }
578         
579         // create the node
580
QName qname = QName.createQName(
581                 NamespaceService.CONTENT_MODEL_1_0_URI,
582                 QName.createValidLocalName(name));
583         ChildAssociationRef assocRef = nodeService.createNode(
584                 parentNodeRef,
585                 ContentModel.ASSOC_CONTAINS,
586                 qname,
587                 typeQName,
588                 properties);
589         NodeRef nodeRef = assocRef.getChildRef();
590         FileInfo fileInfo = toFileInfo(nodeRef);
591         // done
592
if (logger.isDebugEnabled())
593         {
594             FileInfo parentFileInfo = toFileInfo(parentNodeRef);
595             logger.debug("Created: \n" +
596                     " parent: " + parentFileInfo + "\n" +
597                     " created: " + fileInfo);
598         }
599         return fileInfo;
600     }
601     
602     public void delete(NodeRef nodeRef)
603     {
604         nodeService.deleteNode(nodeRef);
605     }
606
607     public FileInfo makeFolders(NodeRef parentNodeRef, List JavaDoc<String JavaDoc> pathElements, QName folderTypeQName)
608     {
609         if (pathElements.size() == 0)
610         {
611             throw new IllegalArgumentException JavaDoc("Path element list is empty");
612         }
613         
614         // make sure that the folder is correct
615
boolean isFolder = isFolder(folderTypeQName);
616         if (!isFolder)
617         {
618             throw new IllegalArgumentException JavaDoc("Type is invalid to make folders with: " + folderTypeQName);
619         }
620         
621         NodeRef currentParentRef = parentNodeRef;
622         // just loop and create if necessary
623
FileInfo lastFileInfo = null;
624         for (String JavaDoc pathElement : pathElements)
625         {
626             try
627             {
628                 // not present - make it
629
FileInfo createdFileInfo = create(currentParentRef, pathElement, folderTypeQName);
630                 currentParentRef = createdFileInfo.getNodeRef();
631                 lastFileInfo = createdFileInfo;
632             }
633             catch (FileExistsException e)
634             {
635                 // it exists - just get it
636
List JavaDoc<FileInfo> fileInfos = search(currentParentRef, pathElement, false, true, false);
637                 if (fileInfos.size() == 0)
638                 {
639                     // ? It must have been removed
640
throw new AlfrescoRuntimeException("Path element has just been removed: " + pathElement);
641                 }
642                 currentParentRef = fileInfos.get(0).getNodeRef();
643                 lastFileInfo = fileInfos.get(0);
644             }
645         }
646         // done
647
return lastFileInfo;
648     }
649
650     public List JavaDoc<FileInfo> getNamePath(NodeRef rootNodeRef, NodeRef nodeRef) throws FileNotFoundException
651     {
652         // check the root
653
if (rootNodeRef == null)
654         {
655             rootNodeRef = nodeService.getRootNode(nodeRef.getStoreRef());
656         }
657         try
658         {
659             List JavaDoc<FileInfo> results = new ArrayList JavaDoc<FileInfo>(10);
660             // get the primary path
661
Path path = nodeService.getPath(nodeRef);
662             // iterate and turn the results into file info objects
663
boolean foundRoot = false;
664             for (Path.Element element : path)
665             {
666                 // ignore everything down to the root
667
Path.ChildAssocElement assocElement = (Path.ChildAssocElement) element;
668                 NodeRef childNodeRef = assocElement.getRef().getChildRef();
669                 if (childNodeRef.equals(rootNodeRef))
670                 {
671                     // just found the root - but we don't put in an entry for it
672
foundRoot = true;
673                     continue;
674                 }
675                 else if (!foundRoot)
676                 {
677                     // keep looking for the root
678
continue;
679                 }
680                 // we found the root and expect to be building the path up
681
FileInfo pathInfo = toFileInfo(childNodeRef);
682                 results.add(pathInfo);
683             }
684             // check that we found the root
685
if (!foundRoot || results.size() == 0)
686             {
687                 throw new FileNotFoundException(nodeRef);
688             }
689             // done
690
if (logger.isDebugEnabled())
691             {
692                 logger.debug("Built name path for node: \n" +
693                         " root: " + rootNodeRef + "\n" +
694                         " node: " + nodeRef + "\n" +
695                         " path: " + results);
696             }
697             return results;
698         }
699         catch (InvalidNodeRefException e)
700         {
701             throw new FileNotFoundException(nodeRef);
702         }
703     }
704
705     public FileInfo resolveNamePath(NodeRef rootNodeRef, List JavaDoc<String JavaDoc> pathElements) throws FileNotFoundException
706     {
707         if (pathElements.size() == 0)
708         {
709             throw new IllegalArgumentException JavaDoc("Path elements list is empty");
710         }
711         // walk the folder tree first
712
NodeRef parentNodeRef = rootNodeRef;
713         StringBuilder JavaDoc currentPath = new StringBuilder JavaDoc(pathElements.size() * 20);
714         int folderCount = pathElements.size() - 1;
715         for (int i = 0; i < folderCount; i++)
716         {
717             String JavaDoc pathElement = pathElements.get(i);
718             FileInfo pathElementInfo = getPathElementInfo(currentPath, rootNodeRef, parentNodeRef, pathElement, true);
719             parentNodeRef = pathElementInfo.getNodeRef();
720         }
721         // we have resolved the folder path - resolve the last component
722
String JavaDoc pathElement = pathElements.get(pathElements.size() - 1);
723         FileInfo result = getPathElementInfo(currentPath, rootNodeRef, parentNodeRef, pathElement, false);
724         // found it
725
if (logger.isDebugEnabled())
726         {
727             logger.debug("Resoved path element: \n" +
728                     " root: " + rootNodeRef + "\n" +
729                     " path: " + currentPath + "\n" +
730                     " node: " + result);
731         }
732         return result;
733     }
734     
735     /**
736      * Helper method to dig down a level for a node based on name
737      */

738     private FileInfo getPathElementInfo(
739             StringBuilder JavaDoc currentPath,
740             NodeRef rootNodeRef,
741             NodeRef parentNodeRef,
742             String JavaDoc pathElement,
743             boolean folderOnly) throws FileNotFoundException
744     {
745         currentPath.append("/").append(pathElement);
746         
747         boolean includeFiles = (folderOnly ? false : true);
748         List JavaDoc<FileInfo> pathElementInfos = search(parentNodeRef, pathElement, includeFiles, true, false);
749         // check
750
if (pathElementInfos.size() == 0)
751         {
752             StringBuilder JavaDoc sb = new StringBuilder JavaDoc(128);
753             sb.append(folderOnly ? "Folder" : "File or folder").append(" not found: \n")
754               .append(" root: ").append(rootNodeRef).append("\n")
755               .append(" path: ").append(currentPath);
756             throw new FileNotFoundException(sb.toString());
757         }
758         else if (pathElementInfos.size() > 1)
759         {
760             // we have detected a duplicate name - warn, but allow
761
StringBuilder JavaDoc sb = new StringBuilder JavaDoc(128);
762             sb.append("Duplicate file or folder found: \n")
763               .append(" root: ").append(rootNodeRef).append("\n")
764               .append(" path: ").append(currentPath);
765             logger.warn(sb);
766         }
767         FileInfo pathElementInfo = pathElementInfos.get(0);
768         return pathElementInfo;
769     }
770
771     public FileInfo getFileInfo(NodeRef nodeRef)
772     {
773         try
774         {
775             return toFileInfo(nodeRef);
776         }
777         catch (InvalidTypeException e)
778         {
779             return null;
780         }
781     }
782
783     public ContentReader getReader(NodeRef nodeRef)
784     {
785         FileInfo fileInfo = toFileInfo(nodeRef);
786         if (fileInfo.isFolder())
787         {
788             throw new InvalidTypeException("Unable to get a content reader for a folder: " + fileInfo);
789         }
790         return contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
791     }
792
793     public ContentWriter getWriter(NodeRef nodeRef)
794     {
795         FileInfo fileInfo = toFileInfo(nodeRef);
796         if (fileInfo.isFolder())
797         {
798             throw new InvalidTypeException("Unable to get a content writer for a folder: " + fileInfo);
799         }
800         return contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
801     }
802 }
803
Popular Tags