org.opencms.ade.galleries.CmsGalleryService.java Source code

Java tutorial

Introduction

Here is the source code for org.opencms.ade.galleries.CmsGalleryService.java

Source

/*
 * This library is part of OpenCms -
 * the Open Source Content Management System
 *
 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
 *
 * This library 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 2.1 of the License, or (at your option) any later version.
 *
 * This library 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.
 *
 * For further information about Alkacon Software, please see the
 * company website: http://www.alkacon.com
 *
 * For further information about OpenCms, please see the
 * project website: http://www.opencms.org
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package org.opencms.ade.galleries;

import org.opencms.ade.galleries.CmsGalleryFilteredNavTreeBuilder.NavigationNode;
import org.opencms.ade.galleries.preview.I_CmsPreviewProvider;
import org.opencms.ade.galleries.shared.CmsGalleryConfiguration;
import org.opencms.ade.galleries.shared.CmsGalleryDataBean;
import org.opencms.ade.galleries.shared.CmsGalleryFolderBean;
import org.opencms.ade.galleries.shared.CmsGallerySearchBean;
import org.opencms.ade.galleries.shared.CmsGallerySearchScope;
import org.opencms.ade.galleries.shared.CmsGalleryTabConfiguration;
import org.opencms.ade.galleries.shared.CmsResourceTypeBean;
import org.opencms.ade.galleries.shared.CmsResourceTypeBean.TypeVisibility;
import org.opencms.ade.galleries.shared.CmsResultItemBean;
import org.opencms.ade.galleries.shared.CmsSitemapEntryBean;
import org.opencms.ade.galleries.shared.CmsVfsEntryBean;
import org.opencms.ade.galleries.shared.I_CmsGalleryProviderConstants;
import org.opencms.ade.galleries.shared.I_CmsGalleryProviderConstants.GalleryMode;
import org.opencms.ade.galleries.shared.I_CmsGalleryProviderConstants.GalleryTabId;
import org.opencms.ade.galleries.shared.I_CmsGalleryProviderConstants.SortParams;
import org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService;
import org.opencms.file.CmsObject;
import org.opencms.file.CmsProperty;
import org.opencms.file.CmsPropertyDefinition;
import org.opencms.file.CmsResource;
import org.opencms.file.CmsResourceFilter;
import org.opencms.file.CmsUser;
import org.opencms.file.CmsVfsResourceNotFoundException;
import org.opencms.file.types.CmsResourceTypeBinary;
import org.opencms.file.types.CmsResourceTypeImage;
import org.opencms.file.types.CmsResourceTypePointer;
import org.opencms.file.types.CmsResourceTypeXmlContainerPage;
import org.opencms.file.types.CmsResourceTypeXmlContent;
import org.opencms.file.types.CmsResourceTypeXmlPage;
import org.opencms.file.types.I_CmsResourceType;
import org.opencms.flex.CmsFlexController;
import org.opencms.gwt.CmsCoreService;
import org.opencms.gwt.CmsGwtService;
import org.opencms.gwt.CmsRpcException;
import org.opencms.gwt.CmsVfsService;
import org.opencms.gwt.shared.CmsGwtConstants;
import org.opencms.gwt.shared.CmsIconUtil;
import org.opencms.gwt.shared.CmsListInfoBean;
import org.opencms.i18n.CmsLocaleManager;
import org.opencms.i18n.CmsMessages;
import org.opencms.json.JSONException;
import org.opencms.json.JSONObject;
import org.opencms.jsp.CmsJspNavBuilder;
import org.opencms.jsp.CmsJspNavBuilder.Visibility;
import org.opencms.jsp.CmsJspNavElement;
import org.opencms.loader.CmsLoaderException;
import org.opencms.loader.CmsResourceManager;
import org.opencms.main.CmsException;
import org.opencms.main.CmsLog;
import org.opencms.main.CmsPermalinkResourceHandler;
import org.opencms.main.CmsStaticResourceHandler;
import org.opencms.main.OpenCms;
import org.opencms.search.fields.CmsSearchFieldMapping;
import org.opencms.search.galleries.CmsGallerySearch;
import org.opencms.search.galleries.CmsGallerySearchParameters;
import org.opencms.search.galleries.CmsGallerySearchResult;
import org.opencms.search.galleries.CmsGallerySearchResultList;
import org.opencms.search.solr.CmsSolrIndex;
import org.opencms.security.CmsPermissionSet;
import org.opencms.security.CmsPermissionViolationException;
import org.opencms.staticexport.CmsLinkManager;
import org.opencms.ui.components.CmsResourceIcon;
import org.opencms.util.CmsDateUtil;
import org.opencms.util.CmsRequestUtil;
import org.opencms.util.CmsStringUtil;
import org.opencms.util.CmsUUID;
import org.opencms.util.CmsUriSplitter;
import org.opencms.workplace.CmsWorkplace;
import org.opencms.workplace.CmsWorkplaceMessages;
import org.opencms.workplace.CmsWorkplaceSettings;
import org.opencms.workplace.explorer.CmsResourceUtil;
import org.opencms.xml.containerpage.CmsADESessionCache;

import java.text.DateFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;

/**
 * Handles all RPC services related to the gallery dialog.<p>
 *
 * @since 8.0.0
 *
 * @see org.opencms.ade.galleries.CmsGalleryService
 * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService
 * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryServiceAsync
 */
public class CmsGalleryService extends CmsGwtService implements I_CmsGalleryService {

    /**
     * Gallery info object.<p>
     */
    protected class CmsGalleryTypeInfo {

        /** The content types using this gallery. */
        private List<I_CmsResourceType> m_contentTypes;

        /** The gallery folder resources. */
        private List<CmsResource> m_galleries;

        /** The resource type of this gallery. */
        private I_CmsResourceType m_resourceType;

        /**
         * Constructor.<p>
         *
         * @param resourceType the resource type of the gallery
         * @param contentType the resource type of the gallery content
         * @param galleries the gallery resources
         */
        protected CmsGalleryTypeInfo(I_CmsResourceType resourceType, I_CmsResourceType contentType,
                List<CmsResource> galleries) {

            m_resourceType = resourceType;
            m_contentTypes = new ArrayList<I_CmsResourceType>();
            m_contentTypes.add(contentType);
            m_galleries = galleries;
        }

        /**
         * Adds a type to the list of content types.<p>
         *
         * @param type the type to add
         */
        protected void addContentType(I_CmsResourceType type) {

            m_contentTypes.add(type);
        }

        /**
         * Returns the contentTypes.<p>
         *
         * @return the contentTypes
         */
        protected List<I_CmsResourceType> getContentTypes() {

            return m_contentTypes;
        }

        /**
         * Returns the gallery folder resources.<p>
         *
         * @return the resources
         */
        protected List<CmsResource> getGalleries() {

            return m_galleries;
        }

        /**
         * Returns the resourceType.<p>
         *
         * @return the resourceType
         */
        protected I_CmsResourceType getResourceType() {

            return m_resourceType;
        }

        /**
         * Sets the contentTypes.<p>
         *
         * @param contentTypes the contentTypes to set
         */
        protected void setContentTypes(List<I_CmsResourceType> contentTypes) {

            m_contentTypes = contentTypes;
        }

        /**
         * Sets the galleries.<p>
         *
         * @param galleries the gallery resource list to set
         */
        protected void setGalleries(List<CmsResource> galleries) {

            m_galleries = galleries;
        }

        /**
         * Sets the resourceType.<p>
         *
         * @param resourceType the resourceType to set
         */
        protected void setResourceType(I_CmsResourceType resourceType) {

            m_resourceType = resourceType;
        }
    }

    /** Bean used to store a single type together with a flag indicating its visibility. */
    class TypeWithVisibility {

        /** True if the type should only be shown in the full list. */
        private boolean m_onlyShowInFullList;

        /** The resource type. */
        private I_CmsResourceType m_type;

        /**
         * Creates a new instance.<p>
         *
         * @param type the resource type
         * @param onlyShowInFullList the flag to control the visibility
         */
        public TypeWithVisibility(I_CmsResourceType type, boolean onlyShowInFullList) {

            m_type = type;
            m_onlyShowInFullList = onlyShowInFullList;
        }

        /**
         * Returns the type.<p>
         *
         * @return the type
         */
        public I_CmsResourceType getType() {

            return m_type;
        }

        /**
         * Returns the onlyShowInFullList.<p>
         *
         * @return the onlyShowInFullList
         */
        public boolean isOnlyShowInFullList() {

            return m_onlyShowInFullList;
        }

    }

    /** Key for additional info gallery folder filter. */
    public static final String FOLDER_FILTER_ADD_INFO_KEY = "gallery_folder_filter";

    /** Limit to the number results loaded on initial search. */
    public static final int INITIAL_SEARCH_MAX_RESULTS = 200;

    /** The key used for storing the last used gallery in adeview mode. */
    public static final String KEY_LAST_USED_GALLERY_ADEVIEW = "__adeView";

    /** Name for the 'galleryShowInvalidDefault' preference. */
    public static final String PREF_GALLERY_SHOW_INVALID_DEFAULT = "galleryShowInvalidDefault";

    /** Key for additional info gallery result view type. */
    public static final String RESULT_VIEW_TYPE_ADD_INFO_KEY = "gallery_result_view_type";

    /** The logger instance for this class. */
    private static final Log LOG = CmsLog.getLog(CmsGalleryService.class);

    /** Serialization uid. */
    private static final long serialVersionUID = 1673026761080584889L;

    /** The instance of the resource manager. */
    CmsResourceManager m_resourceManager;

    /** The workplace settings of the current user. */
    private CmsWorkplaceSettings m_workplaceSettings;

    /** The workplace locale from the current user's settings. */
    private Locale m_wpLocale;

    /**
     * Generates the pre-loaded contents for the VFS tab of the gallery dialog.<p>
     *
     * @param cms the current CMS context
     * @param vfsState the saved VFS tree state (may be null)
     * @param folders the saved search folders (may be null)
     *
     * @return the root tree entry for the VFS tab
     */
    public static CmsVfsEntryBean generateVfsPreloadData(final CmsObject cms, final CmsTreeOpenState vfsState,
            final Set<String> folders) {

        CmsVfsEntryBean vfsPreloadData = null;

        A_CmsTreeTabDataPreloader<CmsVfsEntryBean> vfsloader = new A_CmsTreeTabDataPreloader<CmsVfsEntryBean>() {

            @SuppressWarnings("synthetic-access")
            @Override
            protected CmsVfsEntryBean createEntry(CmsObject innerCms, CmsResource resource) throws CmsException {

                String title = innerCms.readPropertyObject(resource, CmsPropertyDefinition.PROPERTY_TITLE, false)
                        .getValue();
                boolean isEditable = false;
                try {
                    isEditable = innerCms.hasPermissions(resource, CmsPermissionSet.ACCESS_WRITE, false,
                            CmsResourceFilter.ALL);
                } catch (CmsException e) {
                    LOG.info(e.getLocalizedMessage(), e);
                }

                return internalCreateVfsEntryBean(innerCms, resource, title, true, isEditable, null, false);
            }

        };
        Set<CmsResource> treeOpenResources = Sets.newHashSet();
        if (vfsState != null) {

            for (CmsUUID structureId : vfsState.getOpenItems()) {
                try {
                    treeOpenResources.add(cms.readResource(structureId, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED));
                } catch (CmsException e) {
                    LOG.warn(e.getLocalizedMessage(), e);
                }
            }
        }
        CmsObject rootCms = null;
        Set<CmsResource> folderSetResources = Sets.newHashSet();
        try {
            rootCms = OpenCms.initCmsObject(cms);
            rootCms.getRequestContext().setSiteRoot("");
            if (!((folders == null) || folders.isEmpty())) {
                for (String folder : folders) {
                    try {
                        folderSetResources
                                .add(rootCms.readResource(folder, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED));
                    } catch (CmsException e) {
                        LOG.warn(e.getLocalizedMessage(), e);
                    }
                }
            }
        } catch (CmsException e1) {
            LOG.error(e1.getLocalizedMessage(), e1);
        }
        try {
            vfsPreloadData = vfsloader.preloadData(cms, treeOpenResources, folderSetResources);
        } catch (CmsException e) {
            LOG.error(e.getLocalizedMessage(), e);
        }

        return vfsPreloadData;

    }

    /**
     * Returns the initial gallery settings.<p>
     *
     * @param request the current request
     * @param config the gallery configuration
     *
     * @return the initial gallery settings
     *
     * @throws CmsRpcException if something goes wrong
     */
    public static CmsGalleryDataBean getInitialSettings(HttpServletRequest request, CmsGalleryConfiguration config)
            throws CmsRpcException {

        CmsGalleryService srv = new CmsGalleryService();
        srv.setCms(CmsFlexController.getCmsObject(request));
        srv.setRequest(request);
        CmsGalleryDataBean result = null;
        try {
            result = srv.getInitialSettings(config);
        } finally {
            srv.clearThreadStorage();
        }
        return result;
    }

    /**
     * Returns the initial search data.<p>
     *
     * @param request the current request
     * @param config the gallery configuration
     *
     * @return the search data
     */
    public static CmsGallerySearchBean getSearch(HttpServletRequest request, CmsGalleryDataBean config) {

        CmsGalleryService srv = new CmsGalleryService();
        srv.setCms(CmsFlexController.getCmsObject(request));
        srv.setRequest(request);
        CmsGallerySearchBean result = null;
        try {
            result = srv.getSearch(config);
        } finally {
            srv.clearThreadStorage();
        }
        return result;
    }

    /**
     * Gets the attribute name for a tree open state.<p>
     *
     * @param treeName the tree name
     * @param treeToken the tree token
     *
     * @return the attribute name for the tree
     */
    public static String getTreeOpenStateAttributeName(String treeName, String treeToken) {

        return "tree_" + treeName + "_" + treeToken;
    }

    /**
     * Convenience method for reading the saved VFS tree state from the session.<p>
     *
     * @param request the current request
     * @param treeToken the tree token (may be null)
     *
     * @return the saved tree open state (may be null)
     */
    public static CmsTreeOpenState getVfsTreeState(HttpServletRequest request, String treeToken) {

        return (CmsTreeOpenState) request.getSession()
                .getAttribute(getTreeOpenStateAttributeName(I_CmsGalleryProviderConstants.TREE_VFS, treeToken));

    }

    /**
     * Creates the VFS entry bean for a resource.<p>
     *
     * @param cms the CMS context to use
     * @param resource the resource for which to create the VFS entry bean
     * @param title the title
     * @param isRoot true if this is a root entry
     * @param isEditable true if this entry is editable
     * @param children the children of the entry
     * @param isMatch true if the VFS entry bean is a match for the quick search
     *
     * @return the created VFS entry bean
     * @throws CmsException if something goes wrong
     */
    public static CmsVfsEntryBean internalCreateVfsEntryBean(CmsObject cms, CmsResource resource, String title,
            boolean isRoot, boolean isEditable, List<CmsVfsEntryBean> children, boolean isMatch)
            throws CmsException {

        String rootPath = resource.getRootPath();
        CmsUUID structureId = resource.getStructureId();
        CmsVfsEntryBean result = new CmsVfsEntryBean(rootPath, structureId, title, isRoot, isEditable, children,
                isMatch);
        String siteRoot = null;
        if (resource.isFolder()) {
            cms = OpenCms.initCmsObject(cms);
            cms.getRequestContext().setSiteRoot("");
            List<CmsResource> realChildren = cms.getResourcesInFolder(rootPath,
                    CmsResourceFilter.ONLY_VISIBLE_NO_DELETED);
            List<CmsResource> effectiveChildren = new ArrayList<CmsResource>();
            for (CmsResource realChild : realChildren) {
                if (realChild.isFolder()) {
                    effectiveChildren.add(realChild);
                }
            }
            if (effectiveChildren.isEmpty()) {
                result.setChildren(new ArrayList<CmsVfsEntryBean>());
            }
        }

        if (OpenCms.getSiteManager().startsWithShared(rootPath)) {
            siteRoot = OpenCms.getSiteManager().getSharedFolder();
        } else {
            String tempSiteRoot = OpenCms.getSiteManager().getSiteRoot(rootPath);
            if (tempSiteRoot != null) {
                siteRoot = tempSiteRoot;
            } else {
                siteRoot = "";
            }
        }
        result.setSiteRoot(siteRoot);
        return result;
    }

    /**
     * Returns the resource types beans.<p>
     *
     * @param resourceTypes the resource types
     * @param creatableTypes the creatable types
     * @param deactivatedTypes the deactivated types
     * @param typesForTypeTab the types which should be shown in the types tab according to the gallery configuration
     *
     * @return the resource types
     */
    public List<CmsResourceTypeBean> buildTypesList(List<I_CmsResourceType> resourceTypes,
            Set<String> creatableTypes, Set<String> deactivatedTypes, final List<String> typesForTypeTab) {

        List<CmsResourceTypeBean> result = buildTypesList(resourceTypes, creatableTypes);

        for (CmsResourceTypeBean typeBean : result) {
            if ((typesForTypeTab != null) && (typesForTypeTab.size() > 0)) {
                if (!typesForTypeTab.contains(typeBean.getType())) {
                    if (typeBean.getVisibility() != TypeVisibility.hidden) {
                        typeBean.setVisibility(TypeVisibility.showOptional);
                    }
                }
            }
            typeBean.setDeactivated(deactivatedTypes.contains(typeBean.getType()));
        }
        if ((typesForTypeTab != null) && (typesForTypeTab.size() > 0)) {
            Collections.sort(result, new Comparator<CmsResourceTypeBean>() {

                public int compare(CmsResourceTypeBean first, CmsResourceTypeBean second) {

                    return ComparisonChain.start().compare(searchTypeRank(first), searchTypeRank(second))
                            .compare(first.getType(), second.getType()).result();
                }

                int searchTypeRank(CmsResourceTypeBean type) {

                    int index = typesForTypeTab.indexOf(type.getType());
                    if (index == -1) {
                        return Integer.MAX_VALUE;
                    } else {
                        return index;
                    }
                }
            });

        }

        return result;
    }

    /**
     * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#deleteResource(java.lang.String)
     */
    public void deleteResource(String resourcePath) throws CmsRpcException {

        try {
            ensureLock(resourcePath);
            getCmsObject().deleteResource(resourcePath, CmsResource.DELETE_PRESERVE_SIBLINGS);
        } catch (Exception e) {
            error(e);
        }
    }

    /**
     * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#getAdeViewModeConfiguration()
     */
    public CmsGalleryConfiguration getAdeViewModeConfiguration() {

        CmsGalleryConfiguration result = new CmsGalleryConfiguration();
        List<String> typeNames = new ArrayList<String>();

        for (I_CmsResourceType type : OpenCms.getResourceManager().getResourceTypes()) {
            Class<?> typeClass = type.getClass();
            if (CmsResourceTypeXmlContent.class.isAssignableFrom(typeClass)
                    || CmsResourceTypeXmlPage.class.isAssignableFrom(typeClass)) {
                continue;
            }
            if (type.getGalleryTypes().size() > 0) {
                typeNames.add(type.getTypeName());
            }
        }
        result.setSearchTypes(typeNames);
        result.setResourceTypes(typeNames);
        result.setGalleryMode(GalleryMode.adeView);
        result.setGalleryStoragePrefix("" + GalleryMode.adeView);
        result.setTabConfiguration(CmsGalleryTabConfiguration.resolve("selectDoc"));
        return result;
    }

    /**
     * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#getGalleries(java.util.List)
     */
    public List<CmsGalleryFolderBean> getGalleries(List<String> resourceTypes) {

        return buildGalleriesList(readGalleryInfosByTypeNames(resourceTypes));
    }

    /**
     * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#getInfoForResource(java.lang.String, java.lang.String)
     */
    public CmsResultItemBean getInfoForResource(String linkPath, String locale) throws CmsRpcException {

        CmsResultItemBean result = null;
        CmsObject cms = getCmsObject();
        CmsMessages messageBundle = Messages.get().getBundle(getWorkplaceLocale());
        try {
            if (new CmsUriSplitter(linkPath).getProtocol() != null) {
                result = new CmsResultItemBean();
                result.setTitle(messageBundle.key(Messages.GUI_EXTERNAL_LINK_0));
                result.setSubTitle("");
                result.setType(CmsResourceTypePointer.getStaticTypeName());
            } else if (CmsStaticResourceHandler.isStaticResourceUri(linkPath)) {
                result = new CmsResultItemBean();
                result.setTitle(messageBundle.key(Messages.GUI_STATIC_RESOURCE_0));
                result.setSubTitle(CmsStaticResourceHandler.removeStaticResourcePrefix(linkPath));
                result.setType(CmsResourceTypeBinary.getStaticTypeName());
            } else {
                boolean notFound = false;
                String path = linkPath;
                String siteRoot = OpenCms.getSiteManager().getSiteRoot(linkPath);
                String oldSite = cms.getRequestContext().getSiteRoot();
                try {
                    if (siteRoot != null) {
                        // only switch the site if needed
                        cms.getRequestContext().setSiteRoot(siteRoot);
                        // remove the site root, because the link manager call will append it anyway
                        path = cms.getRequestContext().removeSiteRoot(linkPath);
                    }
                    // remove parameters, if not the link manager call might fail
                    int pos = path.indexOf(CmsRequestUtil.URL_DELIMITER);
                    int anchorPos = path.indexOf('#');
                    if ((pos == -1) || ((anchorPos > -1) && (pos > anchorPos))) {
                        pos = anchorPos;
                    }
                    if (pos > -1) {
                        path = path.substring(0, pos);
                    }
                    // get the root path
                    path = OpenCms.getLinkManager().getRootPath(cms, path);

                } catch (Exception e) {
                    notFound = true;
                } finally {
                    if (siteRoot != null) {
                        cms.getRequestContext().setSiteRoot(oldSite);
                    }
                }
                notFound = notFound || (path == null);
                boolean isInTimeRange = true;
                if (!notFound) {
                    CmsObject rootCms = OpenCms.initCmsObject(cms);
                    rootCms.getRequestContext().setSiteRoot("");
                    try {
                        CmsResource selectedResource = rootCms.readResource(path,
                                CmsResourceFilter.IGNORE_EXPIRATION);
                        long currentTime = System.currentTimeMillis();
                        isInTimeRange = selectedResource.isReleasedAndNotExpired(currentTime);
                        if (selectedResource.isFolder()) {
                            result = new CmsResultItemBean();
                            CmsJspNavElement folderNav = new CmsJspNavBuilder(rootCms).getNavigationForResource(
                                    selectedResource.getRootPath(), CmsResourceFilter.IGNORE_EXPIRATION);
                            CmsResource defaultFileResource = null;
                            if (folderNav.isInNavigation() && !folderNav.isNavigationLevel()) {
                                try {
                                    defaultFileResource = rootCms.readDefaultFile(selectedResource,
                                            CmsResourceFilter.ONLY_VISIBLE);
                                } catch (Exception e) {
                                    log(e.getMessage(), e);
                                }
                            }
                            CmsResource resourceForType = defaultFileResource != null ? defaultFileResource
                                    : selectedResource;
                            result.setType(
                                    OpenCms.getResourceManager().getResourceType(resourceForType).getTypeName());

                            String title = folderNav.getProperty(CmsPropertyDefinition.PROPERTY_NAVTEXT);
                            if (CmsStringUtil.isEmptyOrWhitespaceOnly(title)) {
                                title = folderNav.getTitle();
                            } else if (CmsStringUtil.isEmptyOrWhitespaceOnly(title)) {
                                title = CmsResource.getName(path);
                                if (title.contains("/")) {
                                    title = title.substring(0, title.indexOf("/"));
                                }
                            }
                            result.setTitle(title);
                            try {
                                String userName = cms.readUser(selectedResource.getUserLastModified())
                                        .getFullName();
                                result.setUserLastModified(userName);
                            } catch (CmsException e) {
                                log(e.getMessage(), e);
                            }
                            Date date = new Date(selectedResource.getDateLastModified());
                            String formattedDate = CmsDateUtil.getDateTime(date, DateFormat.MEDIUM,
                                    getWorkplaceLocale());
                            result.setDateLastModified(formattedDate);

                        } else {
                            CmsGallerySearchResult resultItem = null;
                            try {
                                resultItem = CmsGallerySearch.searchByPath(cms, path,
                                        CmsLocaleManager.getLocale(locale));
                            } catch (CmsVfsResourceNotFoundException ex) {
                                // ignore
                            }
                            notFound = resultItem == null;
                            if (!notFound) {
                                result = buildSingleSearchResultItem(getCmsObject(), resultItem, null);
                            }
                        }
                    } catch (CmsException ex) {
                        notFound = true;
                    }
                }
                if (notFound) {
                    result = new CmsResultItemBean();
                    result.setTitle(messageBundle.key(Messages.GUI_RESOURCE_NOT_FOUND_0));
                    result.setSubTitle("");
                    result.setType(CmsIconUtil.TYPE_RESOURCE_NOT_FOUND);
                } else if (!isInTimeRange && (result != null)) {
                    result.setType(CmsIconUtil.TYPE_RESOURCE_NOT_FOUND);
                    result.setTitle(
                            messageBundle.key(Messages.GUI_RESOURCE_OUT_OF_TIME_RANGE_1, result.getTitle()));
                }
            }
        } catch (Throwable t) {
            error(t);
        }
        return result;
    }

    /**
     * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#getInitialSettings(org.opencms.ade.galleries.shared.CmsGalleryConfiguration)
     */
    public CmsGalleryDataBean getInitialSettings(CmsGalleryConfiguration conf) throws CmsRpcException {

        try {
            return getInitialSettingsInternal(conf);
        } catch (Throwable t) {
            error(t);
            return null; // will never be reached
        }
    }

    /**
     * Returns the initial gallery data for the container page editor.<p>
     *
     * @param types the available resource types
     * @param uri the page URI
     * @param locale the content locale
     *
     * @return the gallery data
     */
    public CmsGalleryDataBean getInitialSettingsForContainerPage(List<CmsResourceTypeBean> types, String uri,
            String locale) {

        CmsGalleryDataBean data = null;
        try {
            data = new CmsGalleryDataBean();
            boolean galleryShowInvalidDefault = Boolean.parseBoolean(getWorkplaceSettings().getUserSettings()
                    .getAdditionalPreference(PREF_GALLERY_SHOW_INVALID_DEFAULT, true));
            data.setIncludeExpiredDefault(galleryShowInvalidDefault);
            data.setResultViewType(readResultViewType());
            data.setMode(GalleryMode.ade);
            data.setGalleryStoragePrefix("");
            data.setLocales(buildLocalesMap());
            data.setLocale(locale);

            data.setVfsRootFolders(getRootEntries());

            data.setScope(getWorkplaceSettings().getLastSearchScope());
            data.setSortOrder(getWorkplaceSettings().getLastGalleryResultOrder());

            data.setTabIds(GalleryMode.ade.getTabs());
            data.setReferenceSitePath(uri);
            data.setTypes(types);
            Map<String, CmsGalleryTypeInfo> adeGalleryTypeInfos = readGalleryInfosByTypeBeans(types);
            data.setGalleries(buildGalleriesList(adeGalleryTypeInfos));
            data.setStartTab(GalleryTabId.cms_tab_types);
            Set<String> folderFilter = readFolderFilters();
            data.setStartFolderFilter(folderFilter);
            if ((folderFilter != null) && !folderFilter.isEmpty()) {
                try {
                    data.setVfsPreloadData(generateVfsPreloadData(getCmsObject(), null, folderFilter));
                } catch (Exception e) {
                    LOG.error(e.getLocalizedMessage(), e);
                }
            }
            CmsSiteSelectorOptionBuilder optionBuilder = new CmsSiteSelectorOptionBuilder(getCmsObject());
            optionBuilder.addNormalSites(true, getWorkplaceSettings().getUserSettings().getStartFolder());
            optionBuilder.addSharedSite();
            data.setVfsSiteSelectorOptions(optionBuilder.getOptions());

            CmsSiteSelectorOptionBuilder sitemapOptionBuilder = new CmsSiteSelectorOptionBuilder(getCmsObject());
            sitemapOptionBuilder.addNormalSites(false, null);
            if (data.getReferenceSitePath() != null) {
                sitemapOptionBuilder.addCurrentSubsite(getCmsObject().addSiteRoot(data.getReferenceSitePath()));
            }
            data.setSitemapSiteSelectorOptions(sitemapOptionBuilder.getOptions());
            data.setDefaultScope(OpenCms.getWorkplaceManager().getGalleryDefaultScope());
            CmsCoreService service = new CmsCoreService();
            service.setCms(getCmsObject());
            data.setCategories(service.getCategoriesForSitePath(data.getReferenceSitePath()));
        } catch (Exception e) {
            LOG.error(e.getLocalizedMessage(), e);
        }
        return data;
    }

    /**
     * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#getSearch(org.opencms.ade.galleries.shared.CmsGalleryDataBean)
     */
    public CmsGallerySearchBean getSearch(CmsGalleryDataBean data) {

        CmsGallerySearchBean result = null;
        // search within all available types
        List<String> types = getTypeNames(data);
        switch (data.getMode()) {
        case editor:
        case view:
        case adeView:
        case widget:
            String currentelement = data.getCurrentElement();
            try {
                CmsSitemapEntryBean sitemapPreloadData = null;
                CmsVfsEntryBean vfsPreloadData = null;
                boolean disablePreview = false;
                GalleryTabId startTab = null;
                if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(currentelement)) {
                    log("looking up:" + currentelement);
                    // removing the servlet context if present
                    currentelement = CmsLinkManager.removeOpenCmsContext(currentelement);
                    // get search results given resource path
                    result = findResourceInGallery(currentelement, data);
                    if (result != null) {
                        sitemapPreloadData = result.getSitemapPreloadData();
                        vfsPreloadData = result.getVfsPreloadData();
                    }
                    if ((sitemapPreloadData != null)
                            && data.getTabConfiguration().getTabs().contains(GalleryTabId.cms_tab_sitemap)) {
                        startTab = GalleryTabId.cms_tab_sitemap;
                        disablePreview = true;
                    }
                } else {
                    CmsTreeOpenState sitemapState = getSitemapTreeState(data.getTreeToken());
                    if (sitemapState != null) {
                        A_CmsTreeTabDataPreloader<CmsSitemapEntryBean> sitemaploader = new A_CmsTreeTabDataPreloader<CmsSitemapEntryBean>() {

                            @Override
                            protected CmsSitemapEntryBean createEntry(CmsObject cms, CmsResource resource)
                                    throws CmsException {

                                return internalCreateSitemapEntryBean(cms, resource);
                            }

                            /**
                             * @see org.opencms.ade.galleries.A_CmsTreeTabDataPreloader#getChildren(org.opencms.file.CmsResource)
                             */
                            @Override
                            protected List<CmsResource> getChildren(CmsResource resource) throws CmsException {

                                return getSitemapSubEntryResources(resource.getRootPath());
                            }

                        };
                        // in the case
                        sitemapPreloadData = sitemaploader.preloadData(getCmsObject(), Sets.newHashSet(
                                readAll(sitemapState.getOpenItems(), CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)),
                                null);
                    }
                }
                if ((result == null) || (result.getResults() == null) || result.getResults().isEmpty()) {
                    result = new CmsGallerySearchBean();
                    result.setOriginalGalleryData(data);
                    result.setGalleryMode(data.getMode());
                    result.setGalleryStoragePrefix(data.getGalleryStoragePrefix());
                    result.setIgnoreSearchExclude(true);
                    String gallery = data.getStartGallery();
                    if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(gallery)) {
                        List<String> galleries = new ArrayList<String>();
                        galleries.add(gallery);
                        result.setGalleries(galleries);
                    }
                    if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(data.getStartFolder())) {
                        Set<String> folders = new HashSet<String>();
                        folders.add(data.getStartFolder());
                        result.setFolders(folders);
                    } else if (data.getStartFolderFilter() != null) {
                        result.setFolders(data.getStartFolderFilter());
                    }
                    result.setTypes(types);
                    result.setLocale(data.getLocale());
                    CmsGallerySearchScope scope = data.getScope();
                    if (scope == null) {
                        scope = OpenCms.getWorkplaceManager().getGalleryDefaultScope();
                    }
                    result.setSortOrder(data.getSortOrder().name());
                    result.setScope(scope);
                    result.setIncludeExpired(data.getIncludeExpiredDefault());
                    result = search(result);
                }
                result.setSitemapPreloadData(sitemapPreloadData);
                result.setVfsPreloadData(vfsPreloadData);
                result.setInitialTabId(startTab);
                result.setDisablePreview(disablePreview);
                if (types.size() > 1) {
                    // only remove types parameter if there is more than one type available
                    result.setTypes(null);
                }
            } catch (CmsException e) {
                logError(e);
                result = null;
            }
            break;
        case ade:
        default:
            break;
        }
        return result;
    }

    /**
     * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#getSearch(CmsGallerySearchBean)
     */
    public CmsGallerySearchBean getSearch(CmsGallerySearchBean searchObj) throws CmsRpcException {

        CmsGallerySearchBean gSearchObj = null;

        try {
            gSearchObj = search(searchObj);
            getWorkplaceSettings().setLastSearchScope(searchObj.getScope());
            getWorkplaceSettings().setLastGalleryResultOrder(SortParams.valueOf(searchObj.getSortOrder()));
            setLastOpenedGallery(searchObj);
        } catch (Throwable e) {
            error(e);
        }

        return gSearchObj;
    }

    /**
     * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#getSubEntries(java.lang.String, boolean, java.lang.String)
     */
    public List<CmsSitemapEntryBean> getSubEntries(String rootPath, boolean isRoot, String filter)
            throws CmsRpcException {

        try {
            return getSubEntriesInternal(rootPath, isRoot, filter);
        } catch (Throwable e) {
            error(e);
        }
        return null;
    }

    /**
     * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#getSubFolders(java.lang.String)
     */
    public List<CmsVfsEntryBean> getSubFolders(String rootPath) throws CmsRpcException {

        try {
            CmsObject cms = OpenCms.initCmsObject(getCmsObject());
            cms.getRequestContext().setSiteRoot("");
            List<CmsVfsEntryBean> result = new ArrayList<CmsVfsEntryBean>();
            if (cms.existsResource(rootPath, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) {
                CmsResource resource = cms.readResource(rootPath, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED);
                List<CmsResource> resources = cms.getSubFolders(resource.getRootPath(),
                        CmsResourceFilter.ONLY_VISIBLE_NO_DELETED);
                for (CmsResource res : resources) {
                    String title = cms.readPropertyObject(res, CmsPropertyDefinition.PROPERTY_TITLE, false)
                            .getValue();
                    result.add(internalCreateVfsEntryBean(getCmsObject(), res, title, false, isEditable(cms, res),
                            null, false));
                }
            }
            return result;
        } catch (Throwable e) {
            error(e);
        }
        return null;
    }

    /**
     * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#loadVfsEntryBean(java.lang.String, java.lang.String)
     */
    public CmsVfsEntryBean loadVfsEntryBean(String path, String filter) throws CmsRpcException {

        try {
            if (CmsStringUtil.isEmpty(filter)) {

                CmsObject cms = OpenCms.initCmsObject(getCmsObject());
                cms.getRequestContext().setSiteRoot("");
                if (!cms.existsResource(path, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) {
                    String startFolder = CmsStringUtil.joinPaths(path,
                            getWorkplaceSettings().getUserSettings().getStartFolder());
                    if (cms.existsResource(startFolder, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) {
                        path = startFolder;
                    }
                }
                CmsResource optionRes = cms.readResource(path);
                String title = cms.readPropertyObject(optionRes, CmsPropertyDefinition.PROPERTY_TITLE, false)
                        .getValue();
                if (CmsStringUtil.isEmpty(title)) {
                    title = path;
                }
                CmsVfsEntryBean entryBean = internalCreateVfsEntryBean(getCmsObject(), optionRes, title, true,
                        isEditable(cms, optionRes), null, false);
                return entryBean;
            } else {
                filter = filter.toLowerCase();
                CmsObject cms = OpenCms.initCmsObject(getCmsObject());
                cms.getRequestContext().setSiteRoot("");
                if (!cms.existsResource(path, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) {
                    String startFolder = CmsStringUtil.joinPaths(path,
                            getWorkplaceSettings().getUserSettings().getStartFolder());
                    if (cms.existsResource(startFolder, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) {
                        path = startFolder;
                    }
                }
                CmsResource optionRes = cms.readResource(path);
                List<CmsResource> folders = cms.readResources(optionRes.getRootPath(),
                        CmsResourceFilter.ONLY_VISIBLE_NO_DELETED.addRequireFolder());
                folders.add(optionRes);
                Set<CmsResource> folderSet = Sets.newHashSet(folders);
                List<CmsResource> titleResources = cms.readResourcesWithProperty(path,
                        CmsPropertyDefinition.PROPERTY_TITLE);
                titleResources.retainAll(folderSet);
                Set<CmsResource> filterMatches = Sets.newHashSet();
                for (CmsResource folder : folderSet) {
                    if (folder.getName().toLowerCase().contains(filter)) {
                        filterMatches.add(folder);
                        titleResources.remove(folder); // we don't need to check the title if the name already matched
                    }
                }
                for (CmsResource titleRes : titleResources) {
                    CmsProperty prop = cms.readPropertyObject(titleRes, CmsPropertyDefinition.PROPERTY_TITLE,
                            false);
                    String title = prop.getValue();
                    if ((title != null) && title.toLowerCase().contains(filter)) {
                        filterMatches.add(titleRes);
                    }
                }
                Set<String> filterMatchAncestorPaths = Sets.newHashSet();
                if (filterMatches.size() > 0) {
                    for (CmsResource filterMatch : filterMatches) {
                        String currentPath = filterMatch.getRootPath();
                        while (currentPath != null) {
                            filterMatchAncestorPaths.add(currentPath);
                            currentPath = CmsResource.getParentFolder(currentPath);
                        }
                    }
                    Set<String> allPaths = Sets.newHashSet();
                    Set<String> parentPaths = Sets.newHashSet();
                    for (CmsResource folder : folderSet) {
                        allPaths.add(folder.getRootPath());
                        String parent = CmsResource.getParentFolder(folder.getRootPath());
                        if (parent != null) {
                            parentPaths.add(parent);
                        }
                    }
                    parentPaths.retainAll(allPaths);

                    Set<CmsResource> filterMatchAncestors = Sets.newHashSet();
                    for (CmsResource folderRes : folderSet) {
                        if (filterMatchAncestorPaths.contains(folderRes.getRootPath())) {
                            filterMatchAncestors.add(folderRes);
                        }
                    }
                    Map<String, CmsResource> resourcesByPath = Maps.newHashMap();
                    for (CmsResource treeRes : filterMatchAncestors) {
                        resourcesByPath.put(treeRes.getRootPath(), treeRes);
                    }
                    Multimap<CmsResource, CmsResource> childMap = ArrayListMultimap.create();
                    for (CmsResource res : filterMatchAncestors) {
                        CmsResource parent = resourcesByPath.get(CmsResource.getParentFolder(res.getRootPath()));
                        if (parent != null) {
                            childMap.put(parent, res);
                        }
                    }
                    return buildVfsEntryBeanForQuickSearch(optionRes, childMap, filterMatches, parentPaths, true);
                } else {
                    return null;
                }
            }
        } catch (Throwable e) {
            error(e);
            return null;
        }
    }

    /**
     * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#saveResultViewType(java.lang.String)
     */
    public void saveResultViewType(String resultViewType) {

        CmsUser user = getCmsObject().getRequestContext().getCurrentUser();
        user.setAdditionalInfo(RESULT_VIEW_TYPE_ADD_INFO_KEY, resultViewType);
        try {
            getCmsObject().writeUser(user);
        } catch (CmsException e) {
            LOG.error(e.getLocalizedMessage(), e);
        }
    }

    /**
     * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#saveTreeOpenState(java.lang.String, java.lang.String, java.lang.String, java.util.Set)
     */
    public void saveTreeOpenState(String treeName, String treeToken, String siteRoot, Set<CmsUUID> openItems)
            throws CmsRpcException {

        try {
            HttpServletRequest request = getRequest();
            HttpSession session = request.getSession();
            String attributeName = getTreeOpenStateAttributeName(treeName, treeToken);
            if (openItems.isEmpty()) {
                CmsObject cms = OpenCms.initCmsObject(getCmsObject());
                cms.getRequestContext().setSiteRoot("");
                CmsResource resource = cms.readResource(siteRoot);
                openItems = Sets.newHashSet(resource.getStructureId());
            }
            CmsTreeOpenState treeState = new CmsTreeOpenState(treeName, siteRoot, openItems);
            session.setAttribute(attributeName, treeState);
        } catch (Throwable e) {
            error(e);
        }
    }

    /**
     * @see org.opencms.ade.galleries.shared.rpc.I_CmsGalleryService#updateIndex()
     */
    public void updateIndex() throws CmsRpcException {

        try {
            OpenCms.getSearchManager().updateOfflineIndexes();
        } catch (Throwable e) {
            error(e);
        }
    }

    /**
     * Gets an initialized CmsObject to be used for the actual search for a given search bean.<p>
     *
     * @param searchObj the search object
     * @return the initialized CmsObject
     *
     * @throws CmsException if something goes wrong
     */
    protected CmsObject getSearchCms(CmsGallerySearchBean searchObj) throws CmsException {

        CmsObject searchCms = getCmsObject();
        if (searchObj.isIncludeExpired()) {
            searchCms = OpenCms.initCmsObject(getCmsObject());
            searchCms.getRequestContext().setRequestTime(CmsResource.DATE_RELEASED_EXPIRED_IGNORE);
        }
        return searchCms;
    }

    /**
     * Gets the sitemap sub entries for a given path as resources.<p>
     *
     * @param rootPath the root path
     * @return the sitemap sub entry resources
     * @throws CmsException if something goes wrong
     */
    protected List<CmsResource> getSitemapSubEntryResources(String rootPath) throws CmsException {

        CmsObject rootCms = OpenCms.initCmsObject(getCmsObject());
        List<CmsResource> result = new ArrayList<CmsResource>();
        rootCms.getRequestContext().setSiteRoot("");
        CmsJspNavBuilder navBuilder = new CmsJspNavBuilder(rootCms);
        for (CmsJspNavElement navElement : navBuilder.getNavigationForFolder(rootPath, Visibility.all,
                CmsResourceFilter.ONLY_VISIBLE)) {
            if ((navElement != null) && navElement.isInNavigation()) {
                result.add(navElement.getResource());
            }
        }
        return result;
    }

    /**
     * Internal method for getting sitemap sub entries for a given root path.<p>
     *
     * @param rootPath the root path
     * @param isRoot true if this method is used to get the root entries of a sitemap
     * @param filter the filter string (only relevant if isRoot is true)
     * @return the list of sitemap sub-entry beans
     *
     * @throws CmsException if something goes wrong
     */
    protected List<CmsSitemapEntryBean> getSubEntriesInternal(String rootPath, boolean isRoot, String filter)
            throws CmsException {

        CmsObject rootCms = OpenCms.initCmsObject(getCmsObject());
        rootCms.getRequestContext().setSiteRoot("");
        CmsJspNavBuilder navBuilder = new CmsJspNavBuilder(rootCms);
        if (isRoot) {
            if (CmsStringUtil.isEmpty(filter)) {
                List<CmsSitemapEntryBean> result = new ArrayList<CmsSitemapEntryBean>();
                for (CmsJspNavElement navElement : navBuilder.getNavigationForFolder(rootPath, Visibility.all,
                        CmsResourceFilter.ONLY_VISIBLE)) {
                    if ((navElement != null) && navElement.isInNavigation()) {
                        CmsSitemapEntryBean nextEntry = prepareSitemapEntry(rootCms, navElement, false, true);
                        result.add(nextEntry);
                    }
                }
                CmsJspNavElement navElement = navBuilder.getNavigationForResource(rootPath,
                        CmsResourceFilter.ONLY_VISIBLE);
                if (navElement == null) {
                    return result;
                }
                CmsSitemapEntryBean root = prepareSitemapEntry(rootCms, navElement, isRoot, true);
                root.setChildren(result);
                return Collections.singletonList(root);
            } else {
                CmsGalleryFilteredNavTreeBuilder navTreeBuilder = new CmsGalleryFilteredNavTreeBuilder(rootCms,
                        rootPath);
                navTreeBuilder.initTree(filter);
                if (navTreeBuilder.hasMatches()) {
                    return Lists.newArrayList(convertNavigationTreeToBean(rootCms, navTreeBuilder.getRoot(), true));
                } else {
                    return Lists.newArrayList();
                }
            }
        } else {
            List<CmsSitemapEntryBean> result = new ArrayList<CmsSitemapEntryBean>();
            for (CmsJspNavElement navElement : navBuilder.getNavigationForFolder(rootPath, Visibility.all,
                    CmsResourceFilter.ONLY_VISIBLE)) {
                if ((navElement != null) && navElement.isInNavigation()) {
                    CmsSitemapEntryBean nextEntry = prepareSitemapEntry(rootCms, navElement, false, true);
                    result.add(nextEntry);
                }
            }
            return result;
        }
    }

    /**
     * Gets the type names from the gallery data bean.<p>
     *
     * @param data the gallery data bean
     * @return the type names
     */
    protected List<String> getTypeNames(CmsGalleryDataBean data) {

        List<String> types = new ArrayList<String>();
        for (CmsResourceTypeBean info : data.getTypes()) {
            types.add(info.getType());
        }
        return types;
    }

    /**
     * Checks whether a given resource is a sitemap entry.<p>
     *
     * This is used for preselected entries in the gallery widget.<p>
     *
     *
     * @param cms the current CMS context
     * @param resource the resource to check
     * @return true if the resource is a sitemap entry
     *
     * @throws CmsException if something goes wrong
     */
    protected boolean isSitemapEntry(CmsObject cms, CmsResource resource) throws CmsException {

        CmsResourceFilter filter = CmsResourceFilter.ONLY_VISIBLE_NO_DELETED;
        List<CmsResource> ancestors = new ArrayList<CmsResource>();
        CmsResource currentResource = resource;
        String siteRoot = OpenCms.getSiteManager().getSiteRoot(resource.getRootPath());
        if (CmsStringUtil.isEmpty(siteRoot)) {
            return false;
        }
        while (true) {
            CmsResource parent = cms.readParentFolder(currentResource.getStructureId());
            if ((parent == null) || !cms.existsResource(parent.getStructureId(), filter)) {
                break;
            }
            ancestors.add(parent);
            if (CmsStringUtil.comparePaths(siteRoot, parent.getRootPath())) {
                break;
            }
            currentResource = parent;
        }
        Collections.reverse(ancestors);
        boolean first = true;
        for (CmsResource ancestor : ancestors) {
            if (first) {
                if (null == OpenCms.getSiteManager().getSiteRoot(ancestor.getRootPath())) {
                    return false;
                }
            } else {
                if (!hasNavigationProperty(cms, ancestor)) {
                    return false;
                }
            }
            first = false;
        }
        if (resource.isFile()) {
            if (ancestors.isEmpty()) {
                return false;
            }
            CmsResource defaultFile = cms.readDefaultFile(ancestors.get(ancestors.size() - 1), filter);
            if (!resource.equals(defaultFile)) {
                return false;
            }
        } else {
            if (!hasNavigationProperty(cms, resource)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Reads the resources for a collection of structure ids and returns the list of resources which could be read.<p>
     *
     * @param structureIds the structure ids for which we want to read the resources
     * @param filter the filter used to read the resource
     *
     * @return the list of resources for the given structure id
     */
    protected List<CmsResource> readAll(Collection<CmsUUID> structureIds, CmsResourceFilter filter) {

        List<CmsResource> result = new ArrayList<CmsResource>();
        for (CmsUUID id : structureIds) {
            try {
                result.add(getCmsObject().readResource(id, filter));
            } catch (CmsException e) {
                LOG.info(e.getLocalizedMessage(), e);
            }
        }
        return result;
    }

    /**
     * Gets the sitemap tree open state.<p>
     *
     * @param treeToken the tree token to use
     *
     * @return the sitemap tree open state
     */
    CmsTreeOpenState getSitemapTreeState(String treeToken) {

        return (CmsTreeOpenState) (getRequest().getSession().getAttribute(
                getTreeOpenStateAttributeName(I_CmsGalleryProviderConstants.TREE_SITEMAP, treeToken)));
    }

    /**
     * Gets the VFS tree open state.<p>
     *
     * @param treeToken the tree token
     *
     * @return the VFS tree open state
     */
    CmsTreeOpenState getVfsTreeState(String treeToken) {

        return (CmsTreeOpenState) (getRequest().getSession()
                .getAttribute(getTreeOpenStateAttributeName(I_CmsGalleryProviderConstants.TREE_VFS, treeToken)));
    }

    /**
     * Creates the sitemap entry bean for a resource.<p>
     *
     * @param cms the current CMS context
     * @param resource the resource for which the sitemap entry bean should be created
     *
     * @return the created sitemap entry bean
     *
     * @throws CmsException if something goes wrong
     */
    CmsSitemapEntryBean internalCreateSitemapEntryBean(CmsObject cms, CmsResource resource) throws CmsException {

        cms = OpenCms.initCmsObject(cms);
        cms.getRequestContext().setSiteRoot("");
        CmsJspNavBuilder navBuilder = new CmsJspNavBuilder(cms);
        CmsJspNavElement entry = navBuilder.getNavigationForResource(resource.getRootPath());
        if (entry == null) {
            // may be null for expired resources
            return null;
        }
        return prepareSitemapEntry(cms, entry, false, true);
    }

    /**
     * Checks if the current user has write permissions on the given resource.<p>
     *
     * @param cms the current cms context
     * @param resource the resource to check
     *
     * @return <code>true</code> if the current user has write permissions on the given resource
     */
    boolean isEditable(CmsObject cms, CmsResource resource) {

        try {
            return cms.hasPermissions(resource, CmsPermissionSet.ACCESS_WRITE, false, CmsResourceFilter.ALL);
        } catch (CmsException e) {
            return false;
        }
    }

    /**
     * Adds galleries for a given type.<p>
     *
     * @param galleryTypeInfos the gallery type infos
     * @param typeName the type name
     *
     * @throws CmsLoaderException if something goes wrong
     */
    @SuppressWarnings("deprecation")
    private void addGalleriesForType(Map<String, CmsGalleryTypeInfo> galleryTypeInfos, String typeName)
            throws CmsLoaderException {

        I_CmsResourceType contentType = getResourceManager().getResourceType(typeName);
        for (I_CmsResourceType galleryType : contentType.getGalleryTypes()) {

            if (galleryTypeInfos.containsKey(galleryType.getTypeName())) {
                CmsGalleryTypeInfo typeInfo = galleryTypeInfos.get(galleryType.getTypeName());
                typeInfo.addContentType(contentType);
            } else {
                CmsGalleryTypeInfo typeInfo;

                typeInfo = new CmsGalleryTypeInfo(galleryType, contentType,
                        getGalleriesByType(galleryType.getTypeId()));

                galleryTypeInfos.put(galleryType.getTypeName(), typeInfo);
            }

        }
    }

    /**
     * Returns the map with the available galleries.<p>
     *
     * The map uses gallery path as the key and stores the CmsGalleriesListInfoBean as the value.<p>
     *
     * @param galleryTypes the galleries
     *
     * @return the map with gallery info beans
     */
    private List<CmsGalleryFolderBean> buildGalleriesList(Map<String, CmsGalleryTypeInfo> galleryTypes) {

        List<CmsGalleryFolderBean> list = new ArrayList<CmsGalleryFolderBean>();
        if (galleryTypes == null) {
            return list;
        }
        Iterator<Entry<String, CmsGalleryTypeInfo>> iGalleryTypes = galleryTypes.entrySet().iterator();
        while (iGalleryTypes.hasNext()) {
            Entry<String, CmsGalleryTypeInfo> ent = iGalleryTypes.next();
            CmsGalleryTypeInfo tInfo = ent.getValue();
            ArrayList<String> contentTypes = new ArrayList<String>();
            Iterator<I_CmsResourceType> it = tInfo.getContentTypes().iterator();
            while (it.hasNext()) {
                contentTypes.add(String.valueOf(it.next().getTypeName()));
            }
            Iterator<CmsResource> ir = tInfo.getGalleries().iterator();
            while (ir.hasNext()) {
                CmsResource res = ir.next();
                CmsGalleryFolderBean bean = new CmsGalleryFolderBean();
                String sitePath = getCmsObject().getSitePath(res);
                String title = "";
                try {
                    // read the gallery title
                    title = getCmsObject().readPropertyObject(sitePath, CmsPropertyDefinition.PROPERTY_TITLE, false)
                            .getValue("");
                } catch (CmsException e) {
                    // error reading title property
                    logError(e);
                }
                // sitepath as gallery id
                bean.setPath(sitePath);
                // content types
                bean.setContentTypes(contentTypes);
                // title
                bean.setTitle(title);
                // gallery type name
                bean.setType(tInfo.getResourceType().getTypeName());
                bean.setEditable(isEditable(getCmsObject(), res));
                list.add(bean);
            }
        }
        return list;
    }

    /**
     * Returns a map with the available locales.<p>
     *
     * The map entry key is the current locale and the value the localized nice name.<p>
     *
     * @return the map representation of all available locales
     */
    private Map<String, String> buildLocalesMap() {

        TreeMap<String, String> localesMap = new TreeMap<String, String>();
        Iterator<Locale> it = OpenCms.getLocaleManager().getAvailableLocales().iterator();
        while (it.hasNext()) {
            Locale locale = it.next();
            localesMap.put(locale.toString(), locale.getDisplayName(getWorkplaceLocale()));
        }
        return localesMap;
    }

    /**
     * Returns the list of beans for the given search results.<p>
     *
     * @param searchResult the list of search results
     * @param presetResult the search result which corresponds to a preset value in the editor
     *
     * @return the list with the current search results
     */
    private List<CmsResultItemBean> buildSearchResultList(List<CmsGallerySearchResult> searchResult,
            CmsGallerySearchResult presetResult) {

        ArrayList<CmsResultItemBean> list = new ArrayList<CmsResultItemBean>();
        if ((searchResult == null) || (searchResult.size() == 0)) {
            return list;
        }
        CmsObject cms = getCmsObject();
        for (CmsGallerySearchResult sResult : searchResult) {
            try {
                CmsResultItemBean bean = buildSingleSearchResultItem(cms, sResult, presetResult);
                list.add(bean);
            } catch (Exception e) {
                logError(e);
            }
        }
        return list;
    }

    /**
     * Builds a single search result list item for the client from a server-side search result.<p>
     *
     * @param cms the current CMS context
     * @param sResult the server-side search result
     * @param presetResult the preselected result
     *
     * @return the client side search result item
     *
     * @throws CmsException if something goes wrong
     * @throws ParseException if date parsing fails
     */
    private CmsResultItemBean buildSingleSearchResultItem(CmsObject cms, CmsGallerySearchResult sResult,
            CmsGallerySearchResult presetResult) throws CmsException, ParseException {

        Locale wpLocale = getWorkplaceLocale();
        CmsResultItemBean bean = new CmsResultItemBean();
        if (sResult == presetResult) {
            bean.setPreset(true);
        }
        bean.setReleasedAndNotExpired(sResult.isReleaseAndNotExpired(cms));
        String path = sResult.getPath();
        path = cms.getRequestContext().removeSiteRoot(path);

        // resource path as id
        bean.setPath(path);

        // title
        String rawTitle = CmsStringUtil.isEmptyOrWhitespaceOnly(sResult.getTitle())
                ? CmsResource.getName(sResult.getPath())
                : sResult.getTitle();
        bean.setTitle(rawTitle);
        bean.setRawTitle(rawTitle);
        // resource type
        bean.setType(sResult.getResourceType());
        CmsResource resultResource = cms.readResource(new CmsUUID(sResult.getStructureId()),
                CmsResourceFilter.ONLY_VISIBLE_NO_DELETED);
        bean.setDetailResourceType(CmsResourceIcon.getDefaultFileOrDetailType(cms, resultResource));
        // structured id
        bean.setClientId(sResult.getStructureId());

        CmsVfsService.addLockInfo(cms, resultResource, bean);

        String permalinkId = sResult.getStructureId().toString();
        String permalink = CmsStringUtil.joinPaths(OpenCms.getSystemInfo().getOpenCmsContext(),
                CmsPermalinkResourceHandler.PERMALINK_HANDLER, permalinkId);

        bean.setViewLink(permalink);
        // set nice resource type name as subtitle
        I_CmsResourceType type = OpenCms.getResourceManager().getResourceType(sResult.getResourceType());
        String resourceTypeDisplayName = CmsWorkplaceMessages.getResourceTypeName(wpLocale, type.getTypeName());
        String description = sResult.getDescription();
        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(description)) {
            bean.setDescription(description);
            bean.addAdditionalInfo(
                    Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_RESULT_LABEL_DESCRIPTION_0),
                    description);
        } else {
            bean.setDescription(resourceTypeDisplayName);
        }
        bean.setUserLastModified(sResult.getUserLastModified());
        Date lastModDate = sResult.getDateLastModified();
        String formattedDate = lastModDate != null
                ? CmsDateUtil.getDateTime(lastModDate, DateFormat.MEDIUM, wpLocale)
                : "";
        bean.setDateLastModified(formattedDate);
        if (!type.getTypeName().equals(CmsResourceTypeImage.getStaticTypeName())) {
            bean.addAdditionalInfo(
                    Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_RESULT_LABEL_RESOURCE_TYPE_0),
                    resourceTypeDisplayName);
        }
        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(sResult.getExcerpt())) {
            bean.addAdditionalInfo(
                    Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_RESULT_LABEL_EXCERPT_0),
                    sResult.getExcerpt(), CmsListInfoBean.CSS_CLASS_MULTI_LINE);
        }
        if (type instanceof CmsResourceTypeImage) {
            CmsProperty copyrightProp = cms.readPropertyObject(resultResource,
                    CmsPropertyDefinition.PROPERTY_COPYRIGHT, false);
            if (!copyrightProp.isNullProperty()) {
                bean.addAdditionalInfo(
                        Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_RESULT_LABEL_COPYRIGHT_0),
                        copyrightProp.getValue());
            }
            CmsProperty imageDimensionProp = cms.readPropertyObject(resultResource,
                    CmsPropertyDefinition.PROPERTY_IMAGE_SIZE, false);
            if (!imageDimensionProp.isNullProperty()) {
                String dimensions = imageDimensionProp.getValue();
                dimensions = dimensions.substring(2).replace(",h:", " x ");
                bean.setDimension(dimensions);
                bean.addAdditionalInfo(
                        Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_RESULT_LABEL_DIMENSION_0),
                        dimensions);
            }
        }

        if (type instanceof CmsResourceTypeXmlContent) {
            CmsProperty elementModelProperty = cms.readPropertyObject(resultResource,
                    CmsPropertyDefinition.PROPERTY_ELEMENT_MODEL, true);
            if (!elementModelProperty.isNullProperty()) {
                if (Boolean.valueOf(elementModelProperty.getValue()).booleanValue()) {
                    bean.setIsCopyModel(true);
                }
            }
        }

        if (CmsResourceTypeXmlContainerPage.isModelReuseGroup(cms, resultResource)) {
            bean.setPseudoType(CmsGwtConstants.TYPE_MODELGROUP_REUSE);
        }

        bean.setResourceState(resultResource.getState());
        bean.addAdditionalInfo(Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_RESULT_LABEL_SIZE_0),
                (sResult.getLength() / 1000) + " kb");
        if (lastModDate != null) {
            bean.addAdditionalInfo(
                    Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_RESULT_LABEL_DATE_CHANGED_0),
                    CmsDateUtil.getDate(lastModDate, DateFormat.SHORT, getWorkplaceLocale()));
        }
        if ((sResult.getDateExpired().getTime() != CmsResource.DATE_EXPIRED_DEFAULT)
                && !sResult.getDateExpired().equals(CmsSearchFieldMapping.getDefaultDateExpired())) {
            bean.addAdditionalInfo(
                    Messages.get().getBundle(getWorkplaceLocale()).key(Messages.GUI_RESULT_LABEL_DATE_EXPIRED_0),
                    CmsDateUtil.getDate(sResult.getDateExpired(), DateFormat.SHORT, getWorkplaceLocale()));
        }

        bean.setNoEditReson(new CmsResourceUtil(cms, resultResource)
                .getNoEditReason(OpenCms.getWorkplaceManager().getWorkplaceLocale(cms)));
        bean.setMarkChangedState(true);
        return bean;
    }

    /**
     * Generates a map with all available content types.<p>
     *
     * The map uses resource type name as the key and stores the CmsTypesListInfoBean as the value.
     *
     * @param types the resource types
     * @param creatableTypes the creatable types
     *
     * @return the map containing the available resource types
     */
    private List<CmsResourceTypeBean> buildTypesList(List<I_CmsResourceType> types, Set<String> creatableTypes) {

        ArrayList<CmsResourceTypeBean> list = new ArrayList<CmsResourceTypeBean>();
        if (types == null) {
            return list;
        }
        Map<I_CmsResourceType, I_CmsPreviewProvider> typeProviderMapping = getPreviewProviderForTypes(types);
        Iterator<I_CmsResourceType> it = types.iterator();
        while (it.hasNext()) {

            I_CmsResourceType type = it.next();
            try {
                CmsResourceTypeBean bean = createTypeBean(type, typeProviderMapping.get(type),
                        creatableTypes.contains(type.getTypeName()));
                list.add(bean);
            } catch (Exception e) {
                if (type != null) {
                    log(Messages.get().getBundle(getWorkplaceLocale()).key(Messages.ERR_BUILD_TYPE_LIST_1,
                            type.getTypeName()), e);
                }
            }
        }
        return list;
    }

    /**
     * Recursively builds the VFS entry bean for the quick filtering function in the folder tab.<p<
     *
     * @param resource the resource
     * @param childMap map from parent to child resources
     * @param filterMatches the resources matching the filter
     * @param parentPaths root paths of resources which are not leaves
     * @param isRoot true if this the root node
     *
     * @return the VFS entry bean for the client
     *
     * @throws CmsException if something goes wrong
     */
    private CmsVfsEntryBean buildVfsEntryBeanForQuickSearch(CmsResource resource,
            Multimap<CmsResource, CmsResource> childMap, Set<CmsResource> filterMatches, Set<String> parentPaths,
            boolean isRoot) throws CmsException {

        CmsObject cms = getCmsObject();
        String title = cms.readPropertyObject(resource, CmsPropertyDefinition.PROPERTY_TITLE, false).getValue();
        boolean isMatch = filterMatches.contains(resource);
        List<CmsVfsEntryBean> childBeans = Lists.newArrayList();

        Collection<CmsResource> children = childMap.get(resource);
        if (!children.isEmpty()) {
            for (CmsResource child : children) {
                CmsVfsEntryBean childBean = buildVfsEntryBeanForQuickSearch(child, childMap, filterMatches,
                        parentPaths, false);
                childBeans.add(childBean);
            }
        } else if (filterMatches.contains(resource)) {
            if (parentPaths.contains(resource.getRootPath())) {
                childBeans = null;
            }
            // otherwise childBeans remains an empty list
        }

        String rootPath = resource.getRootPath();
        CmsVfsEntryBean result = new CmsVfsEntryBean(rootPath, resource.getStructureId(), title, isRoot,
                isEditable(cms, resource), childBeans, isMatch);
        String siteRoot = null;
        if (OpenCms.getSiteManager().startsWithShared(rootPath)) {
            siteRoot = OpenCms.getSiteManager().getSharedFolder();
        } else {
            String tempSiteRoot = OpenCms.getSiteManager().getSiteRoot(rootPath);
            if (tempSiteRoot != null) {
                siteRoot = tempSiteRoot;
            } else {
                siteRoot = "";
            }
        }
        result.setSiteRoot(siteRoot);
        return result;
    }

    /**
     * Helper method to construct a sitemap entry bean for the sitemap tab filter functionality.<p>
     *
     * @param cms the CMS context
     * @param node the root node of the filtered tree
     * @param isRoot true if this is the root node
     *
     * @return the sitemap entry bean
     */
    private CmsSitemapEntryBean convertNavigationTreeToBean(CmsObject cms, NavigationNode node, boolean isRoot) {

        CmsSitemapEntryBean bean = null;
        try {
            bean = prepareSitemapEntry(cms, node.getNavElement(), isRoot, false);
            bean.setSearchMatch(node.isMatch());
            List<NavigationNode> children = node.getChildren();
            List<CmsSitemapEntryBean> childBeans = Lists.newArrayList();
            if (children.size() > 0) {
                for (NavigationNode child : children) {
                    childBeans.add(convertNavigationTreeToBean(cms, child, false));
                }
            } else if (node.isLeaf()) {
                childBeans = Lists.newArrayList();
            } else {
                // no children in filter result, but can still load children by clicking on tree item
                childBeans = null;
            }
            bean.setChildren(childBeans);

        } catch (CmsException e) {
            LOG.error(e.getLocalizedMessage(), e);
        }
        return bean;
    }

    /**
     * Returns a list of resource types by a request parameter.<p>
     *
     * @param resourceTypes the resource types parameter
     *
     * @return the resource types
     */
    private List<I_CmsResourceType> convertTypeNamesToTypes(List<String> resourceTypes) {

        List<I_CmsResourceType> result = new ArrayList<I_CmsResourceType>();
        if (resourceTypes != null) {
            for (String type : resourceTypes) {
                try {
                    result.add(getResourceManager().getResourceType(type.trim()));
                } catch (Exception e) {
                    logError(e);
                }
            }
        }

        return result;
    }

    /**
     * Creates a resource type bean for the given type.<p>
     *
     * @param type the resource type
     * @param preview the preview provider
     * @param creatable if the type may be created by the current user
     *
     * @return the resource type bean
     */
    @SuppressWarnings("deprecation")
    private CmsResourceTypeBean createTypeBean(I_CmsResourceType type, I_CmsPreviewProvider preview,
            boolean creatable) {

        CmsResourceTypeBean result = new CmsResourceTypeBean();

        result.setType(type.getTypeName());
        result.setTypeId(type.getTypeId());
        Locale wpLocale = getWorkplaceLocale();
        // type title and subtitle
        result.setTitle(CmsWorkplaceMessages.getResourceTypeName(wpLocale, type.getTypeName()));
        result.setDescription(CmsWorkplaceMessages.getResourceTypeDescription(wpLocale, type.getTypeName()));
        // gallery id of corresponding galleries
        ArrayList<String> galleryNames = new ArrayList<String>();
        Iterator<I_CmsResourceType> galleryTypes = type.getGalleryTypes().iterator();
        while (galleryTypes.hasNext()) {
            I_CmsResourceType galleryType = galleryTypes.next();
            galleryNames.add(galleryType.getTypeName());
        }
        result.setGalleryTypeNames(galleryNames);
        if (preview != null) {
            result.setPreviewProviderName(preview.getPreviewName());
        }
        if (type.isFolder()) {
            result.setVisibility(TypeVisibility.hidden);
        }
        result.setCreatableType(creatable);
        return result;
    }

    /**
     * Returns the search object containing the list with search results and the path to the specified resource.<p>
     *
     * @param resourceName the given resource
     * @param data the gallery data bean
     *
     * @return the gallery search object containing the current search parameter and the search result list
     *
     * @throws CmsException if the search fails
     */
    private CmsGallerySearchBean findResourceInGallery(String resourceName, CmsGalleryDataBean data)
            throws CmsException {

        CmsResource resource = null;
        int pos = resourceName.indexOf("?");
        String resName = resourceName;
        String query = "";
        if (pos > -1) {
            query = resourceName.substring(pos);
            resName = resourceName.substring(0, pos);
        }
        String resNameWithoutServer = OpenCms.getLinkManager().getRootPath(getCmsObject(), resName);
        if (resNameWithoutServer != null) {
            resName = resNameWithoutServer;
        }
        CmsObject cms = getCmsObject();
        try {
            log("reading resource: " + resName);
            resource = cms.readResource(resName, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED);
        } catch (CmsException e) {
            String originalSiteRoot = cms.getRequestContext().getSiteRoot();
            try {
                cms.getRequestContext().setSiteRoot("");
                resource = cms.readResource(resName, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED);
            } catch (CmsException e2) {
                logError(e);
                return null;
            } finally {
                cms.getRequestContext().setSiteRoot(originalSiteRoot);
            }
        }
        boolean typeOk = true;
        if ((data.getTypes() != null) && !data.getTypes().isEmpty()) {
            typeOk = false;
            for (CmsResourceTypeBean type : data.getTypes()) {
                if (OpenCms.getResourceManager().matchResourceType(type.getType(), resource.getTypeId())) {
                    typeOk = true;
                }
            }
        }
        if (!typeOk) {
            LOG.debug("Selected resource " + resource.getRootPath()
                    + " has invalid type for configured gallery widget.");
            return null;
        }
        ArrayList<String> types = new ArrayList<String>();
        String resType = OpenCms.getResourceManager().getResourceType(resource).getTypeName();
        types.add(resType);
        Set<String> folders = null;
        if (data.getStartFolderFilter() != null) {
            for (String folder : data.getStartFolderFilter()) {
                if (resource.getRootPath().startsWith(folder)) {
                    folders = data.getStartFolderFilter();
                    break;
                }
            }
        }
        CmsGallerySearchBean initialSearchObj = new CmsGallerySearchBean();
        initialSearchObj.setGalleryMode(data.getMode());
        initialSearchObj.setGalleryStoragePrefix(data.getGalleryStoragePrefix());
        initialSearchObj.setIncludeExpired(data.getIncludeExpiredDefault());
        initialSearchObj.setIgnoreSearchExclude(true);
        initialSearchObj.setTypes(types);
        if (folders != null) {
            initialSearchObj.setFolders(folders);
        }
        ArrayList<String> galleries = new ArrayList<String>();
        for (CmsGalleryFolderBean gallery : data.getGalleries()) {
            String galleryPath = gallery.getPath();
            String galleryRootPath = cms.addSiteRoot(galleryPath);
            String folderPath = CmsResource.getFolderPath(resName);
            if (galleryPath.equals(folderPath) || galleryRootPath.equals(folderPath)) {
                galleries.add(gallery.getPath());
                initialSearchObj.setGalleries(galleries);
                break;
            }
        }
        if (galleries.isEmpty()) {
            ArrayList<String> vfsFolders = new ArrayList<String>();
            vfsFolders.add(CmsResource.getFolderPath(resource.getRootPath()));
            initialSearchObj.setFolders(new HashSet<String>(vfsFolders));
        }
        initialSearchObj.setLocale(data.getLocale());
        CmsGallerySearchBean searchObj = new CmsGallerySearchBean(initialSearchObj);
        searchObj.setSortOrder(CmsGallerySearchParameters.CmsGallerySortParam.DEFAULT.toString());
        int currentPage = 1;
        boolean found = false;
        searchObj.setPage(currentPage);
        CmsGallerySearchParameters params = prepareSearchParams(searchObj);
        CmsObject searchCms = getSearchCms(searchObj);
        org.opencms.search.galleries.CmsGallerySearch searchBean = new org.opencms.search.galleries.CmsGallerySearch();
        searchBean.init(searchCms);
        searchBean.setIndex(CmsSolrIndex.DEFAULT_INDEX_NAME_OFFLINE);
        CmsGallerySearchResultList searchResults = null;
        CmsGallerySearchResultList totalResults = new CmsGallerySearchResultList();
        CmsGallerySearchResult foundItem = null;
        while (!found) {
            params.setResultPage(currentPage);
            searchResults = searchBean.getResult(params);
            totalResults.append(searchResults);
            Iterator<CmsGallerySearchResult> resultsIt = searchResults.listIterator();
            while (resultsIt.hasNext()) {
                CmsGallerySearchResult searchResult = resultsIt.next();
                if (searchResult.getPath().equals(resource.getRootPath())) {
                    found = true;
                    foundItem = searchResult;
                    break;
                }
            }
            if (!found && ((searchResults.getHitCount() / (currentPage * params.getMatchesPerPage())) >= 1)) {
                currentPage++;
            } else {
                break;
            }
            if (searchResults.getHitCount() > INITIAL_SEARCH_MAX_RESULTS) {
                // in case the hit count is too large, don't continue the search to avoid slow load times
                break;
            }
        }
        boolean hasResults = searchResults != null;
        searchResults = totalResults;
        if (hasResults) {
            initialSearchObj.setSortOrder(params.getSortOrder().name());
            initialSearchObj.setResultCount(searchResults.getHitCount());
            initialSearchObj.setPage(params.getResultPage());
            initialSearchObj.setResults(buildSearchResultList(searchResults, foundItem));
            initialSearchObj.setPage(1);
            initialSearchObj.setLastPage(currentPage);
            initialSearchObj.setTabId(I_CmsGalleryProviderConstants.GalleryTabId.cms_tab_results.name());
            initialSearchObj.setResourcePath(resName + query);
            initialSearchObj.setResourceType(resType);
            updateNoUploadReason(searchCms, searchObj);
        } else {
            log("could not find selected resource");
        }
        if ((resource != null)) {
            if (isSitemapEntry(cms, resource)) {
                A_CmsTreeTabDataPreloader<CmsSitemapEntryBean> loader = new A_CmsTreeTabDataPreloader<CmsSitemapEntryBean>() {

                    @Override
                    protected CmsSitemapEntryBean createEntry(CmsObject innerCms, CmsResource innerResource)
                            throws CmsException {

                        return internalCreateSitemapEntryBean(innerCms, innerResource);
                    }

                    /**
                     * @see org.opencms.ade.galleries.A_CmsTreeTabDataPreloader#getChildren(org.opencms.file.CmsResource)
                     */
                    @Override
                    protected List<CmsResource> getChildren(CmsResource parent) throws CmsException {

                        return getSitemapSubEntryResources(parent.getRootPath());
                    }
                };
                CmsSitemapEntryBean entryBean = loader.preloadData(cms,
                        Sets.newHashSet(Collections.singletonList(resource)), null);
                initialSearchObj.setSitemapPreloadData(entryBean);
            } else if (resource.isFolder()) {
                A_CmsTreeTabDataPreloader<CmsVfsEntryBean> loader = new A_CmsTreeTabDataPreloader<CmsVfsEntryBean>() {

                    @Override
                    protected CmsVfsEntryBean createEntry(CmsObject innerCms, CmsResource innerResource)
                            throws CmsException {

                        String title = innerCms
                                .readPropertyObject(innerResource, CmsPropertyDefinition.PROPERTY_TITLE, false)
                                .getValue();
                        return internalCreateVfsEntryBean(getCmsObject(), innerResource, title, true,
                                isEditable(innerCms, innerResource), null, false);
                    }
                };
                CmsVfsEntryBean entryBean = loader.preloadData(cms,
                        Sets.newHashSet(Collections.singletonList(resource)), null);
                initialSearchObj.setVfsPreloadData(entryBean);
            }
        }

        return initialSearchObj;
    }

    /**
     * Get default types for gallery together with visibility.<p>
     *
     * @return the default types
     */
    private List<I_CmsResourceType> getDefaultTypesForGallery() {

        return OpenCms.getResourceManager().getResourceTypes();
    }

    /**
     * Generates a list of available galleries for the given gallery-type.<p>
     *
     * @param galleryTypeId the gallery-type
     *
     * @return the list of galleries
     *
     */
    @SuppressWarnings("deprecation")
    private List<CmsResource> getGalleriesByType(int galleryTypeId) {

        List<CmsResource> galleries = new ArrayList<CmsResource>();

        // We swallow errors in this method because we don't  want a failure to read some folders (e.g. because of permission problems) to
        // cause an empty gallery list as a result

        try {
            galleries.addAll(getCmsObject().readResources("/",
                    CmsResourceFilter.ONLY_VISIBLE_NO_DELETED.addRequireType(galleryTypeId)));
        } catch (Exception e) {
            LOG.error("Could not read site galleries: " + e.getLocalizedMessage(), e);
        }

        String siteRoot = getCmsObject().getRequestContext().getSiteRoot();
        // if the current site is NOT the root site - add all other galleries from the system path

        try {
            if (!siteRoot.equals("")) {
                List<CmsResource> systemGalleries = null;
                // get the galleries in the /system/ folder
                systemGalleries = getCmsObject().readResources(CmsWorkplace.VFS_PATH_SYSTEM,
                        CmsResourceFilter.ONLY_VISIBLE_NO_DELETED.addRequireType(galleryTypeId));
                if (systemGalleries != null) {
                    // add the found system galleries to the result
                    galleries.addAll(systemGalleries);
                }
            }
        } catch (Exception e) {
            LOG.info("Could not read system galleries: " + e.getLocalizedMessage(), e);
        }

        try {
            if (!OpenCms.getSiteManager().isSharedFolder(siteRoot)) {
                String shared = OpenCms.getSiteManager().getSharedFolder();
                List<CmsResource> sharedGalleries = getCmsObject().readResources(shared,
                        CmsResourceFilter.ONLY_VISIBLE_NO_DELETED.addRequireType(galleryTypeId));
                if (sharedGalleries != null) {
                    galleries.addAll(sharedGalleries);
                }
            }
        } catch (Exception e) {
            LOG.info("Could not read shared galleries: " + e.getLocalizedMessage(), e);
        }
        return galleries;
    }

    /**
     * Helper method for getting the initial gallery settings.<p>
     *
     * @param conf the gallery configration
     * @return the gallery settings
     *
     * @throws CmsRpcException if something goes wrong
     */
    private CmsGalleryDataBean getInitialSettingsInternal(CmsGalleryConfiguration conf) throws CmsRpcException {

        CmsGalleryDataBean data = new CmsGalleryDataBean();
        data.setMode(conf.getGalleryMode());
        data.setResultViewType(readResultViewType());
        boolean galleryShowInvalidDefault = Boolean.parseBoolean(getWorkplaceSettings().getUserSettings()
                .getAdditionalPreference(PREF_GALLERY_SHOW_INVALID_DEFAULT, true));
        data.setIncludeExpiredDefault(galleryShowInvalidDefault);

        data.setGalleryStoragePrefix(conf.getGalleryStoragePrefix());
        data.setLocales(buildLocalesMap());
        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(conf.getLocale())) {
            data.setLocale(conf.getLocale());
        } else {
            data.setLocale(getCmsObject().getRequestContext().getLocale().toString());
        }
        data.setVfsRootFolders(getRootEntries());
        data.setScope(getWorkplaceSettings().getLastSearchScope());
        Set<String> folderFilter = readFolderFilters();
        data.setStartFolderFilter(folderFilter);
        if ((folderFilter != null) && !folderFilter.isEmpty()) {
            try {
                data.setVfsPreloadData(generateVfsPreloadData(getCmsObject(),
                        CmsGalleryService.getVfsTreeState(getRequest(), conf.getTreeToken()), folderFilter));
            } catch (Exception e) {
                LOG.error(e.getLocalizedMessage(), e);
            }
        }
        data.setSortOrder(getWorkplaceSettings().getLastGalleryResultOrder());

        List<CmsResourceTypeBean> types = null;
        data.setTabIds(conf.getGalleryMode().getTabs());
        switch (conf.getGalleryMode()) {
        case editor:
        case view:
        case adeView:
        case widget:
            if (conf.getTabIds() != null) {
                data.setTabIds(conf.getTabIds());
            }
            data.setCurrentElement(conf.getCurrentElement());
            String referencePath = conf.getReferencePath();
            if (CmsStringUtil.isEmptyOrWhitespaceOnly(referencePath)) {
                referencePath = conf.getGalleryPath();
            }
            data.setReferenceSitePath(referencePath);
            types = getResourceTypeBeans(conf.getGalleryMode(), data.getReferenceSitePath(),
                    conf.getResourceTypes(), conf.getSearchTypes());
            data.setTypes(types);
            Map<String, CmsGalleryTypeInfo> galleryTypeInfos = readGalleryInfosByTypeBeans(types);
            // in case the 'gallerytypes' parameter is set, allow only the given galleries
            if (conf.getGalleryTypes() != null) {
                Map<String, CmsGalleryTypeInfo> infos = new HashMap<String, CmsGalleryTypeInfo>();
                for (int i = 0; i < conf.getGalleryTypes().length; i++) {
                    CmsGalleryTypeInfo typeInfo = galleryTypeInfos.get(conf.getGalleryTypes()[i]);
                    if (typeInfo != null) {
                        infos.put(conf.getGalleryTypes()[i], typeInfo);
                    }
                }
                galleryTypeInfos = infos;
            }
            data.setGalleries(buildGalleriesList(galleryTypeInfos));
            String startGallery = conf.getGalleryPath();
            // check if the configured gallery path really is an existing gallery
            boolean galleryAvailable = false;
            for (CmsGalleryFolderBean folderBean : data.getGalleries()) {
                if (folderBean.getPath().equals(startGallery)) {
                    galleryAvailable = true;
                    break;
                }
            }
            data.setStartGallery(galleryAvailable ? startGallery : null);
            if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(conf.getStartFolder())) {
                try {
                    CmsObject cloneCms = OpenCms.initCmsObject(getCmsObject());
                    if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(conf.getStartSite())) {
                        cloneCms.getRequestContext().setSiteRoot(conf.getStartSite());
                    }
                    if (cloneCms.existsResource(conf.getStartFolder(), CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) {
                        data.setStartFolder(cloneCms.getRequestContext().addSiteRoot(conf.getStartFolder()));
                    }
                } catch (CmsException e) {
                    log(e.getMessage(), e);
                }
            }

            if (CmsStringUtil.isEmptyOrWhitespaceOnly(data.getStartGallery()) && !data.getGalleries().isEmpty()) {

                String key = "";
                if (!types.isEmpty() && !CmsStringUtil.isEmptyOrWhitespaceOnly(conf.getReferencePath())) {
                    key = types.get(0).getType();
                    try {
                        CmsResource refResource = getCmsObject().readResource(conf.getReferencePath());
                        String referenceType = OpenCms.getResourceManager().getResourceType(refResource)
                                .getTypeName();
                        key = CmsGallerySearchBean.getGalleryStorageKey(data.getGalleryStoragePrefix(),
                                referenceType);
                    } catch (Exception e) {
                        LOG.error("Could not read reference resource: " + conf.getReferencePath());
                    }
                }

                if (!data.getGalleries().isEmpty()) {
                    startGallery = getWorkplaceSettings().getLastUsedGallery(key);
                    if (CmsStringUtil.isEmptyOrWhitespaceOnly(startGallery)) {
                        // check the user preferences for any configured start gallery
                        String galleryTypeName = data.getGalleries().get(0).getType();
                        startGallery = getWorkplaceSettings().getUserSettings().getStartGallery(galleryTypeName,
                                getCmsObject());
                        if (CmsWorkplace.INPUT_DEFAULT.equals(startGallery)) {
                            startGallery = OpenCms.getWorkplaceManager().getDefaultUserSettings()
                                    .getStartGallery(galleryTypeName);
                        }
                        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(startGallery)) {
                            startGallery = getCmsObject().getRequestContext().removeSiteRoot(startGallery);
                        }
                    }
                }
                // check if the gallery is available in this site and still exists
                if (!conf.isResultsSelectable()) {
                    // if selecting results is explicitly disabled, opening the start gallery does not make much sense
                    data.setStartGallery(null);
                } else if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(startGallery)) {
                    boolean galleryExists = getCmsObject().existsResource(startGallery);
                    if (galleryExists) {
                        data.setStartGallery(startGallery);
                    } else {
                        LOG.error("Could not read start gallery: " + startGallery);
                        data.setStartGallery(null);
                    }
                } else {
                    data.setStartGallery(null);
                }
            }

            GalleryTabId defaultTab = conf.getTabConfiguration().getDefaultTab();
            data.setTabConfiguration(conf.getTabConfiguration());
            if (CmsStringUtil.isEmptyOrWhitespaceOnly(data.getStartGallery())
                    && CmsStringUtil.isEmptyOrWhitespaceOnly(data.getCurrentElement())
                    && CmsStringUtil.isEmptyOrWhitespaceOnly(data.getStartFolder())) {
                data.setStartTab(defaultTab);
            } else {
                data.setStartTab(GalleryTabId.cms_tab_results);
            }
            break;
        case ade:
            data.setReferenceSitePath(getCmsObject().getRequestContext().getUri());
            types = getResourceTypeBeans(conf.getGalleryMode(), data.getReferenceSitePath(),
                    conf.getResourceTypes(), conf.getSearchTypes());
            data.setTypes(types);
            Map<String, CmsGalleryTypeInfo> adeGalleryTypeInfos = readGalleryInfosByTypeBeans(types);
            data.setGalleries(buildGalleriesList(adeGalleryTypeInfos));
            data.setStartTab(GalleryTabId.cms_tab_types);
            break;
        default:
            break;
        }

        CmsSiteSelectorOptionBuilder optionBuilder = new CmsSiteSelectorOptionBuilder(getCmsObject());
        optionBuilder.addNormalSites(true, getWorkplaceSettings().getUserSettings().getStartFolder());
        optionBuilder.addSharedSite();
        data.setVfsSiteSelectorOptions(optionBuilder.getOptions());

        CmsSiteSelectorOptionBuilder sitemapOptionBuilder = new CmsSiteSelectorOptionBuilder(getCmsObject());
        sitemapOptionBuilder.addNormalSites(false, null);
        if (data.getReferenceSitePath() != null) {
            sitemapOptionBuilder.addCurrentSubsite(getCmsObject().addSiteRoot(data.getReferenceSitePath()));
        }
        data.setSitemapSiteSelectorOptions(sitemapOptionBuilder.getOptions());
        data.setDefaultScope(OpenCms.getWorkplaceManager().getGalleryDefaultScope());
        return data;
    }

    /**
     * Reads the preview provider configuration and generates needed type-provider mappings.<p>
     *
     * @param types the resource types
     *
     * @return a map from resource types to preview providers
     */
    private Map<I_CmsResourceType, I_CmsPreviewProvider> getPreviewProviderForTypes(List<I_CmsResourceType> types) {

        Map<String, I_CmsPreviewProvider> previewProviderMap = new HashMap<String, I_CmsPreviewProvider>();
        Map<I_CmsResourceType, I_CmsPreviewProvider> typeProviderMapping = new HashMap<I_CmsResourceType, I_CmsPreviewProvider>();
        for (I_CmsResourceType type : types) {
            String providerClass = type.getGalleryPreviewProvider();
            if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(providerClass)) {
                providerClass = providerClass.trim();
                try {
                    if (previewProviderMap.containsKey(providerClass)) {
                        typeProviderMapping.put(type, previewProviderMap.get(providerClass));
                    } else {
                        I_CmsPreviewProvider previewProvider = (I_CmsPreviewProvider) Class.forName(providerClass)
                                .newInstance();
                        previewProviderMap.put(providerClass, previewProvider);
                        typeProviderMapping.put(type, previewProvider);
                    }
                } catch (Exception e) {
                    logError(new CmsException(Messages.get().container(Messages.ERR_INSTANCING_PREVIEW_PROVIDER_2,
                            providerClass, type.getTypeName()), e));
                }
            }
        }
        return typeProviderMapping;
    }

    /**
     * Returns the resourceManager.<p>
     *
     * @return the resourceManager
     */
    private CmsResourceManager getResourceManager() {

        if (m_resourceManager == null) {
            m_resourceManager = OpenCms.getResourceManager();
        }
        return m_resourceManager;
    }

    /**
     * Returns the resource types configured to be used within the given gallery mode.<p>
     *
     * @param galleryMode the gallery mode
     * @param referenceSitePath the reference site-path to check permissions for
     * @param resourceTypesList the resource types parameter
     * @param typesForTypeTab the types which should be shown in the types tab according to the gallery configuration
     *
     * @return the resource types
     */
    private List<CmsResourceTypeBean> getResourceTypeBeans(GalleryMode galleryMode, String referenceSitePath,
            List<String> resourceTypesList, final List<String> typesForTypeTab) {

        List<I_CmsResourceType> resourceTypes = null;
        Set<String> creatableTypes = null;
        switch (galleryMode) {
        case editor:
        case view:
        case adeView:
        case widget:
            resourceTypes = convertTypeNamesToTypes(resourceTypesList);
            if (resourceTypes.size() == 0) {
                resourceTypes = Lists.newArrayList(getDefaultTypesForGallery());
            }
            creatableTypes = Collections.<String>emptySet();
            break;
        case ade:
            throw new IllegalStateException("This code should never be called");
            // ADE case is handled by container page service
        default:
            resourceTypes = Collections.<I_CmsResourceType>emptyList();
            creatableTypes = Collections.<String>emptySet();
        }
        return buildTypesList(resourceTypes, creatableTypes, Collections.<String>emptySet(), typesForTypeTab);
    }

    /**
     * Returns the VFS root entries.<p>
     *
     * @return the VFS root entries
     *
     * @throws CmsRpcException if something goes wrong
     */
    private List<CmsVfsEntryBean> getRootEntries() throws CmsRpcException {

        List<CmsVfsEntryBean> rootFolders = new ArrayList<CmsVfsEntryBean>();
        CmsObject cms = getCmsObject();
        try {
            String path = "/";
            if (!cms.existsResource(path, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) {
                String startFolder = getWorkplaceSettings().getUserSettings().getStartFolder();
                if (cms.existsResource(startFolder, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) {
                    path = startFolder;
                } else {
                    path = null;
                }
            }
            if (path != null) {
                CmsResource rootFolderResource = getCmsObject().readResource(path,
                        CmsResourceFilter.ONLY_VISIBLE_NO_DELETED);
                String title = cms.readPropertyObject(path, CmsPropertyDefinition.PROPERTY_TITLE, false).getValue();
                rootFolders.add(internalCreateVfsEntryBean(getCmsObject(), rootFolderResource, title, true,
                        isEditable(getCmsObject(), rootFolderResource), null, false));
            }

        } catch (CmsException e) {
            error(e);
        }
        return rootFolders;
    }

    /**
     * Returns the workplace locale from the current user's settings.<p>
     *
     * @return the workplace locale
     */
    private Locale getWorkplaceLocale() {

        if (m_wpLocale == null) {
            m_wpLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(getCmsObject());
        }
        return m_wpLocale;
    }

    /**
     * Returns the workplace settings of the current user.<p>
     *
     * @return the workplace settings
     */
    private CmsWorkplaceSettings getWorkplaceSettings() {

        if (m_workplaceSettings == null) {
            m_workplaceSettings = CmsWorkplace.getWorkplaceSettings(getCmsObject(), getRequest());
        }
        return m_workplaceSettings;
    }

    /**
     * Checks whether a resource has a navigation property.<p>
     *
     * @param cms the current CMS context
     * @param resource the resource to use
     *
     * @return true if the resource has a navigation property
     *
     * @throws CmsException if something goes wrong
     */
    private boolean hasNavigationProperty(CmsObject cms, CmsResource resource) throws CmsException {

        List<CmsProperty> props = cms.readPropertyObjects(resource, false);
        Map<String, String> propMap = CmsProperty.toMap(props);
        return propMap.containsKey(CmsPropertyDefinition.PROPERTY_NAVPOS)
                || propMap.containsKey(CmsPropertyDefinition.PROPERTY_NAVTEXT);
    }

    /**
     * Returns the search parameters for the given query data.<p>
     *
     * @param searchData the query data
     *
     * @return the prepared search parameters
     */
    private CmsGallerySearchParameters prepareSearchParams(CmsGallerySearchBean searchData) {

        // create a new search parameter object
        CmsGallerySearchParameters params = new CmsGallerySearchParameters();
        CmsObject cms = getCmsObject();

        // set the selected types to the parameters
        if (searchData.getServerSearchTypes() != null) {
            params.setResourceTypes(searchData.getServerSearchTypes());
        }

        // set the selected galleries to the parameters
        if (searchData.getGalleries() != null) {
            List<String> paramGalleries = new ArrayList<String>();
            for (String gallerySitePath : searchData.getGalleries()) {
                paramGalleries.add(cms.getRequestContext().addSiteRoot(gallerySitePath));
            }
            params.setGalleries(paramGalleries);
        }

        // set the sort order for the galleries to the parameters
        CmsGallerySearchParameters.CmsGallerySortParam sortOrder;
        String temp = searchData.getSortOrder();
        try {
            sortOrder = CmsGallerySearchParameters.CmsGallerySortParam.valueOf(temp);
        } catch (Exception e) {
            sortOrder = CmsGallerySearchParameters.CmsGallerySortParam.DEFAULT;
        }
        params.setSortOrder(sortOrder);
        if (searchData.getScope() == null) {
            params.setScope(OpenCms.getWorkplaceManager().getGalleryDefaultScope());
        } else {
            params.setScope(searchData.getScope());
        }
        params.setReferencePath(searchData.getReferencePath());

        // set the selected folders to the parameters
        params.setFolders(new ArrayList<String>(searchData.getFolders()));

        // set the categories to the parameters
        if (searchData.getCategories() != null) {
            params.setCategories(searchData.getCategories());
        }

        // set the search query to the parameters
        if (!CmsStringUtil.isEmptyOrWhitespaceOnly(searchData.getQuery())) {
            params.setSearchWords(searchData.getQuery());
        }

        // set the result page to the parameters
        int page = searchData.getPage();
        params.setResultPage(page);

        // set the locale to the parameters
        String locale = searchData.getLocale();
        if (CmsStringUtil.isEmptyOrWhitespaceOnly(locale)) {
            locale = getCmsObject().getRequestContext().getLocale().toString();
        }
        params.setSearchLocale(locale);

        // set the matches per page to the parameters
        params.setMatchesPerPage(searchData.getMatchesPerPage());

        // get the date range input
        long dateCreatedStart = searchData.getDateCreatedStart();
        long dateCreatedEnd = searchData.getDateCreatedEnd();
        long dateModifiedStart = searchData.getDateModifiedStart();
        long dateModifiedEnd = searchData.getDateModifiedEnd();

        // set the date created range to the parameters
        if ((dateCreatedStart != -1L) && (dateCreatedEnd != -1L)) {
            params.setDateCreatedTimeRange(dateCreatedStart, dateCreatedEnd);
        } else if (dateCreatedStart != -1L) {
            params.setDateCreatedTimeRange(dateCreatedStart, Long.MAX_VALUE);
        } else if (dateCreatedEnd != -1L) {
            params.setDateCreatedTimeRange(Long.MIN_VALUE, dateCreatedEnd);
        }

        // set the date modified range to the parameters
        if ((dateModifiedStart != -1L) && (dateModifiedEnd != -1L)) {
            params.setDateLastModifiedTimeRange(dateModifiedStart, dateModifiedEnd);
        } else if (dateModifiedStart != -1L) {
            params.setDateLastModifiedTimeRange(dateModifiedStart, Long.MAX_VALUE);
        } else if (dateModifiedEnd != -1L) {
            params.setDateLastModifiedTimeRange(Long.MIN_VALUE, dateModifiedEnd);
        }
        params.setIgnoreSearchExclude(searchData.isIgnoreSearchExclude());
        return params;
    }

    /**
     * Prepares a sitemap entry bean from the given navigation element.<p>
     *
     * @param cms the cms context
     * @param navElement the navigation element
     * @param isRoot <code>true</code> if this is a site root entry
     * @param checkHasChildren if true, check if the entry has any children; set to false if you want to handle the list of children manually
     *
     * @return the sitemap entry
     *
     * @throws CmsException if something goes wrong reading types and resources
     */
    private CmsSitemapEntryBean prepareSitemapEntry(CmsObject cms, CmsJspNavElement navElement, boolean isRoot,
            boolean checkHasChildren) throws CmsException {

        CmsResource ownResource = navElement.getResource();
        CmsResource defaultFileResource = null;
        CmsJspNavBuilder navBuilder = new CmsJspNavBuilder(cms);
        if (ownResource.isFolder() && !navElement.isNavigationLevel()) {
            try {
                defaultFileResource = cms.readDefaultFile(ownResource, CmsResourceFilter.ONLY_VISIBLE);
            } catch (CmsPermissionViolationException e) {
                // user has insufficient rights, can be ignored
            }
        }
        String type;
        if (defaultFileResource != null) {
            type = OpenCms.getResourceManager().getResourceType(defaultFileResource.getTypeId()).getTypeName();
        } else {
            type = OpenCms.getResourceManager().getResourceType(ownResource.getTypeId()).getTypeName();
        }
        boolean isNavLevel = ownResource.isFolder() && navElement.isNavigationLevel();
        // make sure not to show ??? NavText ???
        String title = null;
        if (CmsStringUtil
                .isNotEmptyOrWhitespaceOnly(navElement.getProperty(CmsPropertyDefinition.PROPERTY_NAVTEXT))) {
            title = navElement.getProperty(CmsPropertyDefinition.PROPERTY_NAVTEXT);
        } else if (CmsStringUtil
                .isNotEmptyOrWhitespaceOnly(navElement.getProperty(CmsPropertyDefinition.PROPERTY_TITLE))) {
            title = navElement.getProperty(CmsPropertyDefinition.PROPERTY_TITLE);
        } else {
            title = navElement.getFileName();
            if (title.contains("/")) {
                title = title.substring(0, title.indexOf("/"));
            }
        }
        String childPath = navElement.getResource().getRootPath();
        boolean noChildren = true;

        if (checkHasChildren) {
            List<CmsJspNavElement> childNav = navBuilder.getNavigationForFolder(childPath, Visibility.all,
                    CmsResourceFilter.ONLY_VISIBLE);
            for (CmsJspNavElement childNavEntry : childNav) {
                if (childNavEntry.isInNavigation()) {
                    noChildren = false;
                    break;
                }
            }
        }

        CmsSitemapEntryBean result = new CmsSitemapEntryBean(navElement.getResource().getRootPath(),
                navElement.getResourceName(), ownResource.getStructureId(), title, type, ownResource.isFolder(),
                isRoot, navElement.isHiddenNavigationEntry(), isNavLevel);
        result.setSiteRoot(OpenCms.getSiteManager().getSiteRoot(ownResource.getRootPath()));

        if (checkHasChildren && noChildren) {
            result.setChildren(new ArrayList<CmsSitemapEntryBean>());
        }

        return result;
    }

    /**
     * Reads the folder filters for the current site.<p>
     *
     * @return the folder filters
     */
    private Set<String> readFolderFilters() {

        JSONObject storedFilters = readUserFolderFilters();
        Set<String> result = null;
        if (storedFilters.has(getCmsObject().getRequestContext().getSiteRoot())) {
            try {
                org.opencms.json.JSONArray folders = storedFilters
                        .getJSONArray(getCmsObject().getRequestContext().getSiteRoot());
                result = new HashSet<String>();
                for (int i = 0; i < folders.length(); i++) {
                    result.add(folders.getString(i));
                }
            } catch (JSONException e) {
                LOG.error(e.getLocalizedMessage(), e);
            }
        }
        return result;
    }

    /**
     * Returns a map with gallery type names associated with the list of available galleries for this type.<p>
     *
     * @param resourceTypes the resources types to collect the galleries for
     *
     * @return a map with gallery type and  the associated galleries
     */
    private Map<String, CmsGalleryTypeInfo> readGalleryInfosByTypeBeans(List<CmsResourceTypeBean> resourceTypes) {

        Map<String, CmsGalleryTypeInfo> galleryTypeInfos = new HashMap<String, CmsGalleryTypeInfo>();
        for (CmsResourceTypeBean typeBean : resourceTypes) {
            try {
                if (!typeBean.isDeactivated()) {
                    addGalleriesForType(galleryTypeInfos, typeBean.getType());
                }
            } catch (CmsLoaderException e1) {
                logError(e1);
            }
        }
        return galleryTypeInfos;
    }

    /**
     * Returns a map with gallery type names associated with the list of available galleries for this type.<p>
     *
     * @param resourceTypes the resources types to collect the galleries for
     *
     * @return a map with gallery type and  the associated galleries
     */
    private Map<String, CmsGalleryTypeInfo> readGalleryInfosByTypeNames(List<String> resourceTypes) {

        Map<String, CmsGalleryTypeInfo> galleryTypeInfos = new HashMap<String, CmsGalleryTypeInfo>();
        for (String typeName : resourceTypes) {
            try {
                addGalleriesForType(galleryTypeInfos, typeName);
            } catch (CmsLoaderException e1) {
                logError(e1);
            }
        }
        return galleryTypeInfos;
    }

    /**
     * Reads the result view type from the current user.<p>
     *
     * @return the result view type
     */
    private String readResultViewType() {

        return (String) getCmsObject().getRequestContext().getCurrentUser()
                .getAdditionalInfo(RESULT_VIEW_TYPE_ADD_INFO_KEY);
    }

    /**
     * Reads the users folder filters from the additional info.<p>
     *
     * @return the folder filters
     */
    private JSONObject readUserFolderFilters() {

        CmsUser user = getCmsObject().getRequestContext().getCurrentUser();
        String addInfo = (String) user.getAdditionalInfo(FOLDER_FILTER_ADD_INFO_KEY);
        JSONObject result = null;
        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(addInfo)) {
            try {
                result = new JSONObject(addInfo);
            } catch (JSONException e) {
                LOG.error(e.getLocalizedMessage(), e);
            }
        }
        if (result == null) {
            result = new JSONObject();
        }
        return result;
    }

    /**
     * Returns the gallery search object containing the results for the current parameter.<p>
     *
     * @param searchObj the current search object
     *
     * @return the search result
     *
     * @throws CmsException if the search fails
     */
    private CmsGallerySearchBean search(CmsGallerySearchBean searchObj) throws CmsException {

        CmsGallerySearchBean searchObjBean = new CmsGallerySearchBean(searchObj);
        if (searchObj == null) {
            return searchObjBean;
        }
        // store folder filter
        storeFolderFilter(searchObj.getFolders());

        // search
        CmsGallerySearchParameters params = prepareSearchParams(searchObj);
        org.opencms.search.galleries.CmsGallerySearch searchBean = new org.opencms.search.galleries.CmsGallerySearch();
        CmsObject searchCms = getSearchCms(searchObj);
        searchBean.init(searchCms);

        CmsGallerySearchResultList searchResults = OpenCms.getSearchManager().getIndexSolr("Solr Offline")
                .gallerySearch(searchCms, params);
        searchResults.calculatePages(params.getResultPage(), params.getMatchesPerPage());

        // set only the result dependent search params for this search
        // the user dependent params(galleries, types etc.) remain unchanged
        searchObjBean.setSortOrder(params.getSortOrder().name());
        searchObjBean.setScope(params.getScope());
        searchObjBean.setResultCount(searchResults.getHitCount());
        searchObjBean.setPage(params.getResultPage());
        searchObjBean.setLastPage(params.getResultPage());
        searchObjBean.setResults(buildSearchResultList(searchResults, null));
        if (searchObj.getGalleryMode().equals(GalleryMode.ade)) {
            if (searchObjBean.getResultCount() > 0) {
                CmsADESessionCache cache = CmsADESessionCache.getCache(getRequest(), getCmsObject());
                cache.setLastPageEditorGallerySearch(searchObj);
            }
        }
        updateNoUploadReason(searchCms, searchObjBean);
        return searchObjBean;
    }

    /**
     * Sets the last opened gallery information for the current user.<p>
     *
     * @param searchObject the current search
     */
    private void setLastOpenedGallery(CmsGallerySearchBean searchObject) {

        if ((searchObject.getGalleries() != null) && (searchObject.getGalleries().size() <= 1) // if the size is 0, the user has actively deselected the galleries, so we want to handle this case too
                && searchObject.haveGalleriesChanged()) {
            String galleryPath = searchObject.getGalleries().isEmpty() ? null : searchObject.getGalleries().get(0);
            CmsWorkplaceSettings settings = getWorkplaceSettings();
            if (searchObject.getGalleryMode() == GalleryMode.adeView) {
                settings.setLastUsedGallery("" + GalleryMode.adeView, galleryPath);
            } else {
                String referencePath = searchObject.getReferencePath();

                String referenceTypeName = "";

                try {
                    CmsObject cms = getCmsObject();
                    CmsResource referenceResource = cms.readResource(referencePath);
                    I_CmsResourceType referenceType = OpenCms.getResourceManager()
                            .getResourceType(referenceResource);
                    referenceTypeName = referenceType.getTypeName();
                } catch (CmsException e) {
                    LOG.error(e.getLocalizedMessage(), e);
                }
                settings.setLastUsedGallery(CmsGallerySearchBean.getGalleryStorageKey(
                        searchObject.getGalleryStoragePrefix(), referenceTypeName), galleryPath);
            }
        }
    }

    /**
     * Stores the folder filters for the current site.<p>
     *
     * @param folders the folder filters
     */
    private void storeFolderFilter(Set<String> folders) {

        JSONObject storedFilters = readUserFolderFilters();
        try {
            storedFilters.put(getCmsObject().getRequestContext().getSiteRoot(), folders);
            CmsUser user = getCmsObject().getRequestContext().getCurrentUser();
            user.setAdditionalInfo(FOLDER_FILTER_ADD_INFO_KEY, storedFilters.toString());
            getCmsObject().writeUser(user);
        } catch (Exception e) {
            LOG.error(e.getLocalizedMessage(), e);
        }
    }

    /**
     * Checks the current users permissions on the upload target folder to update the no upload reason.<p>
     *
     * @param searchCms the cms context
     * @param searchObj the search data
     */
    private void updateNoUploadReason(CmsObject searchCms, CmsGallerySearchBean searchObj) {

        if ((searchObj.getGalleries().size() + searchObj.getFolders().size()) == 1) {
            String target = !searchObj.getGalleries().isEmpty() ? searchObj.getGalleries().get(0)
                    : searchObj.getFolders().iterator().next();
            try {
                CmsResource targetRes = searchCms.readResource(target, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED);
                searchObj.setNoUploadReason(
                        new CmsResourceUtil(searchCms, targetRes).getNoEditReason(getWorkplaceLocale(), true));
            } catch (CmsException e) {
                searchObj.setNoUploadReason(e.getLocalizedMessage(getWorkplaceLocale()));
            }
        } else {
            searchObj.setNoUploadReason(null);
        }
    }
}