DocumentProviderUtils.java
/*
* Copyright (C) 2003-2008 eXo Platform SAS.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation; either version 3
* 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, see<http://www.gnu.org/licenses/>.
*/
package org.exoplatform.ecm.webui.component.explorer;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.NodeTypeIterator;
import javax.jcr.nodetype.NodeTypeManager;
import javax.jcr.query.Query;
import javax.jcr.query.Row;
import org.apache.commons.lang.StringUtils;
import org.exoplatform.commons.api.search.data.SearchResult;
import org.exoplatform.ecm.jcr.model.Preference;
import org.exoplatform.ecm.webui.utils.Utils;
import org.exoplatform.services.cms.documents.DocumentTypeService;
import org.exoplatform.services.cms.link.LinkManager;
import org.exoplatform.services.cms.link.NodeFinder;
import org.exoplatform.services.cms.link.NodeLinkAware;
import org.exoplatform.services.cms.templates.TemplateService;
import org.exoplatform.services.jcr.ext.common.SessionProvider;
import org.exoplatform.services.jcr.ext.hierarchy.NodeHierarchyCreator;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.services.security.ConversationState;
import org.exoplatform.services.wcm.core.NodetypeConstant;
import org.exoplatform.services.wcm.search.base.LazyPageList;
import org.exoplatform.services.wcm.search.base.PageListFactory;
import org.exoplatform.services.wcm.search.base.QueryData;
import org.exoplatform.services.wcm.search.base.SearchDataCreator;
import org.exoplatform.services.wcm.utils.WCMCoreUtils;
/**
* Created by The eXo Platform SARL
* Author : Nguyen Anh Vu
* anhvurz90@gmail.com
* Nov 9, 2009
* 1:48:20 PM
*/
public class DocumentProviderUtils {
private static final String Contents_Document_Type = "Content";
private static final String FAVORITE_ALIAS = "userPrivateFavorites";
private static final Log LOG = ExoLogger.getLogger(DocumentProviderUtils.class.getName());
private static final String[] prohibitedSortType = {
NodetypeConstant.SORT_BY_NODESIZE,
NodetypeConstant.SORT_BY_NODETYPE,
NodetypeConstant.SORT_BY_DATE, };
private static DocumentProviderUtils docProviderUtil_ = new DocumentProviderUtils();
private List<String> folderTypes_;
private DocumentProviderUtils() {
}
public static DocumentProviderUtils getInstance() { return docProviderUtil_; }
public boolean canSortType(String sortType) {
for (String type : prohibitedSortType) {
if (type.equals(sortType)) {
return false;
}
}
return true;
}
public <E> LazyPageList<E> getPageList(String ws, String path, Preference pref,
Set<String> allItemFilter, Set<String> allItemByTypeFilter,
SearchDataCreator<E> dataCreater) throws Exception{
String statement = getStatement(ws, path, pref, allItemFilter, allItemByTypeFilter);
QueryData queryData = new QueryData(statement, ws, Query.SQL,
WCMCoreUtils.getRemoteUser().equals(WCMCoreUtils.getSuperUser()));
return PageListFactory.createLazyPageList(queryData, pref.getNodesPerPage(),dataCreater);
}
public LazyPageList<NodeLinkAware> getPageList(String ws, String path, Preference pref,
Set<String> allItemFilter, Set<String> allItemByTypeFilter,
NodeLinkAware parent) throws Exception {
LinkManager linkManager = WCMCoreUtils.getService(LinkManager.class);
NodeFinder nodeFinder = WCMCoreUtils.getService(NodeFinder.class);
String statement;
try {
Node node = (Node)nodeFinder.getItem(ws, path);
if (linkManager.isLink(node)) {
path = linkManager.getTarget(node).getPath();
}else{
path = node.getPath();
}
statement = getStatement(ws, path, pref, allItemFilter, allItemByTypeFilter);
} catch (Exception e) {
statement = null;
}
QueryData queryData = new QueryData(statement, ws, Query.SQL,
WCMCoreUtils.getRemoteUser().equals(WCMCoreUtils.getSuperUser()));
return PageListFactory.createLazyPageList(queryData, pref.getNodesPerPage(), new NodeLinkAwareCreator(parent));
}
private String getStatement(String ws, String path, Preference pref,
Set<String> allItemsFilterSet, Set<String> allItemsByTypeFilter)
throws Exception {
StringBuilder buf = new StringBuilder();
//path
buf = addPathParam(buf, path);
//jcrEnable
buf = addJcrEnableParam(buf, ws, path, pref);
//show non document
buf = addShowNonDocumentType(buf, pref, allItemsByTypeFilter);
//show hidden node
buf = addShowHiddenNodeParam(buf, pref);
//owned by me
buf = addOwnedByMeParam(buf, allItemsFilterSet);
//favorite
buf = addFavoriteParam(buf, ws, allItemsFilterSet);
//all items by type
buf = addAllItemByType(buf, allItemsByTypeFilter);
//sort
buf = addSortParam(buf, pref);
return (buf == null) ? null : buf.toString();
}
/**
* add path condition to query statement
*/
private StringBuilder addPathParam(StringBuilder buf, String path) {
buf.append("SELECT * FROM nt:base ");
if (path != null) {
if (path.endsWith("/")) {
path = path.substring(0, path.length() - 1);
}
buf.append("WHERE jcr:path LIKE '").append(path)
.append("/%' AND NOT jcr:path LIKE '").append(path).append("/%/%' ");
}
return buf;
}
/**
* add is_jcr_enable condition to query statement
*/
private StringBuilder addJcrEnableParam(StringBuilder buf, String ws, String path, Preference pref)
throws Exception {
TemplateService templateService = WCMCoreUtils.getService(TemplateService.class);
SessionProvider provider = WCMCoreUtils.getUserSessionProvider();
Session session = provider.getSession(ws, WCMCoreUtils.getRepository());
Node node = (Node)session.getItem(path);
if(!pref.isJcrEnable() &&
templateService.isManagedNodeType(node.getPrimaryNodeType().getName()) &&
!(node.isNodeType(NodetypeConstant.NT_FOLDER) || node.isNodeType(NodetypeConstant.NT_UNSTRUCTURED) )) {
return null;
}
return buf;
}
/**
* add show_non_document_type condition to query statement
*/
private StringBuilder addShowNonDocumentType(StringBuilder buf, Preference pref, Set<String> allItemsByTypeFilter)
throws Exception {
if (buf == null) return null;
if (!pref.isShowNonDocumentType() || allItemsByTypeFilter.contains(Contents_Document_Type)) {
if (folderTypes_ == null) {
folderTypes_ = getFolderTypes();
}
buf.append(" AND (");
//nt:unstructured && nt:folder
buf.append("( jcr:primaryType='").append(Utils.NT_UNSTRUCTURED)
.append("') OR (exo:primaryType='").append(Utils.NT_UNSTRUCTURED).append("') ");
buf.append(" OR ( jcr:primaryType='").append(Utils.NT_FOLDER)
.append("') OR (exo:primaryType='").append(Utils.NT_FOLDER).append("') ");
//supertype of nt:unstructured or nt:folder
for (String fType : folderTypes_) {
buf.append(" OR ( jcr:primaryType='").append(fType)
.append("') OR (exo:primaryType='").append(fType).append("') ");
}
//all document type
TemplateService templateService = WCMCoreUtils.getService(TemplateService.class);
List<String> docTypes = templateService.getDocumentTemplates();
for (String docType : docTypes) {
buf.append(" OR ( jcr:primaryType='").append(docType)
.append("') OR (exo:primaryType='").append(docType).append("') ");
}
buf.append(" ) ");
}
return buf;
}
private List<String> getFolderTypes() {
List<String> ret = new ArrayList<String>();
NodeTypeManager nodeTypeManager = WCMCoreUtils.getRepository().getNodeTypeManager();
try {
for (NodeTypeIterator iter = nodeTypeManager.getAllNodeTypes(); iter.hasNext();) {
NodeType type = iter.nextNodeType();
if (type.isNodeType(NodetypeConstant.NT_FOLDER) || type.isNodeType(NodetypeConstant.NT_UNSTRUCTURED)) {
ret.add(type.getName());
}
}
} catch (RepositoryException e) {
if (LOG.isWarnEnabled()) {
LOG.warn("Can not get all node types", e.getMessage());
}
}
return ret;
}
/**
* add show_hidden_node condition to query statement
*/
private StringBuilder addShowHiddenNodeParam(StringBuilder buf, Preference pref) {
if (buf == null) return null;
if (!pref.isShowHiddenNode()) {
buf.append(" AND ( NOT jcr:mixinTypes='").append(NodetypeConstant.EXO_HIDDENABLE).append("')");
}
return buf;
}
/**
* add owned_by_me condition to query statement
*/
private StringBuilder addOwnedByMeParam(StringBuilder buf, Set<String> allItemsFilterSet) {
if (buf == null) return null;
if (allItemsFilterSet.contains(NodetypeConstant.OWNED_BY_ME)) {
buf.append(" AND ( exo:owner='")
.append(ConversationState.getCurrent().getIdentity().getUserId())
.append("')");
}
return buf;
}
/**
* add favorite condition to query statement
* @throws Exception
*/
private StringBuilder addFavoriteParam(StringBuilder buf, String ws, Set<String> allItemsFilterSet)
throws Exception {
if (buf == null) return null;
if (allItemsFilterSet.contains(NodetypeConstant.FAVORITE)) {
NodeHierarchyCreator nodeHierarchyCreator = WCMCoreUtils.getService(NodeHierarchyCreator.class);
Node userNode =
nodeHierarchyCreator.getUserNode(WCMCoreUtils.getSystemSessionProvider(),
ConversationState.getCurrent().getIdentity().getUserId());
String favoritePath = nodeHierarchyCreator.getJcrPath(FAVORITE_ALIAS);
int count = 0;
buf.append(" AND (");
for (NodeIterator iter = userNode.getNode(favoritePath).getNodes();iter.hasNext();) {
Node node = iter.nextNode();
if (node.isNodeType(NodetypeConstant.EXO_SYMLINK) &&
node.hasProperty(NodetypeConstant.EXO_WORKSPACE) &&
ws.equals(node.getProperty(NodetypeConstant.EXO_WORKSPACE).getString())) {
if (count ++ > 0) {
buf.append(" OR ");
}
buf.append(" jcr:uuid='")
.append(node.getProperty("exo:uuid").getString())
.append("'");
}
}
buf.append(" ) ");
if (count == 0) {
return null;
}
}
return buf;
}
/**
* add mimetype condition to query statement
*/
private StringBuilder addAllItemByType(StringBuilder buf, Set<String> allItemsByTypeFilterSet) {
if(allItemsByTypeFilterSet.isEmpty()) {
return buf;
}
DocumentTypeService documentTypeService = WCMCoreUtils.getService(DocumentTypeService.class);
StringBuilder buf1 = new StringBuilder(" AND (");
int count = 0;
for (String documentType : allItemsByTypeFilterSet) {
for (String mimeType : documentTypeService.getMimeTypes(documentType)) {
if (count++ > 0) {
buf1.append(" OR ");
}
if (mimeType.endsWith("/")) { mimeType = mimeType.substring(0, mimeType.length() - 1); }
buf1.append(" 'jcr:content/jcr:mimeType' like '").append(mimeType).append("/%'");
}
}
buf1.append(" )");
if (count > 0) {
buf.append(buf1);
}
return buf;
}
/**
* adds 'sort by' condition to query statement
*/
private StringBuilder addSortParam(StringBuilder buf, Preference pref) {
if (buf == null) return null;
String type = "";
if (NodetypeConstant.SORT_BY_NODENAME.equals(pref.getSortType())) { type="exo:name"; }
else if (NodetypeConstant.SORT_BY_CREATED_DATE.equals(pref.getSortType())) {
type = NodetypeConstant.EXO_DATE_CREATED;
} else if (NodetypeConstant.SORT_BY_MODIFIED_DATE.equals(pref.getSortType())) {
type = NodetypeConstant.EXO_LAST_MODIFIED_DATE;
} else { type= pref.getSortType(); }
buf.append(" ORDER BY ").append(type).append(" ");
buf.append("Ascending".equals(pref.getOrder()) ? "ASC" : "DESC");
return buf;
}
/**
* Simple data creator, just creates the node result itself
*/
public class NodeLinkAwareCreator implements SearchDataCreator<NodeLinkAware> {
private NodeLinkAware parent;
public NodeLinkAwareCreator(NodeLinkAware parent) {
this.parent = parent;
}
@Override
public NodeLinkAware createData(Node node, Row row, SearchResult searchResult) {
try {
return (NodeLinkAware)parent.getNode(StringUtils.substringAfterLast(node.getPath(), "/"));
} catch (RepositoryException e) {
LOG.error("Can not create NodeLinkAware", e);
}
return null;
}
}
}