diff --git a/source/java/org/alfresco/repo/action/executer/MailActionExecuter.java b/source/java/org/alfresco/repo/action/executer/MailActionExecuter.java index 79cecafb08..788ce132c6 100644 --- a/source/java/org/alfresco/repo/action/executer/MailActionExecuter.java +++ b/source/java/org/alfresco/repo/action/executer/MailActionExecuter.java @@ -39,13 +39,13 @@ import org.alfresco.repo.action.ParameterDefinitionImpl; import org.alfresco.repo.template.DateCompareMethod; import org.alfresco.repo.template.HasAspectMethod; import org.alfresco.repo.template.I18NMessageMethod; +import org.alfresco.repo.template.TemplateNode; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.ParameterDefinition; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.repository.TemplateNode; import org.alfresco.service.cmr.repository.TemplateService; import org.alfresco.service.cmr.security.AuthenticationService; import org.alfresco.service.cmr.security.AuthorityService; diff --git a/source/java/org/alfresco/repo/action/scheduled/FreeMarkerWithLuceneExtensionsModelFactory.java b/source/java/org/alfresco/repo/action/scheduled/FreeMarkerWithLuceneExtensionsModelFactory.java index 90bb093a8c..75ccd27697 100644 --- a/source/java/org/alfresco/repo/action/scheduled/FreeMarkerWithLuceneExtensionsModelFactory.java +++ b/source/java/org/alfresco/repo/action/scheduled/FreeMarkerWithLuceneExtensionsModelFactory.java @@ -31,10 +31,10 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.alfresco.repo.template.TemplateNode; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.cmr.repository.TemplateNode; import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.alfresco.service.cmr.repository.datatype.Duration; import org.alfresco.service.cmr.search.ResultSet; diff --git a/source/java/org/alfresco/repo/jscript/CategoryTemplateNode.java b/source/java/org/alfresco/repo/jscript/CategoryTemplateNode.java index 6bac982c9d..929439993a 100644 --- a/source/java/org/alfresco/repo/jscript/CategoryTemplateNode.java +++ b/source/java/org/alfresco/repo/jscript/CategoryTemplateNode.java @@ -30,11 +30,11 @@ import java.util.Collections; import java.util.List; import org.alfresco.model.ContentModel; +import org.alfresco.repo.template.TemplateNode; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.TemplateImageResolver; -import org.alfresco.service.cmr.repository.TemplateNode; import org.alfresco.service.cmr.search.CategoryService; import org.alfresco.service.namespace.QName; diff --git a/source/java/org/alfresco/repo/jscript/Node.java b/source/java/org/alfresco/repo/jscript/Node.java index 0f4f58da74..6bdbf8553c 100644 --- a/source/java/org/alfresco/repo/jscript/Node.java +++ b/source/java/org/alfresco/repo/jscript/Node.java @@ -40,6 +40,7 @@ import org.alfresco.repo.action.executer.TransformActionExecuter; import org.alfresco.repo.content.transform.magick.ImageMagickContentTransformer; import org.alfresco.repo.search.QueryParameterDefImpl; import org.alfresco.repo.template.FreeMarkerProcessor; +import org.alfresco.repo.template.TemplateNode; import org.alfresco.repo.version.VersionModel; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; @@ -56,7 +57,6 @@ import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.repository.TemplateImageResolver; -import org.alfresco.service.cmr.repository.TemplateNode; import org.alfresco.service.cmr.search.QueryParameterDefinition; import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.PermissionService; diff --git a/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImpl.java b/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImpl.java index 7f1a3f87ef..b9251c9e74 100644 --- a/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImpl.java +++ b/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImpl.java @@ -331,6 +331,20 @@ public class FileFolderServiceImpl implements FileFolderService } return childNodeRef; } + + public NodeRef searchSimple(NodeRef contextNodeRef, String name, QName assocName) + { + NodeRef childNodeRef = nodeService.getChildByName(contextNodeRef, assocName, name); + if (logger.isDebugEnabled()) + { + logger.debug( + "Simple name search results: \n" + + " parent: " + contextNodeRef + "\n" + + " name: " + name + "\n" + + " result: " + childNodeRef); + } + return childNodeRef; + } /** * @see #search(NodeRef, String, boolean, boolean, boolean) @@ -822,12 +836,21 @@ public class FileFolderServiceImpl implements FileFolderService } // walk the folder tree first NodeRef parentNodeRef = rootNodeRef; - StringBuilder currentPath = new StringBuilder(pathElements.size() * 20); + StringBuilder currentPath = new StringBuilder(pathElements.size() << 4); int folderCount = pathElements.size() - 1; for (int i = 0; i < folderCount; i++) { String pathElement = pathElements.get(i); - NodeRef folderNodeRef = searchSimple(parentNodeRef, pathElement); + NodeRef folderNodeRef; + if (i == 0 && rootNodeRef.equals(nodeService.getRootNode(rootNodeRef.getStoreRef()))) + { + // store root nodes use a different assoc name to the immediate children + folderNodeRef = searchSimple(parentNodeRef, pathElement, ContentModel.ASSOC_CHILDREN); + } + else + { + folderNodeRef = searchSimple(parentNodeRef, pathElement); + } if (folderNodeRef == null) { StringBuilder sb = new StringBuilder(128); diff --git a/source/java/org/alfresco/repo/template/BaseContentNode.java b/source/java/org/alfresco/repo/template/BaseContentNode.java new file mode 100644 index 0000000000..4e072b0cd5 --- /dev/null +++ b/source/java/org/alfresco/repo/template/BaseContentNode.java @@ -0,0 +1,292 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing + */ +package org.alfresco.repo.template; + +import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.text.MessageFormat; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.TemplateException; +import org.alfresco.service.namespace.QName; +import org.springframework.util.StringUtils; + +/** + * @author Kevin Roast + */ +public abstract class BaseContentNode implements TemplateContent +{ + protected final static String CONTENT_DEFAULT_URL = "/download/direct/{0}/{1}/{2}/{3}"; + protected final static String CONTENT_PROP_URL = "/download/direct/{0}/{1}/{2}/{3}?property={4}"; + protected final static String FOLDER_BROWSE_URL = "/navigate/browse/{0}/{1}/{2}"; + + protected ServiceRegistry services = null; + + private Boolean isDocument = null; + private Boolean isContainer = null; + + /** + * @return true if this Node is a container (i.e. a folder) + */ + public boolean getIsContainer() + { + if (isContainer == null) + { + DictionaryService dd = this.services.getDictionaryService(); + isContainer = Boolean.valueOf( (dd.isSubClass(getType(), ContentModel.TYPE_FOLDER) == true && + dd.isSubClass(getType(), ContentModel.TYPE_SYSTEM_FOLDER) == false) ); + } + + return isContainer.booleanValue(); + } + + /** + * @return true if this Node is a Document (i.e. with content) + */ + public boolean getIsDocument() + { + if (isDocument == null) + { + DictionaryService dd = this.services.getDictionaryService(); + isDocument = Boolean.valueOf(dd.isSubClass(getType(), ContentModel.TYPE_CONTENT)); + } + + return isDocument.booleanValue(); + } + + /** + * Override Object.toString() to provide useful debug output + */ + public String toString() + { + if (this.services.getNodeService().exists(getNodeRef())) + { + return "Node Type: " + getType() + + "\tNode Ref: " + getNodeRef().toString(); + } + else + { + return "Node no longer exists: " + getNodeRef(); + } + } + + + // ------------------------------------------------------------------------------ + // Content API + + /** + * @return the content String for this node from the default content property + * (@see ContentModel.PROP_CONTENT) + */ + public String getContent() + { + TemplateContentData content = (TemplateContentData)this.getProperties().get(ContentModel.PROP_CONTENT); + return content != null ? content.getContent() : ""; + } + + /** + * @return For a content document, this method returns the URL to the content stream for + * the default content property (@see ContentModel.PROP_CONTENT) + *

+ * For a container node, this method return the URL to browse to the folder in the web-client + */ + public String getUrl() + { + if (getIsDocument() == true) + { + try + { + return MessageFormat.format(CONTENT_DEFAULT_URL, new Object[] { + getNodeRef().getStoreRef().getProtocol(), + getNodeRef().getStoreRef().getIdentifier(), + getNodeRef().getId(), + StringUtils.replace(URLEncoder.encode(getName(), "UTF-8"), "+", "%20") } ); + } + catch (UnsupportedEncodingException err) + { + throw new TemplateException("Failed to encode content URL for node: " + getNodeRef(), err); + } + } + else + { + return MessageFormat.format(FOLDER_BROWSE_URL, new Object[] { + getNodeRef().getStoreRef().getProtocol(), + getNodeRef().getStoreRef().getIdentifier(), + getNodeRef().getId() } ); + } + } + + /** + * @return The mimetype encoding for content attached to the node from the default content property + * (@see ContentModel.PROP_CONTENT) + */ + public String getMimetype() + { + TemplateContentData content = (TemplateContentData)this.getProperties().get(ContentModel.PROP_CONTENT); + return (content != null ? content.getMimetype() : null); + } + + /** + * @return The size in bytes of the content attached to the node from the default content property + * (@see ContentModel.PROP_CONTENT) + */ + public long getSize() + { + TemplateContentData content = (TemplateContentData)this.getProperties().get(ContentModel.PROP_CONTENT); + return (content != null ? content.getSize() : 0L); + } + + + // ------------------------------------------------------------------------------ + // Inner classes + + /** + * Inner class wrapping and providing access to a ContentData property + */ + public class TemplateContentData implements Serializable + { + /** + * Constructor + * + * @param contentData The ContentData object this object wraps + * @param property The property the ContentData is attached too + */ + public TemplateContentData(ContentData contentData, QName property) + { + this.contentData = contentData; + this.property = property; + } + + /** + * @return the content stream + */ + public String getContent() + { + ContentService contentService = services.getContentService(); + ContentReader reader = contentService.getReader(getNodeRef(), property); + + return (reader != null && reader.exists()) ? reader.getContentString() : ""; + } + + /** + * @return the content stream to the specified maximum length in characters + */ + public String getContent(int length) + { + ContentService contentService = services.getContentService(); + ContentReader reader = contentService.getReader(getNodeRef(), property); + + return (reader != null && reader.exists()) ? reader.getContentString(length) : ""; + } + + /** + * @param length Length of the character stream to return, or -1 for all + * + * @return the binary content stream converted to text using any available transformer + * if fails to convert then null will be returned + */ + public String getContentAsText(int length) + { + String result = null; + + if (MimetypeMap.MIMETYPE_TEXT_PLAIN.equals(getMimetype())) + { + result = getContent(length); + } + else + { + // get the content reader + ContentService contentService = services.getContentService(); + ContentReader reader = contentService.getReader(getNodeRef(), property); + + // get the writer and set it up for text convert + ContentWriter writer = contentService.getWriter(null, ContentModel.PROP_CONTENT, true); + writer.setMimetype("text/plain"); + writer.setEncoding(reader.getEncoding()); + + // try and transform the content + if (contentService.isTransformable(reader, writer)) + { + contentService.transform(reader, writer); + + ContentReader resultReader = writer.getReader(); + if (resultReader != null && reader.exists()) + { + if (length != -1) + { + result = resultReader.getContentString(length); + } + else + { + result = resultReader.getContentString(); + } + } + } + } + return result; + } + + /** + * @return + */ + public String getUrl() + { + try + { + return MessageFormat.format(CONTENT_PROP_URL, new Object[] { + getNodeRef().getStoreRef().getProtocol(), + getNodeRef().getStoreRef().getIdentifier(), + getNodeRef().getId(), + StringUtils.replace(URLEncoder.encode(getName(), "UTF-8"), "+", "%20"), + StringUtils.replace(URLEncoder.encode(property.toString(), "UTF-8"), "+", "%20") } ); + } + catch (UnsupportedEncodingException err) + { + throw new TemplateException("Failed to encode content URL for node: " + getNodeRef(), err); + } + } + + public long getSize() + { + return contentData.getSize(); + } + + public String getMimetype() + { + return contentData.getMimetype(); + } + + private ContentData contentData; + private QName property; + } +} diff --git a/source/java/org/alfresco/repo/template/BasePathResultsMap.java b/source/java/org/alfresco/repo/template/BasePathResultsMap.java index b00ea3c2e2..ada739ce32 100644 --- a/source/java/org/alfresco/repo/template/BasePathResultsMap.java +++ b/source/java/org/alfresco/repo/template/BasePathResultsMap.java @@ -30,7 +30,6 @@ import java.util.List; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.TemplateNode; import org.alfresco.service.cmr.search.QueryParameterDefinition; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/source/java/org/alfresco/repo/template/BasePermissionsNode.java b/source/java/org/alfresco/repo/template/BasePermissionsNode.java new file mode 100644 index 0000000000..515234f8dc --- /dev/null +++ b/source/java/org/alfresco/repo/template/BasePermissionsNode.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing + */ +package org.alfresco.repo.template; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.alfresco.service.cmr.security.AccessPermission; +import org.alfresco.service.cmr.security.AccessStatus; + +/** + * @author Kevin Roast + */ +public abstract class BasePermissionsNode extends BaseContentNode implements TemplatePermissions +{ + private List permissions = null; + + // ------------------------------------------------------------------------------ + // Security API + + /** + * @return List of permissions applied to this Node. + * Strings returned are of the format [ALLOWED|DENIED];[USERNAME|GROUPNAME];PERMISSION for example + * ALLOWED;kevinr;Consumer so can be easily tokenized on the ';' character. + */ + public List getPermissions() + { + if (this.permissions == null) + { + String userName = this.services.getAuthenticationService().getCurrentUserName(); + this.permissions = new ArrayList(4); + Set acls = this.services.getPermissionService().getAllSetPermissions(getNodeRef()); + for (AccessPermission permission : acls) + { + StringBuilder buf = new StringBuilder(64); + buf.append(permission.getAccessStatus()) + .append(';') + .append(permission.getAuthority()) + .append(';') + .append(permission.getPermission()); + this.permissions.add(buf.toString()); + } + } + return this.permissions; + } + + /** + * @return true if this node inherits permissions from its parent node, false otherwise. + */ + public boolean getInheritsPermissions() + { + return this.services.getPermissionService().getInheritParentPermissions(getNodeRef()); + } + + /** + * @param permission Permission name to test + * + * @return true if the current user is granted the specified permission on the node + */ + public boolean hasPermission(String permission) + { + return (this.services.getPermissionService().hasPermission(getNodeRef(), permission) == AccessStatus.ALLOWED); + } +} diff --git a/source/java/org/alfresco/repo/template/BaseSearchResultsMap.java b/source/java/org/alfresco/repo/template/BaseSearchResultsMap.java index abc30e4132..949d2d73c5 100644 --- a/source/java/org/alfresco/repo/template/BaseSearchResultsMap.java +++ b/source/java/org/alfresco/repo/template/BaseSearchResultsMap.java @@ -32,7 +32,6 @@ import java.util.List; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.TemplateNode; import org.alfresco.service.cmr.search.ResultSet; import org.alfresco.service.cmr.search.ResultSetRow; import org.alfresco.service.cmr.search.SearchService; diff --git a/source/java/org/alfresco/repo/template/BaseTemplateExtensionImplementation.java b/source/java/org/alfresco/repo/template/BaseTemplateExtensionImplementation.java index 4161d46055..82d4a32bf7 100644 --- a/source/java/org/alfresco/repo/template/BaseTemplateExtensionImplementation.java +++ b/source/java/org/alfresco/repo/template/BaseTemplateExtensionImplementation.java @@ -1,18 +1,26 @@ /* - * Copyright (C) 2005 Alfresco, Inc. + * Copyright (C) 2005-2007 Alfresco Software Limited. * - * Licensed under the Mozilla Public License version 1.1 - * with a permitted attribution clause. You may obtain a - * copy of the License at - * - * http://www.alfresco.org/legal/license.txt - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific - * language governing permissions and limitations under the - * License. + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing */ package org.alfresco.repo.template; diff --git a/source/java/org/alfresco/repo/template/BaseTemplateMap.java b/source/java/org/alfresco/repo/template/BaseTemplateMap.java index ffdc8f3764..bdd012e1e7 100644 --- a/source/java/org/alfresco/repo/template/BaseTemplateMap.java +++ b/source/java/org/alfresco/repo/template/BaseTemplateMap.java @@ -27,7 +27,6 @@ package org.alfresco.repo.template; import java.util.HashMap; import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.repository.TemplateNode; /** * An abstract Map class that can be used process the parent Node as part of the get() diff --git a/source/java/org/alfresco/repo/template/CropContentMethod.java b/source/java/org/alfresco/repo/template/CropContentMethod.java index 6e0eda4f8f..4f6f7052cc 100644 --- a/source/java/org/alfresco/repo/template/CropContentMethod.java +++ b/source/java/org/alfresco/repo/template/CropContentMethod.java @@ -26,9 +26,7 @@ package org.alfresco.repo.template; import java.util.List; -import org.alfresco.model.ContentModel; -import org.alfresco.service.cmr.repository.TemplateNode; -import org.alfresco.service.cmr.repository.TemplateNode.TemplateContentData; +import org.alfresco.repo.template.BaseContentNode.TemplateContentData; import freemarker.ext.beans.BeanModel; import freemarker.template.TemplateMethodModelEx; diff --git a/source/java/org/alfresco/repo/template/FreeMarkerProcessor.java b/source/java/org/alfresco/repo/template/FreeMarkerProcessor.java index 6f6d5924ca..aa55c358e8 100644 --- a/source/java/org/alfresco/repo/template/FreeMarkerProcessor.java +++ b/source/java/org/alfresco/repo/template/FreeMarkerProcessor.java @@ -37,7 +37,6 @@ import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.TemplateException; import org.alfresco.service.cmr.repository.TemplateExtensionImplementation; import org.alfresco.service.cmr.repository.TemplateImageResolver; -import org.alfresco.service.cmr.repository.TemplateNode; import org.alfresco.service.cmr.repository.TemplateProcessor; import org.apache.log4j.Logger; diff --git a/source/java/org/alfresco/repo/template/HasAspectMethod.java b/source/java/org/alfresco/repo/template/HasAspectMethod.java index 5a3c167b08..f08e4d6701 100644 --- a/source/java/org/alfresco/repo/template/HasAspectMethod.java +++ b/source/java/org/alfresco/repo/template/HasAspectMethod.java @@ -26,7 +26,6 @@ package org.alfresco.repo.template; import java.util.List; -import org.alfresco.service.cmr.repository.TemplateNode; import freemarker.ext.beans.BeanModel; import freemarker.template.TemplateMethodModelEx; diff --git a/source/java/org/alfresco/repo/template/HasPermissionMethod.java b/source/java/org/alfresco/repo/template/HasPermissionMethod.java index d3b8bb7b10..2f1bc8e28c 100644 --- a/source/java/org/alfresco/repo/template/HasPermissionMethod.java +++ b/source/java/org/alfresco/repo/template/HasPermissionMethod.java @@ -26,7 +26,6 @@ package org.alfresco.repo.template; import java.util.List; -import org.alfresco.service.cmr.repository.TemplateNode; import freemarker.ext.beans.BeanModel; import freemarker.template.TemplateMethodModelEx; diff --git a/source/java/org/alfresco/repo/template/LuceneSearchResultsMap.java b/source/java/org/alfresco/repo/template/LuceneSearchResultsMap.java index d94fe2498c..cf2889f84c 100644 --- a/source/java/org/alfresco/repo/template/LuceneSearchResultsMap.java +++ b/source/java/org/alfresco/repo/template/LuceneSearchResultsMap.java @@ -31,7 +31,6 @@ import org.alfresco.model.ContentModel; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.TemplateNode; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; diff --git a/source/java/org/alfresco/repo/template/NamePathResultsMap.java b/source/java/org/alfresco/repo/template/NamePathResultsMap.java index 4228e0544f..18b64fe1e7 100644 --- a/source/java/org/alfresco/repo/template/NamePathResultsMap.java +++ b/source/java/org/alfresco/repo/template/NamePathResultsMap.java @@ -30,7 +30,6 @@ import java.util.StringTokenizer; import org.alfresco.repo.search.QueryParameterDefImpl; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; -import org.alfresco.service.cmr.repository.TemplateNode; import org.alfresco.service.cmr.search.QueryParameterDefinition; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; diff --git a/source/java/org/alfresco/repo/template/NodeSearchResultsMap.java b/source/java/org/alfresco/repo/template/NodeSearchResultsMap.java index 1a1a7c59c5..3c16b7e69b 100644 --- a/source/java/org/alfresco/repo/template/NodeSearchResultsMap.java +++ b/source/java/org/alfresco/repo/template/NodeSearchResultsMap.java @@ -28,7 +28,6 @@ import java.util.List; import org.alfresco.repo.search.impl.lucene.LuceneQueryParser; import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.repository.TemplateNode; /** * Provides functionality to execute a Lucene search for a single node by NodeRef. diff --git a/source/java/org/alfresco/repo/template/SavedSearchResultsMap.java b/source/java/org/alfresco/repo/template/SavedSearchResultsMap.java index 17b3d4482f..3676d178ba 100644 --- a/source/java/org/alfresco/repo/template/SavedSearchResultsMap.java +++ b/source/java/org/alfresco/repo/template/SavedSearchResultsMap.java @@ -31,7 +31,6 @@ import org.alfresco.model.ContentModel; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.TemplateNode; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; diff --git a/source/java/org/alfresco/repo/template/TemplateContent.java b/source/java/org/alfresco/repo/template/TemplateContent.java new file mode 100644 index 0000000000..967993b1d0 --- /dev/null +++ b/source/java/org/alfresco/repo/template/TemplateContent.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing + */ +package org.alfresco.repo.template; + + +/** + * @author Kevin Roast + */ +public interface TemplateContent extends TemplateProperties +{ + /** + * @return the content String for this node from the default content property + * (@see ContentModel.PROP_CONTENT) + */ + public String getContent(); + + /** + * @return For a content document, this method returns the URL to the content stream for + * the default content property (@see ContentModel.PROP_CONTENT) + *

+ * For a container node, this method return the URL to browse to the folder in the web-client + */ + public String getUrl(); + + /** + * @return The mimetype encoding for content attached to the node from the default content property + * (@see ContentModel.PROP_CONTENT) + */ + public String getMimetype(); + + /** + * @return The size in bytes of the content attached to the node from the default content property + * (@see ContentModel.PROP_CONTENT) + */ + public long getSize(); +} diff --git a/source/java/org/alfresco/service/cmr/repository/TemplateNode.java b/source/java/org/alfresco/repo/template/TemplateNode.java similarity index 61% rename from source/java/org/alfresco/service/cmr/repository/TemplateNode.java rename to source/java/org/alfresco/repo/template/TemplateNode.java index 04cef7283b..f7366a3342 100644 --- a/source/java/org/alfresco/service/cmr/repository/TemplateNode.java +++ b/source/java/org/alfresco/repo/template/TemplateNode.java @@ -1,946 +1,638 @@ -/* - * Copyright (C) 2005-2007 Alfresco Software Limited. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: - * http://www.alfresco.com/legal/licensing" - */ -package org.alfresco.service.cmr.repository; - -import java.io.Serializable; -import java.io.StringReader; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.alfresco.model.ContentModel; -import org.alfresco.repo.action.executer.TransformActionExecuter; -import org.alfresco.repo.content.MimetypeMap; -import org.alfresco.repo.security.permissions.AccessDeniedException; -import org.alfresco.repo.template.LuceneSearchResultsMap; -import org.alfresco.repo.template.NamePathResultsMap; -import org.alfresco.repo.template.NodeSearchResultsMap; -import org.alfresco.repo.template.SavedSearchResultsMap; -import org.alfresco.repo.template.XPathResultsMap; -import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.audit.AuditInfo; -import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.service.cmr.lock.LockStatus; -import org.alfresco.service.cmr.security.AccessPermission; -import org.alfresco.service.cmr.security.AccessStatus; -import org.alfresco.service.cmr.version.Version; -import org.alfresco.service.cmr.version.VersionHistory; -import org.alfresco.service.namespace.QName; -import org.alfresco.service.namespace.QNameMap; -import org.alfresco.service.namespace.RegexQNamePattern; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.util.StringUtils; -import org.xml.sax.InputSource; - -import freemarker.ext.dom.NodeModel; - -/** - * Node class specific for use by Template pages that support Bean objects as part of the model. - * The default template engine FreeMarker can use these objects and they are provided to support it. - * A single method is completely freemarker specific - getXmlNodeModel() - *

- * The class exposes Node properties, children as dynamically populated maps and lists. - *

- * Various helper methods are provided to access common and useful node variables such - * as the content url and type information. - * - * @author Kevin Roast - */ -public class TemplateNode implements Serializable -{ - private static final long serialVersionUID = 1234390333739034171L; - - private static Log logger = LogFactory.getLog(TemplateNode.class); - - protected final static String NAMESPACE_BEGIN = "" + QName.NAMESPACE_BEGIN; - protected final static String CONTENT_DEFAULT_URL = "/download/direct/{0}/{1}/{2}/{3}"; - private final static String CONTENT_PROP_URL = "/download/direct/{0}/{1}/{2}/{3}?property={4}"; - private final static String FOLDER_BROWSE_URL = "/navigate/browse/{0}/{1}/{2}"; - - /** The children of this node */ - private List children = null; - - /** The target associations from this node */ - private Map> targetAssocs = null; - - /** The child associations from this node */ - private Map> childAssocs = null; - - /** All associations from this node */ - private Map> assocs = null; - - /** Cached values */ - protected NodeRef nodeRef; - private String name; - private QName type; - private String path; - private String id; - private Set aspects = null; - private QNameMap properties; - private List permissions = null; - private boolean propsRetrieved = false; - protected ServiceRegistry services = null; - private Boolean isDocument = null; - private Boolean isContainer = null; - private String displayPath = null; - private String mimetype = null; - private Long size = null; - protected TemplateImageResolver imageResolver = null; - private TemplateNode parent = null; - private ChildAssociationRef primaryParentAssoc = null; - private Boolean isCategory = null; - - - // ------------------------------------------------------------------------------ - // Construction - - /** - * Constructor - * - * @param nodeRef The NodeRef this Node wrapper represents - * @param services The ServiceRegistry the TemplateNode can use to access services - * @param resolver Image resolver to use to retrieve icons - */ - public TemplateNode(NodeRef nodeRef, ServiceRegistry services, TemplateImageResolver resolver) - { - if (nodeRef == null) - { - throw new IllegalArgumentException("NodeRef must be supplied."); - } - - if (services == null) - { - throw new IllegalArgumentException("The ServiceRegistry must be supplied."); - } - - this.nodeRef = nodeRef; - this.id = nodeRef.getId(); - this.services = services; - this.imageResolver = resolver; - - this.properties = new QNameMap(this.services.getNamespaceService()); - } - - - // ------------------------------------------------------------------------------ - // Node API - - /** - * @return The GUID for the node - */ - public String getId() - { - return this.id; - } - - /** - * @return Returns the NodeRef this Node object represents - */ - public NodeRef getNodeRef() - { - return this.nodeRef; - } - - /** - * @return Returns the type. - */ - public QName getType() - { - if (this.type == null) - { - this.type = this.services.getNodeService().getType(this.nodeRef); - } - - return type; - } - - /** - * @return The display name for the node - */ - public String getName() - { - if (this.name == null) - { - // try and get the name from the properties first - this.name = (String)getProperties().get("cm:name"); - - // if we didn't find it as a property get the name from the association name - if (this.name == null) - { - ChildAssociationRef parentRef = this.services.getNodeService().getPrimaryParent(this.nodeRef); - if (parentRef != null && parentRef.getQName() != null) - { - this.name = parentRef.getQName().getLocalName(); - } - else - { - this.name = ""; - } - } - } - - return this.name; - } - - /** - * @return The children of this Node as TemplateNode wrappers - */ - public List getChildren() - { - if (this.children == null) - { - List childRefs = this.services.getNodeService().getChildAssocs(this.nodeRef); - this.children = new ArrayList(childRefs.size()); - for (ChildAssociationRef ref : childRefs) - { - // create our Node representation from the NodeRef - TemplateNode child = new TemplateNode(ref.getChildRef(), this.services, this.imageResolver); - this.children.add(child); - } - } - - return this.children; - } - - /** - * @return The child associations for this Node. As a Map of assoc name to a List of TemplateNodes. - */ - public Map> getChildAssocs() - { - if (this.childAssocs == null) - { - List refs = this.services.getNodeService().getChildAssocs(this.nodeRef); - this.childAssocs = new QNameMap>(this.services.getNamespaceService()); - for (ChildAssociationRef ref : refs) - { - String qname = ref.getTypeQName().toString(); - List nodes = this.childAssocs.get(qname); - if (nodes == null) - { - // first access for the list for this qname - nodes = new ArrayList(4); - this.childAssocs.put(ref.getTypeQName().toString(), nodes); - } - nodes.add( new TemplateNode(ref.getChildRef(), this.services, this.imageResolver) ); - } - } - - return this.childAssocs; - } - - /** - * @return The target associations for this Node. As a Map of assoc name to a List of TemplateNodes. - */ - public Map> getTargetAssocs() - { - if (this.targetAssocs == null) - { - List refs = this.services.getNodeService().getTargetAssocs(this.nodeRef, RegexQNamePattern.MATCH_ALL); - this.targetAssocs = new QNameMap>(this.services.getNamespaceService()); - for (AssociationRef ref : refs) - { - String qname = ref.getTypeQName().toString(); - List nodes = this.targetAssocs.get(qname); - if (nodes == null) - { - // first access for the list for this qname - nodes = new ArrayList(4); - this.targetAssocs.put(ref.getTypeQName().toString(), nodes); - } - nodes.add( new TemplateNode(ref.getTargetRef(), this.services, this.imageResolver) ); - } - } - - return this.targetAssocs; - } - - /** - * @return All associations for this Node. As a Map of assoc name to a List of TemplateNodes. - */ - public Map> getAssocs() - { - if (this.assocs == null) - { - this.assocs = new QNameMap>(this.services.getNamespaceService()); - this.assocs.putAll(getTargetAssocs()); - this.assocs.putAll(getChildAssocs()); - } - return this.assocs; - } - - /** - * @return All the properties known about this node. - */ - public Map getProperties() - { - if (this.propsRetrieved == false) - { - Map props = this.services.getNodeService().getProperties(this.nodeRef); - - for (QName qname : props.keySet()) - { - Serializable propValue = props.get(qname); - if (propValue instanceof NodeRef) - { - // NodeRef object properties are converted to new TemplateNode objects - // so they can be used as objects within a template - propValue = new TemplateNode(((NodeRef)propValue), this.services, this.imageResolver); - } - else if (propValue instanceof ContentData) - { - // ContentData object properties are converted to TemplateContentData objects - // so the content and other properties of those objects can be accessed - propValue = new TemplateContentData((ContentData)propValue, qname); - } - this.properties.put(qname.toString(), propValue); - } - - this.propsRetrieved = true; - } - - return this.properties; - } - - /** - * @return a list of objects representing the version history of this node. - * @see VersionHistoryNode - */ - public List getVersionHistory() - { - List records = Collections.emptyList(); - - if (this.getAspects().contains(ContentModel.ASPECT_VERSIONABLE)) - { - VersionHistory history = this.services.getVersionService().getVersionHistory(this.nodeRef); - if (history != null) - { - records = new ArrayList(8); - for (Version version : history.getAllVersions()) - { - // create a wrapper for the version information - VersionHistoryNode record = new VersionHistoryNode(version, this); - - // add the client side version to the list - records.add(record); - } - } - } - - return records; - } - - /** - * @return true if this Node is a container (i.e. a folder) - */ - public boolean getIsContainer() - { - if (isContainer == null) - { - DictionaryService dd = this.services.getDictionaryService(); - isContainer = Boolean.valueOf( (dd.isSubClass(getType(), ContentModel.TYPE_FOLDER) == true && - dd.isSubClass(getType(), ContentModel.TYPE_SYSTEM_FOLDER) == false) ); - } - - return isContainer.booleanValue(); - } - - /** - * @return true if this Node is a Document (i.e. with content) - */ - public boolean getIsDocument() - { - if (isDocument == null) - { - DictionaryService dd = this.services.getDictionaryService(); - isDocument = Boolean.valueOf(dd.isSubClass(getType(), ContentModel.TYPE_CONTENT)); - } - - return isDocument.booleanValue(); - } - - /** - * @return The list of aspects applied to this node - */ - public Set getAspects() - { - if (this.aspects == null) - { - this.aspects = this.services.getNodeService().getAspects(this.nodeRef); - } - - return this.aspects; - } - - /** - * @param aspect The aspect name to test for - * - * @return true if the node has the aspect false otherwise - */ - public boolean hasAspect(String aspect) - { - if (this.aspects == null) - { - this.aspects = this.services.getNodeService().getAspects(this.nodeRef); - } - - if (aspect.startsWith(NAMESPACE_BEGIN)) - { - return aspects.contains((QName.createQName(aspect))); - } - else - { - boolean found = false; - for (QName qname : this.aspects) - { - if (qname.toPrefixString(this.services.getNamespaceService()).equals(aspect)) - { - found = true; - break; - } - } - return found; - } - } - - /** - * @return true if the node is currently locked - */ - public boolean getIsLocked() - { - boolean locked = false; - - if (getAspects().contains(ContentModel.ASPECT_LOCKABLE)) - { - LockStatus lockStatus = this.services.getLockService().getLockStatus(this.nodeRef); - if (lockStatus == LockStatus.LOCKED || lockStatus == LockStatus.LOCK_OWNER) - { - locked = true; - } - } - - return locked; - } - - /** - * @return true if the node is a Category instance - */ - public boolean getIsCategory() - { - if (isCategory == null) - { - DictionaryService dd = this.services.getDictionaryService(); - isCategory = Boolean.valueOf(dd.isSubClass(getType(), ContentModel.TYPE_CATEGORY)); - } - - return isCategory.booleanValue(); - } - - /** - * @return the parent node - */ - public TemplateNode getParent() - { - if (parent == null) - { - NodeRef parentRef = this.services.getNodeService().getPrimaryParent(nodeRef).getParentRef(); - // handle root node (no parent!) - if (parentRef != null) - { - parent = new TemplateNode(parentRef, this.services, this.imageResolver); - } - } - - return parent; - } - - /** - * @return the primary parent association so we can access the association QName and association type QName. - */ - public ChildAssociationRef getPrimaryParentAssoc() - { - if (primaryParentAssoc == null) - { - primaryParentAssoc = this.services.getNodeService().getPrimaryParent(nodeRef); - } - return primaryParentAssoc; - } - - - // ------------------------------------------------------------------------------ - // Content API - - /** - * @return the content String for this node from the default content property - * (@see ContentModel.PROP_CONTENT) - */ - public String getContent() - { - TemplateContentData content = (TemplateContentData)this.getProperties().get(ContentModel.PROP_CONTENT); - return content != null ? content.getContent() : ""; - } - - /** - * @return For a content document, this method returns the URL to the content stream for - * the default content property (@see ContentModel.PROP_CONTENT) - *

- * For a container node, this method return the URL to browse to the folder in the web-client - */ - public String getUrl() - { - if (getIsDocument() == true) - { - try - { - return MessageFormat.format(CONTENT_DEFAULT_URL, new Object[] { - nodeRef.getStoreRef().getProtocol(), - nodeRef.getStoreRef().getIdentifier(), - nodeRef.getId(), - StringUtils.replace(URLEncoder.encode(getName(), "UTF-8"), "+", "%20") } ); - } - catch (UnsupportedEncodingException err) - { - throw new TemplateException("Failed to encode content URL for node: " + nodeRef, err); - } - } - else - { - return MessageFormat.format(FOLDER_BROWSE_URL, new Object[] { - nodeRef.getStoreRef().getProtocol(), - nodeRef.getStoreRef().getIdentifier(), - nodeRef.getId() } ); - } - } - - /** - * @return The mimetype encoding for content attached to the node from the default content property - * (@see ContentModel.PROP_CONTENT) - */ - public String getMimetype() - { - if (mimetype == null) - { - TemplateContentData content = (TemplateContentData)this.getProperties().get(ContentModel.PROP_CONTENT); - if (content != null) - { - mimetype = content.getMimetype(); - } - } - - return mimetype; - } - - /** - * @return The size in bytes of the content attached to the node from the default content property - * (@see ContentModel.PROP_CONTENT) - */ - public long getSize() - { - if (size == null) - { - TemplateContentData content = (TemplateContentData)this.getProperties().get(ContentModel.PROP_CONTENT); - if (content != null) - { - size = content.getSize(); - } - } - - return size != null ? size.longValue() : 0L; - } - - - // ------------------------------------------------------------------------------ - // Node Helper API - - /** - * @return FreeMarker NodeModel for the XML content of this node, or null if no parsable XML found - */ - public NodeModel getXmlNodeModel() - { - try - { - return NodeModel.parse(new InputSource(new StringReader(getContent()))); - } - catch (Throwable err) - { - if (logger.isDebugEnabled()) - logger.debug(err.getMessage(), err); - - return null; - } - } - - /** - * @return Display path to this node - the path built of 'cm:name' attribute values. - */ - public String getDisplayPath() - { - if (displayPath == null) - { - try - { - displayPath = this.services.getNodeService().getPath(this.nodeRef).toDisplayPath(this.services.getNodeService()); - } - catch (AccessDeniedException err) - { - displayPath = ""; - } - } - - return displayPath; - } - - /** - * @return QName path to this node. This can be used for Lucene PATH: style queries - */ - public String getQnamePath() - { - return this.services.getNodeService().getPath(this.nodeRef).toPrefixString(this.services.getNamespaceService()); - } - - /** - * @return the small icon image for this node - */ - public String getIcon16() - { - if (this.imageResolver != null) - { - if (getIsDocument()) - { - return this.imageResolver.resolveImagePathForName(getName(), true); - } - else - { - String icon = (String)getProperties().get("app:icon"); - if (icon != null) - { - return "/images/icons/" + icon + "-16.gif"; - } - else - { - return "/images/icons/space_small.gif"; - } - } - } - else - { - return "/images/filetypes/_default.gif"; - } - } - - /** - * @return the large icon image for this node - */ - public String getIcon32() - { - if (this.imageResolver != null) - { - if (getIsDocument()) - { - return this.imageResolver.resolveImagePathForName(getName(), false); - } - else - { - String icon = (String)getProperties().get("app:icon"); - if (icon != null) - { - return "/images/icons/" + icon + ".gif"; - } - else - { - return "/images/icons/space-icon-default.gif"; - } - } - } - else - { - return "/images/filetypes32/_default.gif"; - } - } - - - // ------------------------------------------------------------------------------ - // Security API - - /** - * @return List of permissions applied to this Node. - * Strings returned are of the format [ALLOWED|DENIED];[USERNAME|GROUPNAME];PERMISSION for example - * ALLOWED;kevinr;Consumer so can be easily tokenized on the ';' character. - */ - public List getPermissions() - { - if (this.permissions == null) - { - String userName = this.services.getAuthenticationService().getCurrentUserName(); - this.permissions = new ArrayList(4); - Set acls = this.services.getPermissionService().getAllSetPermissions(this.nodeRef); - for (AccessPermission permission : acls) - { - StringBuilder buf = new StringBuilder(64); - buf.append(permission.getAccessStatus()) - .append(';') - .append(permission.getAuthority()) - .append(';') - .append(permission.getPermission()); - this.permissions.add(buf.toString()); - } - } - return this.permissions; - } - - /** - * @return true if this node inherits permissions from its parent node, false otherwise. - */ - public boolean getInheritsPermissions() - { - return this.services.getPermissionService().getInheritParentPermissions(this.nodeRef); - } - - /** - * @param permission Permission name to test - * - * @return true if the current user is granted the specified permission on the node - */ - public boolean hasPermission(String permission) - { - return (this.services.getPermissionService().hasPermission(this.nodeRef, permission) == AccessStatus.ALLOWED); - } - - - // ------------------------------------------------------------------------------ - // Search API - - /** - * @return A map capable of returning the TemplateNode at the specified Path as a child of this node. - */ - public Map getChildByNamePath() - { - return new NamePathResultsMap(this, this.services); - } - - /** - * @return A map capable of returning a List of TemplateNode objects from an XPath query - * as children of this node. - */ - public Map getChildrenByXPath() - { - return new XPathResultsMap(this, this.services); - } - - /** - * @return A map capable of returning a List of TemplateNode objects from an NodeRef to a Saved Search - * object. The Saved Search is executed and the resulting nodes supplied as a sequence. - */ - public Map getChildrenBySavedSearch() - { - return new SavedSearchResultsMap(this, this.services); - } - - /** - * @return A map capable of returning a List of TemplateNode objects from an NodeRef to a Lucene search - * string. The Saved Search is executed and the resulting nodes supplied as a sequence. - */ - public Map getChildrenByLuceneSearch() - { - return new LuceneSearchResultsMap(this, this.services); - } - - /** - * @return A map capable of returning a TemplateNode for a single specified NodeRef reference. - */ - public Map getNodeByReference() - { - return new NodeSearchResultsMap(this, this.services); - } - - - // ------------------------------------------------------------------------------ - // Audit API - - /** - * @return a list of AuditInfo objects describing the Audit Trail for this node instance - */ - public List getAuditTrail() - { - return this.services.getAuditService().getAuditTrail(this.nodeRef); - } - - - // ------------------------------------------------------------------------------ - // Misc helpers - - /** - * @return the image resolver instance used by this node - */ - public TemplateImageResolver getImageResolver() - { - return this.imageResolver; - } - - /** - * Override Object.toString() to provide useful debug output - */ - public String toString() - { - if (this.services.getNodeService().exists(nodeRef)) - { - return "Node Type: " + getType() + - "\tNode Ref: " + this.nodeRef.toString(); - } - else - { - return "Node no longer exists: " + nodeRef; - } - } - - - // ------------------------------------------------------------------------------ - // Inner classes - - /** - * Inner class wrapping and providing access to a ContentData property - */ - public class TemplateContentData implements Serializable - { - /** - * Constructor - * - * @param contentData The ContentData object this object wraps - * @param property The property the ContentData is attached too - */ - public TemplateContentData(ContentData contentData, QName property) - { - this.contentData = contentData; - this.property = property; - } - - /** - * @return the content stream - */ - public String getContent() - { - ContentService contentService = services.getContentService(); - ContentReader reader = contentService.getReader(nodeRef, property); - - return (reader != null && reader.exists()) ? reader.getContentString() : ""; - } - - /** - * @return the content stream to the specified maximum length in characters - */ - public String getContent(int length) - { - ContentService contentService = services.getContentService(); - ContentReader reader = contentService.getReader(nodeRef, property); - - return (reader != null && reader.exists()) ? reader.getContentString(length) : ""; - } - - /** - * @param length Length of the character stream to return, or -1 for all - * - * @return the binary content stream converted to text using any available transformer - * if fails to convert then null will be returned - */ - public String getContentAsText(int length) - { - String result = null; - - if (MimetypeMap.MIMETYPE_TEXT_PLAIN.equals(mimetype)) - { - result = getContent(length); - } - else - { - // get the content reader - ContentService contentService = services.getContentService(); - ContentReader reader = contentService.getReader(nodeRef, property); - - // get the writer and set it up for text convert - ContentWriter writer = contentService.getWriter(null, ContentModel.PROP_CONTENT, true); - writer.setMimetype("text/plain"); - writer.setEncoding(reader.getEncoding()); - - // try and transform the content - if (contentService.isTransformable(reader, writer)) - { - contentService.transform(reader, writer); - - ContentReader resultReader = writer.getReader(); - if (resultReader != null && reader.exists()) - { - if (length != -1) - { - result = resultReader.getContentString(length); - } - else - { - result = resultReader.getContentString(); - } - } - } - } - return result; - } - - /** - * @return - */ - public String getUrl() - { - try - { - return MessageFormat.format(CONTENT_PROP_URL, new Object[] { - nodeRef.getStoreRef().getProtocol(), - nodeRef.getStoreRef().getIdentifier(), - nodeRef.getId(), - StringUtils.replace(URLEncoder.encode(getName(), "UTF-8"), "+", "%20"), - StringUtils.replace(URLEncoder.encode(property.toString(), "UTF-8"), "+", "%20") } ); - } - catch (UnsupportedEncodingException err) - { - throw new TemplateException("Failed to encode content URL for node: " + nodeRef, err); - } - } - - public long getSize() - { - return contentData.getSize(); - } - - public String getMimetype() - { - return contentData.getMimetype(); - } - - private ContentData contentData; - private QName property; - } +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.template; + +import java.io.Serializable; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.security.permissions.AccessDeniedException; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.audit.AuditInfo; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.lock.LockStatus; +import org.alfresco.service.cmr.repository.AssociationRef; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.TemplateImageResolver; +import org.alfresco.service.cmr.version.Version; +import org.alfresco.service.cmr.version.VersionHistory; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.namespace.QNameMap; +import org.alfresco.service.namespace.RegexQNamePattern; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.xml.sax.InputSource; + +import freemarker.ext.dom.NodeModel; + +/** + * Node class specific for use by Template pages that support Bean objects as part of the model. + * The default template engine FreeMarker can use these objects and they are provided to support it. + * A single method is completely freemarker specific - getXmlNodeModel() + *

+ * The class exposes Node properties, children as dynamically populated maps and lists. + *

+ * Various helper methods are provided to access common and useful node variables such + * as the content url and type information. + * + * @author Kevin Roast + */ +public class TemplateNode extends BasePermissionsNode +{ + private static final long serialVersionUID = 1234390333739034171L; + + private static Log logger = LogFactory.getLog(TemplateNode.class); + + protected final static String NAMESPACE_BEGIN = "" + QName.NAMESPACE_BEGIN; + + /** The children of this node */ + private List children = null; + + /** The target associations from this node */ + private Map> targetAssocs = null; + + /** The child associations from this node */ + private Map> childAssocs = null; + + /** All associations from this node */ + private Map> assocs = null; + + /** Cached values */ + protected NodeRef nodeRef; + private String name; + private QName type; + private String path; + private String id; + private Set aspects = null; + private QNameMap properties; + private boolean propsRetrieved = false; + private String displayPath = null; + protected TemplateImageResolver imageResolver = null; + private TemplateNode parent = null; + private ChildAssociationRef primaryParentAssoc = null; + private Boolean isCategory = null; + + + // ------------------------------------------------------------------------------ + // Construction + + /** + * Constructor + * + * @param nodeRef The NodeRef this Node wrapper represents + * @param services The ServiceRegistry the TemplateNode can use to access services + * @param resolver Image resolver to use to retrieve icons + */ + public TemplateNode(NodeRef nodeRef, ServiceRegistry services, TemplateImageResolver resolver) + { + if (nodeRef == null) + { + throw new IllegalArgumentException("NodeRef must be supplied."); + } + + if (services == null) + { + throw new IllegalArgumentException("The ServiceRegistry must be supplied."); + } + + this.nodeRef = nodeRef; + this.id = nodeRef.getId(); + this.services = services; + this.imageResolver = resolver; + + this.properties = new QNameMap(this.services.getNamespaceService()); + } + + + // ------------------------------------------------------------------------------ + // TemplateNodeRef contract implementation + + /** + * @return The GUID for the node + */ + public String getId() + { + return this.id; + } + + /** + * @return Returns the NodeRef this Node object represents + */ + public NodeRef getNodeRef() + { + return this.nodeRef; + } + + /** + * @return Returns the type. + */ + public QName getType() + { + if (this.type == null) + { + this.type = this.services.getNodeService().getType(this.nodeRef); + } + + return type; + } + + /** + * @return The display name for the node + */ + public String getName() + { + if (this.name == null) + { + // try and get the name from the properties first + this.name = (String)getProperties().get("cm:name"); + + // if we didn't find it as a property get the name from the association name + if (this.name == null) + { + ChildAssociationRef parentRef = this.services.getNodeService().getPrimaryParent(this.nodeRef); + if (parentRef != null && parentRef.getQName() != null) + { + this.name = parentRef.getQName().getLocalName(); + } + else + { + this.name = ""; + } + } + } + + return this.name; + } + + + // ------------------------------------------------------------------------------ + // TemplateProperties contract implementation + + /** + * @return The children of this Node as objects that support the TemplateProperties contract. + */ + public List getChildren() + { + if (this.children == null) + { + List childRefs = this.services.getNodeService().getChildAssocs(this.nodeRef); + this.children = new ArrayList(childRefs.size()); + for (ChildAssociationRef ref : childRefs) + { + // create our Node representation from the NodeRef + TemplateNode child = new TemplateNode(ref.getChildRef(), this.services, this.imageResolver); + this.children.add(child); + } + } + + return this.children; + } + + /** + * @return All the properties known about this node. + */ + public Map getProperties() + { + if (this.propsRetrieved == false) + { + Map props = this.services.getNodeService().getProperties(this.nodeRef); + + for (QName qname : props.keySet()) + { + Serializable propValue = props.get(qname); + if (propValue instanceof NodeRef) + { + // NodeRef object properties are converted to new TemplateNode objects + // so they can be used as objects within a template + propValue = new TemplateNode(((NodeRef)propValue), this.services, this.imageResolver); + } + else if (propValue instanceof ContentData) + { + // ContentData object properties are converted to TemplateContentData objects + // so the content and other properties of those objects can be accessed + propValue = new TemplateContentData((ContentData)propValue, qname); + } + this.properties.put(qname.toString(), propValue); + } + + this.propsRetrieved = true; + } + + return this.properties; + } + + /** + * @return The list of aspects applied to this node + */ + public Set getAspects() + { + if (this.aspects == null) + { + this.aspects = this.services.getNodeService().getAspects(this.nodeRef); + } + + return this.aspects; + } + + /** + * @param aspect The aspect name to test for + * + * @return true if the node has the aspect false otherwise + */ + public boolean hasAspect(String aspect) + { + if (this.aspects == null) + { + this.aspects = this.services.getNodeService().getAspects(this.nodeRef); + } + + if (aspect.startsWith(NAMESPACE_BEGIN)) + { + return aspects.contains((QName.createQName(aspect))); + } + else + { + boolean found = false; + for (QName qname : this.aspects) + { + if (qname.toPrefixString(this.services.getNamespaceService()).equals(aspect)) + { + found = true; + break; + } + } + return found; + } + } + + + // ------------------------------------------------------------------------------ + // Repository Node API + + /** + * @return The child associations for this Node. As a Map of assoc name to a List of TemplateNodes. + */ + public Map> getChildAssocs() + { + if (this.childAssocs == null) + { + List refs = this.services.getNodeService().getChildAssocs(this.nodeRef); + this.childAssocs = new QNameMap>(this.services.getNamespaceService()); + for (ChildAssociationRef ref : refs) + { + String qname = ref.getTypeQName().toString(); + List nodes = this.childAssocs.get(qname); + if (nodes == null) + { + // first access for the list for this qname + nodes = new ArrayList(4); + this.childAssocs.put(ref.getTypeQName().toString(), nodes); + } + nodes.add( new TemplateNode(ref.getChildRef(), this.services, this.imageResolver) ); + } + } + + return this.childAssocs; + } + + /** + * @return The target associations for this Node. As a Map of assoc name to a List of TemplateNodes. + */ + public Map> getTargetAssocs() + { + if (this.targetAssocs == null) + { + List refs = this.services.getNodeService().getTargetAssocs(this.nodeRef, RegexQNamePattern.MATCH_ALL); + this.targetAssocs = new QNameMap>(this.services.getNamespaceService()); + for (AssociationRef ref : refs) + { + String qname = ref.getTypeQName().toString(); + List nodes = this.targetAssocs.get(qname); + if (nodes == null) + { + // first access for the list for this qname + nodes = new ArrayList(4); + this.targetAssocs.put(ref.getTypeQName().toString(), nodes); + } + nodes.add( new TemplateNode(ref.getTargetRef(), this.services, this.imageResolver) ); + } + } + + return this.targetAssocs; + } + + /** + * @return All associations for this Node. As a Map of assoc name to a List of TemplateNodes. + */ + public Map> getAssocs() + { + if (this.assocs == null) + { + this.assocs = new QNameMap>(this.services.getNamespaceService()); + this.assocs.putAll(getTargetAssocs()); + this.assocs.putAll(getChildAssocs()); + } + return this.assocs; + } + + /** + * @return true if the node is currently locked + */ + public boolean getIsLocked() + { + boolean locked = false; + + if (getAspects().contains(ContentModel.ASPECT_LOCKABLE)) + { + LockStatus lockStatus = this.services.getLockService().getLockStatus(this.nodeRef); + if (lockStatus == LockStatus.LOCKED || lockStatus == LockStatus.LOCK_OWNER) + { + locked = true; + } + } + + return locked; + } + + /** + * @return true if the node is a Category instance + */ + public boolean getIsCategory() + { + if (isCategory == null) + { + DictionaryService dd = this.services.getDictionaryService(); + isCategory = Boolean.valueOf(dd.isSubClass(getType(), ContentModel.TYPE_CATEGORY)); + } + + return isCategory.booleanValue(); + } + + /** + * @return the parent node + */ + public TemplateNode getParent() + { + if (parent == null) + { + NodeRef parentRef = this.services.getNodeService().getPrimaryParent(nodeRef).getParentRef(); + // handle root node (no parent!) + if (parentRef != null) + { + parent = new TemplateNode(parentRef, this.services, this.imageResolver); + } + } + + return parent; + } + + /** + * @return the primary parent association so we can access the association QName and association type QName. + */ + public ChildAssociationRef getPrimaryParentAssoc() + { + if (primaryParentAssoc == null) + { + primaryParentAssoc = this.services.getNodeService().getPrimaryParent(nodeRef); + } + return primaryParentAssoc; + } + + /** + * @return a list of objects representing the version history of this node. + * @see VersionHistoryNode + */ + public List getVersionHistory() + { + List records = Collections.emptyList(); + + if (this.getAspects().contains(ContentModel.ASPECT_VERSIONABLE)) + { + VersionHistory history = this.services.getVersionService().getVersionHistory(this.nodeRef); + if (history != null) + { + records = new ArrayList(8); + for (Version version : history.getAllVersions()) + { + // create a wrapper for the version information + VersionHistoryNode record = new VersionHistoryNode(version, this, this.services); + + // add the client side version to the list + records.add(record); + } + } + } + + return records; + } + + + // ------------------------------------------------------------------------------ + // Node Helper API + + /** + * @return FreeMarker NodeModel for the XML content of this node, or null if no parsable XML found + */ + public NodeModel getXmlNodeModel() + { + try + { + return NodeModel.parse(new InputSource(new StringReader(getContent()))); + } + catch (Throwable err) + { + if (logger.isDebugEnabled()) + logger.debug(err.getMessage(), err); + + return null; + } + } + + /** + * @return Display path to this node - the path built of 'cm:name' attribute values. + */ + public String getDisplayPath() + { + if (displayPath == null) + { + try + { + displayPath = this.services.getNodeService().getPath(this.nodeRef).toDisplayPath(this.services.getNodeService()); + } + catch (AccessDeniedException err) + { + displayPath = ""; + } + } + + return displayPath; + } + + /** + * @return QName path to this node. This can be used for Lucene PATH: style queries + */ + public String getQnamePath() + { + return this.services.getNodeService().getPath(this.nodeRef).toPrefixString(this.services.getNamespaceService()); + } + + /** + * @return the small icon image for this node + */ + public String getIcon16() + { + if (this.imageResolver != null) + { + if (getIsDocument()) + { + return this.imageResolver.resolveImagePathForName(getName(), true); + } + else + { + String icon = (String)getProperties().get("app:icon"); + if (icon != null) + { + return "/images/icons/" + icon + "-16.gif"; + } + else + { + return "/images/icons/space_small.gif"; + } + } + } + else + { + return "/images/filetypes/_default.gif"; + } + } + + /** + * @return the large icon image for this node + */ + public String getIcon32() + { + if (this.imageResolver != null) + { + if (getIsDocument()) + { + return this.imageResolver.resolveImagePathForName(getName(), false); + } + else + { + String icon = (String)getProperties().get("app:icon"); + if (icon != null) + { + return "/images/icons/" + icon + ".gif"; + } + else + { + return "/images/icons/space-icon-default.gif"; + } + } + } + else + { + return "/images/filetypes32/_default.gif"; + } + } + + + // ------------------------------------------------------------------------------ + // Search API + + /** + * @return A map capable of returning the TemplateNode at the specified Path as a child of this node. + */ + public Map getChildByNamePath() + { + return new NamePathResultsMap(this, this.services); + } + + /** + * @return A map capable of returning a List of TemplateNode objects from an XPath query + * as children of this node. + */ + public Map getChildrenByXPath() + { + return new XPathResultsMap(this, this.services); + } + + /** + * @return A map capable of returning a List of TemplateNode objects from an NodeRef to a Saved Search + * object. The Saved Search is executed and the resulting nodes supplied as a sequence. + */ + public Map getChildrenBySavedSearch() + { + return new SavedSearchResultsMap(this, this.services); + } + + /** + * @return A map capable of returning a List of TemplateNode objects from an NodeRef to a Lucene search + * string. The Saved Search is executed and the resulting nodes supplied as a sequence. + */ + public Map getChildrenByLuceneSearch() + { + return new LuceneSearchResultsMap(this, this.services); + } + + /** + * @return A map capable of returning a TemplateNode for a single specified NodeRef reference. + */ + public Map getNodeByReference() + { + return new NodeSearchResultsMap(this, this.services); + } + + + // ------------------------------------------------------------------------------ + // Audit API + + /** + * @return a list of AuditInfo objects describing the Audit Trail for this node instance + */ + public List getAuditTrail() + { + return this.services.getAuditService().getAuditTrail(this.nodeRef); + } + + + // ------------------------------------------------------------------------------ + // Misc helpers + + /** + * @return the image resolver instance used by this node + */ + public TemplateImageResolver getImageResolver() + { + return this.imageResolver; + } } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/template/TemplateNodeRef.java b/source/java/org/alfresco/repo/template/TemplateNodeRef.java new file mode 100644 index 0000000000..05f68f7c96 --- /dev/null +++ b/source/java/org/alfresco/repo/template/TemplateNodeRef.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing + */ +package org.alfresco.repo.template; + +import java.io.Serializable; + +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.QName; + +/** + * @author Kevin Roast + */ +public interface TemplateNodeRef extends Serializable +{ + /** + * @return The GUID for the node + */ + public String getId(); + + /** + * @return Returns the NodeRef this Node object represents + */ + public NodeRef getNodeRef(); + + /** + * @return Returns the type. + */ + public QName getType(); + + /** + * @return The display name for the node + */ + public String getName(); +} diff --git a/source/java/org/alfresco/repo/template/TemplatePermissions.java b/source/java/org/alfresco/repo/template/TemplatePermissions.java new file mode 100644 index 0000000000..fd6a9dd063 --- /dev/null +++ b/source/java/org/alfresco/repo/template/TemplatePermissions.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing + */ +package org.alfresco.repo.template; + +import java.util.List; + +/** + * @author Kevin Roast + */ +public interface TemplatePermissions extends TemplateNodeRef +{ + /** + * @return List of permissions applied to this Node. + * Strings returned are of the format [ALLOWED|DENIED];[USERNAME|GROUPNAME];PERMISSION for example + * ALLOWED;kevinr;Consumer so can be easily tokenized on the ';' character. + */ + public List getPermissions(); + + /** + * @return true if this node inherits permissions from its parent node, false otherwise. + */ + public boolean getInheritsPermissions(); + + /** + * @param permission Permission name to test + * + * @return true if the current user is granted the specified permission on the node + */ + public boolean hasPermission(String permission); +} diff --git a/source/java/org/alfresco/repo/template/TemplateProperties.java b/source/java/org/alfresco/repo/template/TemplateProperties.java new file mode 100644 index 0000000000..848ced91d3 --- /dev/null +++ b/source/java/org/alfresco/repo/template/TemplateProperties.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing + */ +package org.alfresco.repo.template; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.service.namespace.QName; + +/** + * @author Kevin Roast + */ +public interface TemplateProperties extends TemplateNodeRef +{ + /** + * @return The properties available on this node. + */ + public Map getProperties(); + + /** + * @return The list of aspects applied to this node + */ + public Set getAspects(); + + /** + * @param aspect The aspect name to test for + * + * @return true if the node has the aspect false otherwise + */ + public boolean hasAspect(String aspect); + + /** + * @return The children of this Node as TemplateNode wrappers + */ + public List getChildren(); +} diff --git a/source/java/org/alfresco/repo/template/TemplateServiceImplTest.java b/source/java/org/alfresco/repo/template/TemplateServiceImplTest.java index d22f8e567a..e9e86a65c7 100644 --- a/source/java/org/alfresco/repo/template/TemplateServiceImplTest.java +++ b/source/java/org/alfresco/repo/template/TemplateServiceImplTest.java @@ -42,7 +42,6 @@ import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.cmr.repository.TemplateNode; import org.alfresco.service.cmr.repository.TemplateService; import org.alfresco.service.transaction.TransactionService; import org.alfresco.util.ApplicationContextHelper; diff --git a/source/java/org/alfresco/service/cmr/repository/VersionHistoryNode.java b/source/java/org/alfresco/repo/template/VersionHistoryNode.java similarity index 84% rename from source/java/org/alfresco/service/cmr/repository/VersionHistoryNode.java rename to source/java/org/alfresco/repo/template/VersionHistoryNode.java index 1a04b60111..24e871baa9 100644 --- a/source/java/org/alfresco/service/cmr/repository/VersionHistoryNode.java +++ b/source/java/org/alfresco/repo/template/VersionHistoryNode.java @@ -22,18 +22,22 @@ * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ -package org.alfresco.service.cmr.repository; +package org.alfresco.repo.template; import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.text.MessageFormat; import java.util.Date; +import java.util.List; import java.util.Map; import java.util.Set; import org.alfresco.model.ContentModel; -import org.alfresco.service.cmr.repository.TemplateNode.TemplateContentData; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.TemplateException; import org.alfresco.service.cmr.version.Version; import org.alfresco.service.cmr.version.VersionType; import org.alfresco.service.namespace.QName; @@ -46,7 +50,7 @@ import org.springframework.util.StringUtils; * * @author Kevin Roast */ -public class VersionHistoryNode implements Serializable +public class VersionHistoryNode extends BaseContentNode { private QNameMap properties; private boolean propsRetrieved = false; @@ -59,7 +63,7 @@ public class VersionHistoryNode implements Serializable * * @param version Descriptor of the node version information */ - public VersionHistoryNode(Version version, TemplateNode parent) + public VersionHistoryNode(Version version, TemplateNode parent, ServiceRegistry services) { if (version == null) { @@ -69,8 +73,13 @@ public class VersionHistoryNode implements Serializable { throw new IllegalArgumentException("Parent TemplateNode is mandatory."); } + if (services == null) + { + throw new IllegalArgumentException("The ServiceRegistry must be supplied."); + } this.version = version; this.parent = parent; + this.services = services; this.properties = new QNameMap(parent.services.getNamespaceService()); } @@ -238,26 +247,23 @@ public class VersionHistoryNode implements Serializable } } + /** + * @see org.alfresco.repo.template.TemplateProperties#getChildren() + */ + public List getChildren() + { + return null; + } + // ------------------------------------------------------------------------------ // Content API /** - * @return the content String for this node from the default content property - * (@see ContentModel.PROP_CONTENT) - */ - public String getContent() - { - TemplateContentData content = (TemplateContentData)this.getProperties().get(ContentModel.PROP_CONTENT); - return content != null ? content.getContent() : ""; - } - - /** - * @return For a content document, this method returns the URL to the content stream for + * @return Returns the URL to the content stream for the frozen state of the node from * the default content property (@see ContentModel.PROP_CONTENT) - *

- * For a container node, this method return the URL to browse to the folder in the web-client */ + @Override public String getUrl() { NodeRef nodeRef = this.version.getFrozenStateNodeRef(); @@ -274,24 +280,4 @@ public class VersionHistoryNode implements Serializable throw new TemplateException("Failed to encode content URL for node: " + nodeRef, err); } } - - /** - * @return The mimetype encoding for content attached to the node from the default content property - * (@see ContentModel.PROP_CONTENT) - */ - public String getMimetype() - { - TemplateContentData content = (TemplateContentData)this.getProperties().get(ContentModel.PROP_CONTENT); - return (content != null ? content.getMimetype() : null); - } - - /** - * @return The size in bytes of the content attached to the node from the default content property - * (@see ContentModel.PROP_CONTENT) - */ - public long getSize() - { - TemplateContentData content = (TemplateContentData)this.getProperties().get(ContentModel.PROP_CONTENT); - return (content != null ? content.getSize() : 0L); - } } diff --git a/source/java/org/alfresco/repo/template/XPathResultsMap.java b/source/java/org/alfresco/repo/template/XPathResultsMap.java index 858ac48ef3..7b0a91e1b8 100644 --- a/source/java/org/alfresco/repo/template/XPathResultsMap.java +++ b/source/java/org/alfresco/repo/template/XPathResultsMap.java @@ -25,7 +25,6 @@ package org.alfresco.repo.template; import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.repository.TemplateNode; /** * A special Map that executes an XPath against the parent Node as part of the get()