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.HashMap; 019import java.util.Locale; 020import java.util.Map; 021import java.util.Map.Entry; 022 023import org.apache.avalon.framework.service.ServiceException; 024import org.apache.avalon.framework.service.ServiceManager; 025import org.apache.commons.lang3.StringUtils; 026 027import org.ametys.cms.content.CopyContentMetadataComponent; 028import org.ametys.cms.content.CopyReport; 029import org.ametys.cms.content.CopyReport.CopyMode; 030import org.ametys.cms.contenttype.ContentTypesHelper; 031import org.ametys.cms.repository.Content; 032import org.ametys.cms.repository.ModifiableContent; 033import org.ametys.cms.workflow.CreateContentFunction; 034import org.ametys.core.util.I18nUtils; 035import org.ametys.plugins.repository.UnknownAmetysObjectException; 036import org.ametys.runtime.i18n.I18nizableText; 037 038import com.opensymphony.module.propertyset.PropertySet; 039import com.opensymphony.workflow.WorkflowException; 040 041/** 042 * OSWorkflow function to create a content by copy of another 043 * 044 * The required transient variables: 045 * - CreateContentByCopyFunction.BASE_CONTENT_KEY - Content The content that will be used for duplication. 046 * - or CreateContentByCopyFunction.BASE_CONTENT_ID - String The id of content The content that will be used for duplication. 047 * 048 * - CreateContentByCopyFunction.COPY_MAP_KEY - Map<String, Object> The map of properties to copy. Can be null if CreateContentByCopyFunction.COPY_METADATASET_NAME is used 049 */ 050public class CreateContentByCopyFunction extends CreateContentFunction 051{ 052 /** Constant for storing the base content used for the duplication into the transient variables map. */ 053 public static final String BASE_CONTENT_KEY = CreateContentByCopyFunction.class.getName() + "$baseContent"; 054 055 /** Constant for storing the id of base content used for the duplication into the transient variables map. */ 056 public static final String BASE_CONTENT_ID = CreateContentByCopyFunction.class.getName() + "$baseContentId"; 057 058 /** Constant for storing the map containing the duplication info into the transient variables map. Can be null.*/ 059 public static final String COPY_MAP_KEY = CreateContentByCopyFunction.class.getName() + "$copyProperties"; 060 061 /** Constant for storing the copy report object into the transient variables map. Can be null. */ 062 public static final String COPY_REPORT_KEY = CreateContentByCopyFunction.class.getName() + "$copyReport"; 063 064 /** Constant for storing the name of metadata set to use for copy. */ 065 public static final String COPY_METADATASET_NAME = CreateContentByCopyFunction.class.getName() + "$metadataSetName"; 066 /** Constant for storing the type of metadata set to use for copy. */ 067 public static final String COPY_METADATASET_TYPE = CreateContentByCopyFunction.class.getName() + "$metadataSetType"; 068 069 /** The metadata copy component */ 070 protected CopyContentMetadataComponent _copyContentMetadataHelper; 071 /** The content type helper */ 072 protected ContentTypesHelper _cTypesHelper; 073 074 /** I18n Utils */ 075 protected I18nUtils _i18nUtils; 076 077 @Override 078 public void service(ServiceManager manager) throws ServiceException 079 { 080 super.service(manager); 081 _copyContentMetadataHelper = (CopyContentMetadataComponent) manager.lookup(CopyContentMetadataComponent.ROLE); 082 _cTypesHelper = (ContentTypesHelper) manager.lookup(ContentTypesHelper.ROLE); 083 _i18nUtils = (I18nUtils) manager.lookup(I18nUtils.ROLE); 084 } 085 086 @SuppressWarnings("cast") 087 @Override 088 public void execute(Map transientVars, Map args, PropertySet ps) throws WorkflowException 089 { 090 // Preparation of the transientVars to work with the super method (CreateContentFunction). 091 Content baseContent = getBaseContentForCopy(transientVars); 092 093 if (baseContent == null) 094 { 095 throw new WorkflowException("Unable to retrieve the base content for the duplication."); 096 } 097 098 if (transientVars.get(CreateContentFunction.CONTENT_TITLE_KEY) == null) 099 { 100 if (_contentHelper.isMultilingual(baseContent)) 101 { 102 Map<String, String> titleVariants = new HashMap<>(); 103 Map<String, String> baseTitleVariants = _contentHelper.getTitleVariants(baseContent); 104 105 for (Entry<String, String> entry : baseTitleVariants.entrySet()) 106 { 107 titleVariants.put(entry.getKey(), entry.getValue() + _i18nUtils.translate(new I18nizableText("plugin.cms", "CONTENT_COPY_CREATE_CONTENT_TITLE_SUFFIX"))); 108 } 109 110 String defaultLang = (String) transientVars.get(CreateContentFunction.CONTENT_LANGUAGE_KEY); 111 Locale defaultLocale = StringUtils.isNotEmpty(defaultLang) ? new Locale(defaultLang) : new Locale(titleVariants.keySet().iterator().next()); 112 transientVars.put(CreateContentFunction.CONTENT_NAME_KEY, baseContent.getTitle(defaultLocale)); 113 transientVars.put(CreateContentFunction.CONTENT_TITLE_VARIANTS_KEY, titleVariants); 114 } 115 else 116 { 117 transientVars.put(CreateContentFunction.CONTENT_NAME_KEY, baseContent.getTitle(null)); 118 // If title is not set, the base title is set with a copy suffix. 119 transientVars.put(CreateContentFunction.CONTENT_TITLE_KEY, baseContent.getTitle(null) + _i18nUtils.translate(new I18nizableText("plugin.cms", "CONTENT_COPY_CREATE_CONTENT_TITLE_SUFFIX"))); 120 } 121 } 122 else 123 { 124 transientVars.put(CreateContentFunction.CONTENT_NAME_KEY, (String) transientVars.get(CreateContentFunction.CONTENT_TITLE_KEY)); 125 } 126 127 if (transientVars.get(CreateContentFunction.CONTENT_TYPES_KEY) == null) 128 { 129 transientVars.put(CreateContentFunction.CONTENT_TYPES_KEY, baseContent.getTypes()); 130 } 131 132 transientVars.put(CreateContentFunction.CONTENT_MIXINS_KEY, baseContent.getMixinTypes()); 133 transientVars.put(CreateContentFunction.CONTENT_LANGUAGE_KEY, baseContent.getLanguage()); 134 135 // Super method call. 136 super.execute(transientVars, args, ps); 137 } 138 139 /** 140 * Get the content 141 * @param transientVars The workflow transiant vars with BASE_CONTENT_KEY (the content itself) or BASE_CONTENT_ID (the id of the content) 142 * @return the content or null if the object cannot be found 143 */ 144 protected Content getBaseContentForCopy (Map transientVars) 145 { 146 Content baseContent = (Content) transientVars.get(BASE_CONTENT_KEY); 147 148 if (baseContent == null) 149 { 150 String baseContentId = (String) transientVars.get(BASE_CONTENT_ID); 151 152 try 153 { 154 baseContent = _resolver.resolveById(baseContentId); 155 } 156 catch (UnknownAmetysObjectException e) 157 { 158 return null; 159 } 160 } 161 162 return baseContent; 163 } 164 165 @Override 166 protected void _populateAdditionalData(Map transientVars, ModifiableContent content) throws WorkflowException 167 { 168 super._populateAdditionalData(transientVars, content); 169 170 // This is where the duplication process is made. After the new content has been created. 171 Content baseContent = getBaseContentForCopy(transientVars); 172 173 String metadataSetName = (String) transientVars.get(COPY_METADATASET_NAME); 174 String metadataSetType = (String) transientVars.get(COPY_METADATASET_TYPE); 175 176 if (!transientVars.containsKey(COPY_REPORT_KEY)) 177 { 178 transientVars.put(COPY_REPORT_KEY, new CopyReport(baseContent.getId(), _contentHelper.getTitle(baseContent), true, metadataSetName != null ? metadataSetName : "main", metadataSetType != null ? metadataSetType : "edition", CopyMode.CREATION)); 179 } 180 CopyReport copyReport = (CopyReport) transientVars.get(COPY_REPORT_KEY); 181 182 Map<String, Object> copyMap = _buildCopyMap(transientVars, baseContent, metadataSetName, metadataSetType); 183 184 _copyContentMetadataHelper.copyMetadataMap(baseContent, content, copyMap, copyReport); 185 } 186 187 188 /** 189 * Get the builded copy map 190 * @param transientVars the vars 191 * @param baseContent the base content to be copied 192 * @param metadataSetName the metadata set name 193 * @param metadataSetType the metadata set type 194 * @return the builded copy map 195 */ 196 @SuppressWarnings("unchecked") 197 protected Map<String, Object> _buildCopyMap(Map transientVars, Content baseContent, String metadataSetName, String metadataSetType) 198 { 199 Map<String, Object> copyMap = (Map<String, Object>) transientVars.get(COPY_MAP_KEY); 200 if (copyMap == null) 201 { 202 copyMap = _copyContentMetadataHelper.buildCopyMap(baseContent, metadataSetName != null ? metadataSetName : "main", metadataSetType != null ? metadataSetType : "edition"); 203 } 204 205 return copyMap; 206 } 207}