001/*
002 *  Copyright 2013 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.cms.workflow.copy;
017
018import java.util.Map;
019
020import org.apache.avalon.framework.service.ServiceException;
021import org.apache.avalon.framework.service.ServiceManager;
022
023import org.ametys.cms.content.CopyContentMetadataComponent;
024import org.ametys.cms.content.CopyReport;
025import org.ametys.cms.content.CopyReport.CopyMode;
026import org.ametys.cms.contenttype.ContentTypesHelper;
027import org.ametys.cms.repository.Content;
028import org.ametys.cms.repository.ModifiableContent;
029import org.ametys.cms.workflow.CreateContentFunction;
030import org.ametys.core.util.I18nUtils;
031import org.ametys.plugins.repository.UnknownAmetysObjectException;
032import org.ametys.runtime.i18n.I18nizableText;
033
034import com.opensymphony.module.propertyset.PropertySet;
035import com.opensymphony.workflow.WorkflowException;
036
037/**
038 * OSWorkflow function to create a content by copy of another
039 * 
040 * The required transient variables:
041 * - CreateContentByCopyFunction.BASE_CONTENT_KEY - Content The content that will be used for duplication.
042 * - or CreateContentByCopyFunction.BASE_CONTENT_ID - String The id of content The content that will be used for duplication.
043 * 
044 * - CreateContentByCopyFunction.COPY_MAP_KEY - Map<String, Object> The map of properties to copy. Can be null if CreateContentByCopyFunction.COPY_METADATASET_NAME is used
045 */
046public class CreateContentByCopyFunction extends CreateContentFunction
047{
048    /** Constant for storing the base content used for the duplication into the transient variables map. */
049    public static final String BASE_CONTENT_KEY = CreateContentByCopyFunction.class.getName() + "$baseContent";
050    
051    /** Constant for storing the id of base content used for the duplication into the transient variables map. */
052    public static final String BASE_CONTENT_ID = CreateContentByCopyFunction.class.getName() + "$baseContentId";
053    
054    /** Constant for storing the map containing the duplication info into the transient variables map. Can be null.*/
055    public static final String COPY_MAP_KEY = CreateContentByCopyFunction.class.getName() + "$copyProperties";
056    
057    /** Constant for storing the copy report object into the transient variables map. Can be null. */
058    public static final String COPY_REPORT_KEY = CreateContentByCopyFunction.class.getName() + "$copyReport";
059    
060    /** Constant for storing the name of metadata set to use for copy. */
061    public static final String COPY_METADATASET_NAME = CreateContentByCopyFunction.class.getName() + "$metadataSetName";
062    /** Constant for storing the type of metadata set to use for copy. */
063    public static final String COPY_METADATASET_TYPE = CreateContentByCopyFunction.class.getName() + "$metadataSetType";
064
065    /** The metadata copy component */
066    protected CopyContentMetadataComponent _copyContentMetadataHelper;
067    /** The content type helper */
068    protected ContentTypesHelper _cTypesHelper;
069
070    /** I18n Utils */
071    protected I18nUtils _i18nUtils;
072
073    @Override
074    public void service(ServiceManager manager) throws ServiceException
075    {
076        super.service(manager);
077        _copyContentMetadataHelper = (CopyContentMetadataComponent) manager.lookup(CopyContentMetadataComponent.ROLE);
078        _cTypesHelper = (ContentTypesHelper) manager.lookup(ContentTypesHelper.ROLE);
079        _i18nUtils = (I18nUtils) manager.lookup(I18nUtils.ROLE);
080    }
081    
082    @SuppressWarnings("cast")
083    @Override
084    public void execute(Map transientVars, Map args, PropertySet ps) throws WorkflowException
085    {
086        // Preparation of the transientVars to work with the super method (CreateContentFunction).
087        Content baseContent = getBaseContentForCopy(transientVars);
088        
089        if (baseContent == null)
090        {
091            throw new WorkflowException("Unable to retrieve the base content for the duplication.");
092        }
093        
094        if (transientVars.get(CreateContentFunction.CONTENT_TITLE_KEY) == null)
095        {
096            transientVars.put(CreateContentFunction.CONTENT_NAME_KEY, baseContent.getTitle());
097            // If title is not set, the base title is set with a copy suffix. 
098            transientVars.put(CreateContentFunction.CONTENT_TITLE_KEY, baseContent.getTitle() + _i18nUtils.translate(new I18nizableText("plugin.cms", "CONTENT_COPY_CREATE_CONTENT_TITLE_SUFFIX")));
099        }
100        else
101        {
102            transientVars.put(CreateContentFunction.CONTENT_NAME_KEY, (String) transientVars.get(CreateContentFunction.CONTENT_TITLE_KEY));
103        }
104        
105        if (transientVars.get(CreateContentFunction.CONTENT_TYPES_KEY) == null)
106        {
107            transientVars.put(CreateContentFunction.CONTENT_TYPES_KEY, baseContent.getTypes());
108        }
109        
110        transientVars.put(CreateContentFunction.CONTENT_MIXINS_KEY, baseContent.getMixinTypes());
111        transientVars.put(CreateContentFunction.CONTENT_LANGUAGE_KEY, baseContent.getLanguage());
112        
113        // Super method call.
114        super.execute(transientVars, args, ps);
115    }
116    
117    /**
118     * Get the content
119     * @param transientVars The workflow transiant vars with BASE_CONTENT_KEY (the content itself) or BASE_CONTENT_ID (the id of the content)
120     * @return the content or null if the object cannot be found
121     */
122    protected Content getBaseContentForCopy (Map transientVars)
123    {
124        Content baseContent = (Content) transientVars.get(BASE_CONTENT_KEY);
125        
126        if (baseContent == null)
127        {
128            String baseContentId = (String) transientVars.get(BASE_CONTENT_ID);
129            
130            try
131            {
132                baseContent = _resolver.resolveById(baseContentId);
133            }
134            catch (UnknownAmetysObjectException e)
135            {
136                return null;
137            }
138        }
139        
140        return baseContent;
141    }
142
143    @SuppressWarnings("unchecked")
144    @Override
145    protected void _populateAdditionalData(Map transientVars, ModifiableContent content) throws WorkflowException
146    {
147        super._populateAdditionalData(transientVars, content);
148        
149        // This is where the duplication process is made. After the new content has been created.
150        Content baseContent = getBaseContentForCopy(transientVars);
151        
152        String metadataSetName = (String) transientVars.get(COPY_METADATASET_NAME);
153        String metadataSetType = (String) transientVars.get(COPY_METADATASET_TYPE);
154        
155        if (!transientVars.containsKey(COPY_REPORT_KEY))
156        {
157            transientVars.put(COPY_REPORT_KEY, new CopyReport(baseContent.getId(), baseContent.getTitle(), true, metadataSetName != null ? metadataSetName : "main", metadataSetType != null ? metadataSetType : "edition", CopyMode.CREATION));
158        }
159        CopyReport copyReport = (CopyReport) transientVars.get(COPY_REPORT_KEY);
160        
161        Map<String, Object> copyMap = (Map<String, Object>) transientVars.get(COPY_MAP_KEY);
162        if (copyMap == null)
163        {
164            copyMap = _copyContentMetadataHelper.buildCopyMap(baseContent, metadataSetName != null ? metadataSetName : "main", metadataSetType != null ? metadataSetType : "edition");
165        }
166        
167        _copyContentMetadataHelper.copyMetadataMap(baseContent, content, copyMap, copyReport);
168    }
169}