/*
* Copyright (C) 2005-2012 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see .
*/
package org.alfresco.repo.model.filefolder;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.query.CannedQueryParameters;
import org.alfresco.repo.domain.node.NodeDAO;
import org.alfresco.repo.domain.node.NodePropertyHelper;
import org.alfresco.repo.domain.qname.QNameDAO;
import org.alfresco.repo.domain.query.CannedQueryDAO;
import org.alfresco.repo.model.filefolder.HiddenAspect.Visibility;
import org.alfresco.repo.node.getchildren.FilterProp;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.repo.security.permissions.impl.acegi.MethodSecurityBean;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.FileFilterMode;
import org.alfresco.util.FileFilterMode.Client;
/**
* GetChidren canned query for files and folders.
*
* To get paged list of files and folders of a parent folder filtered by child type.
* Also optionally filtered and/or sorted by one or more properties (up to three).
*
* This is the same as the nodes getchildren canned query, except it takes into account hidden files and folders (with respect to client visibility)
* and other aspect(s) to ignore - eg. optionally "cm:checkedOut" in case of Share DocLib.
*
* @since 4.1.1
* @author steveglover, janv
*
*/
public class GetChildrenCannedQuery extends org.alfresco.repo.node.getchildren.GetChildrenCannedQuery
{
private HiddenAspect hiddenAspect;
private DictionaryService dictionaryService;
private NodeService nodeService;
private Set ignoreAspectQNames;
public GetChildrenCannedQuery(
NodeDAO nodeDAO,
QNameDAO qnameDAO,
CannedQueryDAO cannedQueryDAO,
NodePropertyHelper nodePropertyHelper,
TenantService tenantService,
MethodSecurityBean methodSecurity,
CannedQueryParameters params,
HiddenAspect hiddenAspect,
DictionaryService dictionaryService,
NodeService nodeService,
Set ignoreAspectQNames)
{
super(nodeDAO, qnameDAO, cannedQueryDAO, nodePropertyHelper, tenantService, methodSecurity, params);
this.hiddenAspect = hiddenAspect;
this.dictionaryService = dictionaryService;
this.nodeService = nodeService;
this.ignoreAspectQNames = ignoreAspectQNames;
}
@Override
protected UnsortedChildQueryCallback getUnsortedChildQueryCallback(final List rawResult, final int requestedCount)
{
UnsortedChildQueryCallback callback = new FileFolderUnsortedChildQueryCallback(rawResult, requestedCount);
return callback;
}
@Override
protected FilterSortChildQueryCallback getFilterSortChildQuery(final List children, final List filterProps)
{
FilterSortChildQueryCallback callback = new FileFolderFilterSortChildQueryCallback(children, filterProps);
return callback;
}
private class FileFolderFilterSortChildQueryCallback extends DefaultFilterSortChildQueryCallback
{
private Map isTypeFolderMap = new HashMap(10);
public FileFolderFilterSortChildQueryCallback(List children, List filterProps)
{
super(children, filterProps);
}
@Override
protected boolean include(FilterSortNode node)
{
boolean ret = super.include(node);
return ret && includeImpl(ret, node.getNodeRef());
}
@Override
public boolean handle(FilterSortNode node)
{
super.handle(node);
Map propVals = node.getPropVals();
QName nodeTypeQName = (QName)propVals.get(GetChildrenCannedQuery.SORT_QNAME_NODE_TYPE);
if (nodeTypeQName != null)
{
// ALF-13968
Boolean isFolder = isTypeFolderMap.get(nodeTypeQName);
if (isFolder == null)
{
isFolder = dictionaryService.isSubClass(nodeTypeQName, ContentModel.TYPE_FOLDER);
isTypeFolderMap.put(nodeTypeQName, isFolder);
}
propVals.put(GetChildrenCannedQuery.SORT_QNAME_NODE_IS_FOLDER, isFolder);
}
return true;
}
}
private class FileFolderUnsortedChildQueryCallback extends DefaultUnsortedChildQueryCallback
{
public FileFolderUnsortedChildQueryCallback(List rawResult,int requestedCount)
{
super(rawResult, requestedCount);
}
@Override
protected boolean include(NodeRef nodeRef)
{
boolean ret = super.include(nodeRef);
return ret && includeImpl(ret, nodeRef);
}
}
protected boolean includeImpl(boolean ret, NodeRef nodeRef)
{
// only visible files are returned, relative to the client type.
try
{
final Client client = FileFilterMode.getClient();
boolean notHidden = hiddenAspect.getVisibility(client, nodeRef) != Visibility.NotVisible;
boolean notIgnore = true;
if (ignoreAspectQNames != null)
{
if (ignoreAspectQNames.size() > 1)
{
Set nodeAspects = nodeService.getAspects(nodeRef);
notIgnore = (! nodeAspects.removeAll(ignoreAspectQNames));
}
else if (ignoreAspectQNames.size() == 1)
{
if (nodeService.hasAspect(nodeRef, ignoreAspectQNames.iterator().next()))
{
notIgnore = false;
}
}
}
return ret && notHidden && notIgnore;
}
catch (AccessDeniedException e)
{
// user may not have permission to determine the visibility of the node
return ret;
}
}
}