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

org.opencms.ade.containerpage.CmsModelGroupHelper 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 (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.containerpage;

import org.opencms.ade.configuration.CmsADEConfigData;
import org.opencms.ade.configuration.CmsResourceTypeConfig;
import org.opencms.ade.containerpage.shared.CmsContainerElement;
import org.opencms.ade.containerpage.shared.CmsContainerElement.ModelGroupState;
import org.opencms.ade.containerpage.shared.CmsFormatterConfig;
import org.opencms.file.CmsObject;
import org.opencms.file.CmsProperty;
import org.opencms.file.CmsPropertyDefinition;
import org.opencms.file.CmsResource;
import org.opencms.file.CmsUser;
import org.opencms.file.types.CmsResourceTypeXmlContainerPage;
import org.opencms.lock.CmsLock;
import org.opencms.main.CmsException;
import org.opencms.main.CmsLog;
import org.opencms.main.OpenCms;
import org.opencms.util.CmsStringUtil;
import org.opencms.util.CmsUUID;
import org.opencms.xml.containerpage.CmsADESessionCache;
import org.opencms.xml.containerpage.CmsContainerBean;
import org.opencms.xml.containerpage.CmsContainerElementBean;
import org.opencms.xml.containerpage.CmsContainerPageBean;
import org.opencms.xml.containerpage.CmsXmlContainerPage;
import org.opencms.xml.containerpage.CmsXmlContainerPageFactory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.logging.Log;

/**
 * Handles all model group specific tasks.

*/ public class CmsModelGroupHelper { /** The name of the container storing the groups base element. */ public static final String MODEL_GROUP_BASE_CONTAINER = "base_container"; /** Static reference to the log. */ private static final Log LOG = CmsLog.getLog(CmsModelGroupHelper.class); /** The current cms context. */ private CmsObject m_cms; /** The session cache instance. */ private CmsADESessionCache m_sessionCache; /** The configuration data of the current container page location. */ private CmsADEConfigData m_configData; /** Indicating the edit model groups mode. */ private boolean m_isEditingModelGroups; /** * Constructor.

* * @param cms the current cms context * @param configData the configuration data * @param sessionCache the session cache * @param isEditingModelGroups the edit model groups flag */ public CmsModelGroupHelper( CmsObject cms, CmsADEConfigData configData, CmsADESessionCache sessionCache, boolean isEditingModelGroups) { m_cms = cms; m_sessionCache = sessionCache; m_configData = configData; m_isEditingModelGroups = isEditingModelGroups; } /** * Creates a new model group resource.

* * @param cms the current cms context * @param configData the configuration data * * @return the new resource * * @throws CmsException in case creating the resource fails */ public static CmsResource createModelGroup(CmsObject cms, CmsADEConfigData configData) throws CmsException { CmsResourceTypeConfig typeConfig = configData.getResourceType( CmsResourceTypeXmlContainerPage.MODEL_GROUP_TYPE_NAME); return typeConfig.createNewElement(cms, configData.getBasePath()); } /** * Returns if the given resource is a model group resource.

* * @param resource the resource * * @return true if the given resource is a model group resource */ public static boolean isModelGroupResource(CmsResource resource) { return CmsResourceTypeXmlContainerPage.MODEL_GROUP_TYPE_NAME.equals( OpenCms.getResourceManager().getResourceType(resource).getTypeName()); } /** * Adds the model group elements to the page.

* * @param elements the requested elements * @param page the page * @param locale the content locale * * @return the adjusted page * * @throws CmsException in case something goes wrong */ public CmsContainerPageBean prepareforModelGroupContent( Map elements, CmsContainerPageBean page, Locale locale) throws CmsException { for (Entry entry : elements.entrySet()) { CmsContainerElementBean element = entry.getValue(); CmsContainerPageBean modelPage = null; String modelInstanceId = null; boolean foundInstance = false; if (CmsModelGroupHelper.isModelGroupResource(element.getResource())) { modelPage = getContainerPageBean(element.getResource()); CmsContainerElementBean baseElement = getModelBaseElement(modelPage); if (baseElement == null) { break; } String baseInstanceId = baseElement.getInstanceId(); String originalInstanceId = element.getInstanceId(); element = getModelReplacementElement(element, baseElement, true); List modelContainers = readModelContainers( baseInstanceId, originalInstanceId, modelPage); if (!m_isEditingModelGroups && baseElement.isCopyModel()) { modelContainers = createNewElementsForModelGroup(m_cms, modelContainers, locale); } modelContainers.addAll(page.getContainers().values()); page = new CmsContainerPageBean(modelContainers); // update the entry element value, as the settings will have changed entry.setValue(element); // also update the session cache m_sessionCache.setCacheContainerElement(element.editorHash(), element); } else { // here we need to make sure to remove the source container page setting and to set a new element instance id Map settings = new HashMap(element.getIndividualSettings()); String source = settings.get(CmsContainerpageService.SOURCE_CONTAINERPAGE_ID_SETTING); settings.remove(CmsContainerpageService.SOURCE_CONTAINERPAGE_ID_SETTING); if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(source)) { try { CmsUUID sourceId = new CmsUUID(source); CmsResource sourcePage = m_cms.readResource(sourceId); if (CmsResourceTypeXmlContainerPage.isContainerPage(sourcePage)) { CmsXmlContainerPage xmlCnt = CmsXmlContainerPageFactory.unmarshal( m_cms, m_cms.readFile(sourcePage)); modelPage = xmlCnt.getContainerPage(m_cms); modelInstanceId = element.getInstanceId(); } settings.remove(CmsContainerElement.ELEMENT_INSTANCE_ID); element = CmsContainerElementBean.cloneWithSettings(element, settings); if (modelPage != null) { Map> containerByParent = new HashMap>(); for (CmsContainerBean container : modelPage.getContainers().values()) { if (container.getParentInstanceId() != null) { if (!containerByParent.containsKey(container.getParentInstanceId())) { containerByParent.put( container.getParentInstanceId(), new ArrayList()); } containerByParent.get(container.getParentInstanceId()).add(container); } if (!foundInstance) { for (CmsContainerElementBean child : container.getElements()) { if (modelInstanceId == null) { if (child.getId().equals(element.getId())) { modelInstanceId = child.getInstanceId(); foundInstance = true; // we also want to keep the settings of the model group Map setting = new HashMap( child.getIndividualSettings()); setting.remove(CmsContainerElement.ELEMENT_INSTANCE_ID); element = CmsContainerElementBean.cloneWithSettings(element, setting); break; } } else { if (modelInstanceId.equals(child.getInstanceId())) { foundInstance = true; break; } } } } } if (foundInstance && containerByParent.containsKey(modelInstanceId)) { List modelContainers = collectModelStructure( modelInstanceId, element.getInstanceId(), containerByParent); modelContainers = createNewElementsForModelGroup(m_cms, modelContainers, locale); modelContainers.addAll(page.getContainers().values()); page = new CmsContainerPageBean(modelContainers); } } // update the entry element value, as the settings will have changed entry.setValue(element); // also update the session cache m_sessionCache.setCacheContainerElement(element.editorHash(), element); } catch (Exception e) { LOG.info(e.getLocalizedMessage(), e); } } } } return page; } /** * Reads the present model groups and merges their containers into the page.

* * @param page the container page * * @return the resulting container page */ public CmsContainerPageBean readModelGroups(CmsContainerPageBean page) { List resultContainers = new ArrayList(); for (CmsContainerBean container : page.getContainers().values()) { boolean hasModels = false; List elements = new ArrayList(); for (CmsContainerElementBean element : container.getElements()) { try { element.initResource(m_cms); if (isModelGroupResource(element.getResource())) { hasModels = true; CmsContainerPageBean modelGroupPage = getContainerPageBean(element.getResource()); CmsContainerElementBean baseElement = getModelBaseElement(modelGroupPage); if (baseElement == null) { break; } String baseInstanceId = baseElement.getInstanceId(); CmsContainerElementBean replaceElement = getModelReplacementElement( element, baseElement, false); m_sessionCache.setCacheContainerElement(replaceElement.editorHash(), replaceElement); elements.add(replaceElement); resultContainers.addAll( readModelContainers(baseInstanceId, element.getInstanceId(), modelGroupPage)); } else { elements.add(element); } } catch (CmsException e) { LOG.info(e.getLocalizedMessage(), e); } } if (hasModels) { resultContainers.add( new CmsContainerBean( container.getName(), container.getType(), container.getParentInstanceId(), container.getMaxElements(), elements)); } else { resultContainers.add(container); } } return new CmsContainerPageBean(resultContainers); } /** * Removes the model group containers.

* * @param page the container page state * * @return the container page without the model group containers */ public CmsContainerPageBean removeModelGroupContainers(CmsContainerPageBean page) { Map> containersByParent = getContainerByParent(page); Set modelInstances = new HashSet(); for (CmsContainerElementBean element : page.getElements()) { if (element.getIndividualSettings().containsKey(CmsContainerElement.MODEL_GROUP_ID)) { modelInstances.add(element.getInstanceId()); } } Set descendingInstances = new HashSet(); for (String modelInstance : modelInstances) { descendingInstances.addAll(collectDescendingInstances(modelInstance, containersByParent)); } List containers = new ArrayList(); for (CmsContainerBean container : page.getContainers().values()) { if ((container.getParentInstanceId() == null) || !descendingInstances.contains(container.getParentInstanceId())) { // iterate the container elements to replace the model group elements List elements = new ArrayList(); for (CmsContainerElementBean element : container.getElements()) { if (modelInstances.contains(element.getInstanceId())) { CmsUUID modelId = new CmsUUID( element.getIndividualSettings().get(CmsContainerElement.MODEL_GROUP_ID)); CmsContainerElementBean replacer = new CmsContainerElementBean( modelId, element.getFormatterId(), element.getIndividualSettings(), false); elements.add(replacer); } else { elements.add(element); } } containers.add( new CmsContainerBean( container.getName(), container.getType(), container.getParentInstanceId(), container.getMaxElements(), elements)); } } return new CmsContainerPageBean(containers); } /** * Saves the model groups of the given container page.

* * @param page the container page * * @return the container page referencing the saved model groups */ public CmsContainerPageBean saveModelGroups(CmsContainerPageBean page) { Map> containersByParent = getContainerByParent(page); Map modelInstances = new HashMap(); Set descendingInstances = new HashSet(); for (CmsContainerElementBean element : page.getElements()) { String modelGroupId = null; if (element.getIndividualSettings().containsKey(CmsContainerElement.MODEL_GROUP_ID) || element.isModelGroup()) { modelGroupId = element.getIndividualSettings().get(CmsContainerElement.MODEL_GROUP_ID); modelInstances.put(element.getInstanceId(), modelGroupId); Set childInstances = collectDescendingInstances(element.getInstanceId(), containersByParent); descendingInstances.addAll(childInstances); CmsResource modelGroup = null; try { modelGroup = m_cms.readResource(new CmsUUID(modelGroupId)); ensureLock(modelGroup); String title = element.getIndividualSettings().get(CmsContainerElement.MODEL_GROUP_TITLE); String description = element.getIndividualSettings().get( CmsContainerElement.MODEL_GROUP_DESCRIPTION); String groupType = ""; if (Boolean.valueOf( element.getIndividualSettings().get(CmsContainerElement.USE_AS_COPY_MODEL)).booleanValue()) { groupType = CmsContainerElement.USE_AS_COPY_MODEL; } List props = new ArrayList(); props.add(new CmsProperty(CmsPropertyDefinition.PROPERTY_TITLE, title, title)); props.add(new CmsProperty(CmsPropertyDefinition.PROPERTY_DESCRIPTION, description, description)); props.add(new CmsProperty(CmsPropertyDefinition.PROPERTY_TEMPLATE_ELEMENTS, groupType, groupType)); m_cms.writePropertyObjects(modelGroup, props); List modelContainers = new ArrayList(); CmsContainerElementBean baseElement = element.clone(); CmsContainerBean baseContainer = new CmsContainerBean( MODEL_GROUP_BASE_CONTAINER, MODEL_GROUP_BASE_CONTAINER, null, Collections.singletonList(baseElement)); modelContainers.add(baseContainer); for (String childInstance : childInstances) { if (containersByParent.containsKey(childInstance)) { modelContainers.addAll(containersByParent.get(childInstance)); } } CmsContainerPageBean modelPage = new CmsContainerPageBean(modelContainers); CmsXmlContainerPage xmlCnt = CmsXmlContainerPageFactory.unmarshal( m_cms, m_cms.readFile(modelGroup)); xmlCnt.save(m_cms, modelPage); tryUnlock(modelGroup); } catch (CmsException e) { LOG.error("Error saving model group resource.", e); } } } List containers = new ArrayList(); for (CmsContainerBean container : page.getContainers().values()) { if ((container.getParentInstanceId() == null) || !descendingInstances.contains(container.getParentInstanceId())) { // iterate the container elements to replace the model group elements List elements = new ArrayList(); for (CmsContainerElementBean element : container.getElements()) { if (modelInstances.containsKey(element.getInstanceId())) { CmsUUID modelId = new CmsUUID(modelInstances.get(element.getInstanceId())); CmsContainerElementBean replacer = new CmsContainerElementBean( modelId, element.getFormatterId(), element.getIndividualSettings(), false); elements.add(replacer); } else { elements.add(element); } } containers.add( new CmsContainerBean( container.getName(), container.getType(), container.getParentInstanceId(), container.getMaxElements(), elements)); } } return new CmsContainerPageBean(containers); } /** * Adjusts formatter settings and initializes a new instance id for the given container element.

* * @param element the container element * @param originalContainer the original parent container name * @param adjustedContainer the target container name * * @return the new element instance */ private CmsContainerElementBean adjustSettings( CmsContainerElementBean element, String originalContainer, String adjustedContainer) { Map settings = new HashMap(element.getIndividualSettings()); settings.put(CmsContainerElement.ELEMENT_INSTANCE_ID, new CmsUUID().toString()); String formatterId = settings.remove(CmsFormatterConfig.getSettingsKeyForContainer(originalContainer)); settings.put(CmsFormatterConfig.getSettingsKeyForContainer(adjustedContainer), formatterId); return CmsContainerElementBean.cloneWithSettings(element, settings); } /** * Returns the descending instance id's to the given element instance.

* * @param instanceId the instance id * @param containersByParent the container page containers by parent instance id * * @return the containers */ private Set collectDescendingInstances( String instanceId, Map> containersByParent) { Set descendingInstances = new HashSet(); descendingInstances.add(instanceId); if (containersByParent.containsKey(instanceId)) { for (CmsContainerBean container : containersByParent.get(instanceId)) { for (CmsContainerElementBean element : container.getElements()) { descendingInstances.addAll(collectDescendingInstances(element.getInstanceId(), containersByParent)); } } } return descendingInstances; } /** * Collects the model group structure.

* * @param modelInstanceId the model instance id * @param replaceModelId the local instance id * @param containerByParent the model group page containers by parent instance id * * @return the collected containers */ private List collectModelStructure( String modelInstanceId, String replaceModelId, Map> containerByParent) { List result = new ArrayList(); if (containerByParent.containsKey(modelInstanceId)) { for (CmsContainerBean container : containerByParent.get(modelInstanceId)) { String adjustedContainerName = replaceModelId + container.getName().substring(modelInstanceId.length()); List elements = new ArrayList(); for (CmsContainerElementBean element : container.getElements()) { CmsContainerElementBean copyElement = adjustSettings( element, container.getName(), adjustedContainerName); m_sessionCache.setCacheContainerElement(copyElement.editorHash(), copyElement); elements.add(copyElement); result.addAll( collectModelStructure(element.getInstanceId(), copyElement.getInstanceId(), containerByParent)); } result.add( new CmsContainerBean( adjustedContainerName, container.getType(), replaceModelId, container.getMaxElements(), elements)); } } return result; } /** * Creates new resources for elements marked with create as new.

* * @param cms the cms context * @param modelContainers the model containers * @param locale the content locale * * @return the updated model containers * * @throws CmsException in case something goes wrong */ private List createNewElementsForModelGroup( CmsObject cms, List modelContainers, Locale locale) throws CmsException { Map newResources = new HashMap(); CmsObject cloneCms = OpenCms.initCmsObject(cms); cloneCms.getRequestContext().setLocale(locale); for (CmsContainerBean container : modelContainers) { for (CmsContainerElementBean element : container.getElements()) { if (element.isCreateNew() && !newResources.containsKey(element.getId())) { element.initResource(cms); String typeName = OpenCms.getResourceManager().getResourceType(element.getResource()).getTypeName(); CmsResourceTypeConfig typeConfig = m_configData.getResourceType(typeName); if (typeConfig == null) { throw new IllegalArgumentException( "Can not copy template model element '" + element.getResource().getRootPath() + "' because the resource type '" + typeName + "' is not available in this sitemap."); } CmsResource newResource = typeConfig.createNewElement( cloneCms, element.getResource(), m_configData.getBasePath()); newResources.put(element.getId(), newResource); } } } if (!newResources.isEmpty()) { List updatedContainers = new ArrayList(); for (CmsContainerBean container : modelContainers) { List updatedElements = new ArrayList(); for (CmsContainerElementBean element : container.getElements()) { if (newResources.containsKey(element.getId())) { CmsContainerElementBean newBean = new CmsContainerElementBean( newResources.get(element.getId()).getStructureId(), element.getFormatterId(), element.getIndividualSettings(), false); updatedElements.add(newBean); } else { updatedElements.add(element); } } CmsContainerBean updatedContainer = new CmsContainerBean( container.getName(), container.getType(), container.getParentInstanceId(), container.getMaxElements(), updatedElements); updatedContainers.add(updatedContainer); } modelContainers = updatedContainers; } return modelContainers; } /** * Locks the given resource.

* * @param resource the resource to lock * * @throws CmsException in case locking fails */ private void ensureLock(CmsResource resource) throws CmsException { CmsUser user = m_cms.getRequestContext().getCurrentUser(); CmsLock lock = m_cms.getLock(resource); if (!lock.isOwnedBy(user)) { m_cms.lockResourceTemporary(resource); } else if (!lock.isOwnedInProjectBy(user, m_cms.getRequestContext().getCurrentProject())) { m_cms.changeLock(resource); } } /** * Collects the page containers by parent instance id * * @param page the page * * @return the containers by parent id */ private Map> getContainerByParent(CmsContainerPageBean page) { Map> containerByParent = new HashMap>(); for (CmsContainerBean container : page.getContainers().values()) { if (container.getParentInstanceId() != null) { if (!containerByParent.containsKey(container.getParentInstanceId())) { containerByParent.put(container.getParentInstanceId(), new ArrayList()); } containerByParent.get(container.getParentInstanceId()).add(container); } } return containerByParent; } /** * Unmarshals the given resource.

* * @param resource the resource * * @return the container page bean * * @throws CmsException in case unmarshalling fails */ private CmsContainerPageBean getContainerPageBean(CmsResource resource) throws CmsException { CmsXmlContainerPage xmlCnt = CmsXmlContainerPageFactory.unmarshal(m_cms, m_cms.readFile(resource)); return xmlCnt.getContainerPage(m_cms); } /** * Returns the model group base element.

* * @param modelGroupPage the model group page * * @return the base element */ private CmsContainerElementBean getModelBaseElement(CmsContainerPageBean modelGroupPage) { CmsContainerBean container = modelGroupPage.getContainers().get(MODEL_GROUP_BASE_CONTAINER); return container != null ? container.getElements().get(0) : null; } /** * Returns the the element to be rendered as the model group base.

* * @param element the original element * @param baseElement the model group base * @param allowCopyModel if copy models are allowed * * @return the element */ private CmsContainerElementBean getModelReplacementElement( CmsContainerElementBean element, CmsContainerElementBean baseElement, boolean allowCopyModel) { Map settings = new HashMap(element.getIndividualSettings()); if (m_isEditingModelGroups || !(baseElement.isCopyModel() && allowCopyModel)) { // skip the model id in case of copy models settings.put(CmsContainerElement.MODEL_GROUP_ID, element.getId().toString()); try { CmsProperty titleProp = m_cms.readPropertyObject( element.getResource(), CmsPropertyDefinition.PROPERTY_TITLE, false); settings.put(CmsContainerElement.MODEL_GROUP_TITLE, titleProp.getValue()); CmsProperty descProp = m_cms.readPropertyObject( element.getResource(), CmsPropertyDefinition.PROPERTY_DESCRIPTION, false); settings.put(CmsContainerElement.MODEL_GROUP_DESCRIPTION, descProp.getValue()); } catch (CmsException e) { LOG.error(e.getLocalizedMessage(), e); } if (allowCopyModel) { // transfer all other settings for (Entry settingEntry : baseElement.getIndividualSettings().entrySet()) { if (!settings.containsKey(settingEntry.getKey())) { settings.put(settingEntry.getKey(), settingEntry.getValue()); } } } } else if (baseElement.isCopyModel()) { settings.put(CmsContainerElement.MODEL_GROUP_STATE, ModelGroupState.wasModelGroup.name()); } return CmsContainerElementBean.cloneWithSettings(baseElement, settings); } /** * Returns the model containers.

* * @param modelInstanceId the model instance id * @param localInstanceId the local instance id * @param modelPage the model page bean * * @return the model group containers */ private List readModelContainers( String modelInstanceId, String localInstanceId, CmsContainerPageBean modelPage) { Map> containerByParent = getContainerByParent(modelPage); List modelContainers; if (containerByParent.containsKey(modelInstanceId)) { modelContainers = collectModelStructure(modelInstanceId, localInstanceId, containerByParent); } else { modelContainers = Collections.emptyList(); } return modelContainers; } /** * Tries to unlock a resource.

* * @param resource the resource to unlock */ private void tryUnlock(CmsResource resource) { try { m_cms.unlockResource(resource); } catch (CmsException e) { LOG.debug("Unable to unlock " + resource.getRootPath(), e); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy