All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opencms.xml.containerpage.CmsFormatterConfiguration Maven / Gradle / Ivy

Go to download

OpenCms is an enterprise-ready, easy to use website content management system based on Java and XML technology. Offering a complete set of features, OpenCms helps content managers worldwide to create and maintain beautiful websites fast and efficiently.

There is a newer version: 18.0
Show newest version
/*
 * 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.xml.containerpage;

import org.opencms.ade.containerpage.shared.CmsFormatterConfig;
import org.opencms.file.CmsObject;
import org.opencms.file.CmsResource;
import org.opencms.file.types.CmsResourceTypeJsp;
import org.opencms.main.CmsException;
import org.opencms.main.CmsLog;
import org.opencms.main.OpenCms;
import org.opencms.security.CmsRole;
import org.opencms.util.CmsStringUtil;
import org.opencms.util.CmsUUID;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;

import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

/**
 * Represents a formatter configuration.

* * A formatter configuration can be either defined in the XML schema XSD of a XML content, * or in a special sitemap configuration file.

* * @since 8.0.0 */ public final class CmsFormatterConfiguration { /** * This class is used to sort lists of formatter beans in order of importance.

*/ public static class FormatterComparator implements Comparator { /** * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) */ public int compare(I_CmsFormatterBean first, I_CmsFormatterBean second) { return ComparisonChain.start().compare(second.getRank(), first.getRank()).compare( second.isTypeFormatter() ? 1 : 0, first.isTypeFormatter() ? 1 : 0).compare(second.getMinWidth(), first.getMinWidth()).result(); } } /** * Predicate which checks whether the given formatter is a detail formatter.

*/ public static class IsDetail implements Predicate { /** * @see com.google.common.base.Predicate#apply(java.lang.Object) */ public boolean apply(I_CmsFormatterBean formatter) { return formatter.isDetailFormatter(); } } /** * Predicate which checks whether the given formatter is a display formatter.

*/ public static class IsDisplay implements Predicate { /** * @see com.google.common.base.Predicate#apply(java.lang.Object) */ public boolean apply(I_CmsFormatterBean formatter) { return formatter.isDisplayFormatter(); } } /** * Predicate to check whether the formatter is from a schema.

*/ public static class IsSchemaFormatter implements Predicate { /** * @see com.google.common.base.Predicate#apply(java.lang.Object) */ public boolean apply(I_CmsFormatterBean formatter) { return !formatter.isFromFormatterConfigFile(); } } /** * Predicate which checks whether a formatter matches the given container type or width.

*/ private class MatchesTypeOrWidth implements Predicate { /** If nested containers are allowed. */ private boolean m_allowNested; /** The set of container types to match. */ private Set m_types = Sets.newHashSet(); /** The container width. */ private int m_width; /** * Creates a new matcher instance.

* * @param type the container type * @param width the container width * @param allowNested if nested containers are allowed */ public MatchesTypeOrWidth(String type, int width, boolean allowNested) { if (!CmsStringUtil.isEmptyOrWhitespaceOnly(type)) { // split with comma and optionally spaces to the left/right of the comma as separator m_types.addAll(Arrays.asList(type.trim().split(" *, *"))); } m_width = width; m_allowNested = allowNested; } /** * @see com.google.common.base.Predicate#apply(java.lang.Object) */ public boolean apply(I_CmsFormatterBean formatter) { return matchFormatter(formatter, m_types, m_width, m_allowNested); } } /** The empty formatter configuration. */ public static final CmsFormatterConfiguration EMPTY_CONFIGURATION = new CmsFormatterConfiguration(null, null); /** The log instance for this class. */ public static final Log LOG = CmsLog.getLog(CmsFormatterConfiguration.class); /** The container width to match all width configured formatters. */ public static final int MATCH_ALL_CONTAINER_WIDTH = -2; /** CmsObject used to read the JSP resources configured in the XSD schema. */ private static CmsObject m_adminCms; /** All formatters that have been added to this configuration. */ private List m_allFormatters; /** The available display formatters. */ private List m_displayFormatters; /** Cache for the searchContent option. */ private Map m_searchContent = Maps.newHashMap(); /** * Creates a new formatter configuration based on the given list of formatters.

* * @param cms the current users OpenCms context * @param formatters the list of configured formatters */ private CmsFormatterConfiguration(CmsObject cms, List formatters) { if (formatters == null) { // this is needed for the empty configuration m_allFormatters = Collections.emptyList(); } else { m_allFormatters = new ArrayList(formatters); } init(cms, m_adminCms); } /** * Returns the formatter configuration for the current project based on the given list of formatters.

* * @param cms the current users OpenCms context, required to know which project to read the JSP from * @param formatters the list of configured formatters * * @return the formatter configuration for the current project based on the given list of formatters */ public static CmsFormatterConfiguration create(CmsObject cms, List formatters) { if ((formatters != null) && (formatters.size() > 0) && (cms != null)) { return new CmsFormatterConfiguration(cms, formatters); } else { return EMPTY_CONFIGURATION; } } /** * Initialize the formatter configuration.

* * @param cms an initialized admin OpenCms user context * * @throws CmsException in case the initialization fails */ public static void initialize(CmsObject cms) throws CmsException { OpenCms.getRoleManager().checkRole(cms, CmsRole.ADMINISTRATOR); try { // store the Admin cms to index Cms resources m_adminCms = OpenCms.initCmsObject(cms); m_adminCms.getRequestContext().setSiteRoot(""); } catch (CmsException e) { // this should never happen } } /** * Checks whether the given formatter bean matches the container types, width and nested flag.

* * @param formatter the formatter bean * @param types the container types * @param width the container width * @param allowNested whether nested containers are allowed * * @return true in case the formatter matches */ public static boolean matchFormatter( I_CmsFormatterBean formatter, Set types, int width, boolean allowNested) { if (!allowNested && formatter.hasNestedContainers()) { return false; } if (formatter.isMatchAll()) { return true; } if (formatter.isTypeFormatter()) { return !Sets.intersection(types, formatter.getContainerTypes()).isEmpty(); } else { return (width == MATCH_ALL_CONTAINER_WIDTH) || ((formatter.getMinWidth() <= width) && (width <= formatter.getMaxWidth())); } } /** * Gets a list of all defined formatters.

* * @return the list of all formatters */ public List getAllFormatters() { return new ArrayList(m_allFormatters); } /** * Gets the formatters which are available for the given container type and width.

* * @param containerTypes the container types (comma separated) * @param containerWidth the container width * @param allowNested if nested containers are allowed * * @return the list of available formatters */ public List getAllMatchingFormatters( String containerTypes, int containerWidth, boolean allowNested) { return new ArrayList( Collections2.filter(m_allFormatters, new MatchesTypeOrWidth(containerTypes, containerWidth, allowNested))); } /** * Selects the best matching formatter for the provided type and width from this configuration.

* * This method first tries to find the formatter for the provided container type. * If this fails, it returns the width based formatter that matched the container width.

* * @param containerTypes the container types (comma separated) * @param containerWidth the container width * @param allowNested if nested containers are allowed * * @return the matching formatter, or null if none was found */ public I_CmsFormatterBean getDefaultFormatter( final String containerTypes, final int containerWidth, final boolean allowNested) { Optional result = Iterables.tryFind( m_allFormatters, new MatchesTypeOrWidth(containerTypes, containerWidth, allowNested)); return result.orNull(); } /** * Selects the best matching schema formatter for the provided type and width from this configuration.

* * @param containerTypes the container types (comma separated) * @param containerWidth the container width * * @return the matching formatter, or null if none was found */ public I_CmsFormatterBean getDefaultSchemaFormatter(final String containerTypes, final int containerWidth) { Optional result = Iterables.tryFind( m_allFormatters, Predicates.and(new IsSchemaFormatter(), new MatchesTypeOrWidth(containerTypes, containerWidth, false))); return result.orNull(); } /** * Gets the detail formatter to use for the given type and container width.

* * @param types the container types (comma separated) * @param containerWidth the container width * * @return the detail formatter to use */ public I_CmsFormatterBean getDetailFormatter(String types, int containerWidth) { // detail formatters must still match the type or width Predicate checkValidDetailFormatter = Predicates.and( new MatchesTypeOrWidth(types, containerWidth, true), new IsDetail()); Optional result = Iterables.tryFind(m_allFormatters, checkValidDetailFormatter); return result.orNull(); } /** * Gets all detail formatters.

* * @return the detail formatters */ public Collection getDetailFormatters() { return Collections. unmodifiableCollection( Collections2.filter(m_allFormatters, new IsDetail())); } /** * Returns the display formatter for this type.

* * @return the display formatter */ public I_CmsFormatterBean getDisplayFormatter() { if (!getDisplayFormatters().isEmpty()) { return getDisplayFormatters().get(0); } return null; } /** * Returns the available display formatters.

* * @return the display formatters */ public List getDisplayFormatters() { if (m_displayFormatters == null) { List formatters = new ArrayList( Collections2.filter(m_allFormatters, new IsDisplay())); if (formatters.size() > 1) { Collections.sort(formatters, new Comparator() { public int compare(I_CmsFormatterBean o1, I_CmsFormatterBean o2) { return o1.getRank() == o2.getRank() ? 0 : (o1.getRank() < o2.getRank() ? -1 : 1); } }); } m_displayFormatters = Collections.unmodifiableList(formatters); } return m_displayFormatters; } /** * Returns the formatters available for selection for the given container type and width.

* * @param containerTypes the container types (comma separated) * @param containerWidth the container width * @param allowNested if nested containers are allowed * * @return the list of available formatters */ public Map getFormatterSelection( String containerTypes, int containerWidth, boolean allowNested) { Map result = new LinkedHashMap(); for (I_CmsFormatterBean formatter : Collections2.filter( m_allFormatters, new MatchesTypeOrWidth(containerTypes, containerWidth, allowNested))) { if (formatter.isFromFormatterConfigFile()) { result.put(formatter.getId(), formatter); } else { result.put( CmsFormatterConfig.SCHEMA_FORMATTER_ID + formatter.getJspStructureId().toString(), formatter); } } return result; } /** * Returns the formatter from this configuration that is to be used for the preview in the ADE gallery GUI, * or null if there is no preview formatter configured.

* * @return the formatter from this configuration that is to be used for the preview in the ADE gallery GUI, * or null if there is no preview formatter configured */ public I_CmsFormatterBean getPreviewFormatter() { Optional result; result = Iterables.tryFind(m_allFormatters, new Predicate() { public boolean apply(I_CmsFormatterBean formatter) { return formatter.isPreviewFormatter(); } }); if (!result.isPresent()) { result = Iterables.tryFind(m_allFormatters, new Predicate() { public boolean apply(I_CmsFormatterBean formatter) { if (formatter.isTypeFormatter()) { return formatter.getContainerTypes().contains(CmsFormatterBean.PREVIEW_TYPE); } else { return (formatter.getMinWidth() <= CmsFormatterBean.PREVIEW_WIDTH) && (CmsFormatterBean.PREVIEW_WIDTH <= formatter.getMaxWidth()); } } }); } if (!result.isPresent()) { result = Iterables.tryFind(m_allFormatters, new Predicate() { public boolean apply(I_CmsFormatterBean formatter) { return !formatter.isTypeFormatter() && (formatter.getMaxWidth() >= CmsFormatterBean.PREVIEW_WIDTH); } }); } if (!result.isPresent() && !m_allFormatters.isEmpty()) { result = Optional.fromNullable(m_allFormatters.iterator().next()); } return result.orNull(); } /** * Returns the provided true in case this configuration has a formatter * for the given type / width parameters.

* * @param containerTypes the container types (comma separated) * @param containerWidth the container width * @param allowNested if nested containers are allowed * * @return the provided true in case this configuration has a formatter * for the given type / width parameters. */ public boolean hasFormatter(String containerTypes, int containerWidth, boolean allowNested) { return getDefaultFormatter(containerTypes, containerWidth, allowNested) != null; } /** * Returns true in case there is at least one usable formatter configured in this configuration.

* * @return true in case there is at least one usable formatter configured in this configuration */ public boolean hasFormatters() { return !m_allFormatters.isEmpty(); } /** * Returns true in case this configuration contains a formatter with the * provided structure id that has been configured for including the formatted content in the online search.

* * @param formatterStructureId the formatter structure id * * @return true in case this configuration contains a formatter with the * provided structure id that has been configured for including the formatted content in the online search */ public boolean isSearchContent(CmsUUID formatterStructureId) { if (EMPTY_CONFIGURATION == this) { // don't search if this is just the empty configuration return false; } // lookup the cache Boolean result = m_searchContent.get(formatterStructureId); if (result == null) { // result so far unknown for (I_CmsFormatterBean formatter : m_allFormatters) { if (formatter.getJspStructureId().equals(formatterStructureId)) { // found the match result = Boolean.valueOf(formatter.isSearchContent()); // first match rules break; } } if (result == null) { // no match found, in this case dont search the content result = Boolean.FALSE; } // store result in the cache m_searchContent.put(formatterStructureId, result); } return result.booleanValue(); } /** * Initializes all formatters of this configuration.

* * It is also checked if the configured JSP root path exists, if not the formatter is removed * as it is unusable.

* * @param userCms the current users OpenCms context, used for selecting the right project * @param adminCms the Admin user context to use for reading the JSP resources */ private void init(CmsObject userCms, CmsObject adminCms) { List filteredFormatters = new ArrayList(); for (I_CmsFormatterBean formatter : m_allFormatters) { if (formatter.getJspStructureId() == null) { // a formatter may have been re-used so the structure id is already available CmsResource res = null; // first we make sure that the JSP exists at all (and also we read the UUID that way) try { // first get a cms copy so we can mess up the context without modifying the original CmsObject cmsCopy = OpenCms.initCmsObject(adminCms); cmsCopy.getRequestContext().setCurrentProject(userCms.getRequestContext().getCurrentProject()); // switch to the root site cmsCopy.getRequestContext().setSiteRoot(""); // now read the JSP res = cmsCopy.readResource(formatter.getJspRootPath()); } catch (CmsException e) { //if this happens the result is null and we write a LOG error } if ((res == null) || !CmsResourceTypeJsp.isJsp(res)) { // the formatter must exist and it must be a JSP LOG.error( Messages.get().getBundle().key( Messages.ERR_FORMATTER_JSP_DONT_EXIST_1, formatter.getJspRootPath())); } else { formatter.setJspStructureId(res.getStructureId()); // res may still be null in case of failure } } if (formatter.getJspStructureId() != null) { filteredFormatters.add(formatter); } else { LOG.warn("Invalid formatter: " + formatter.getJspRootPath()); } } Collections.sort(filteredFormatters, new FormatterComparator()); m_allFormatters = Collections.unmodifiableList(filteredFormatters); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy