001/* 002 * Copyright 2014 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.clientsideelement; 017 018import java.util.ArrayList; 019import java.util.Date; 020import java.util.HashMap; 021import java.util.HashSet; 022import java.util.List; 023import java.util.Map; 024import java.util.Set; 025 026import org.apache.avalon.framework.service.ServiceException; 027import org.apache.avalon.framework.service.ServiceManager; 028import org.apache.commons.lang3.StringUtils; 029 030import org.ametys.cms.ObservationConstants; 031import org.ametys.cms.alerts.AlertsConstants; 032import org.ametys.cms.content.archive.ArchiveConstants; 033import org.ametys.cms.repository.Content; 034import org.ametys.core.observation.Event; 035import org.ametys.core.observation.ObservationManager; 036import org.ametys.core.ui.Callable; 037import org.ametys.core.ui.StaticClientSideElement; 038import org.ametys.plugins.repository.AmetysObjectResolver; 039import org.ametys.plugins.repository.metadata.ModifiableCompositeMetadata; 040import org.ametys.plugins.repository.version.ModifiableMetadataAwareVersionableAmetysObject; 041import org.ametys.runtime.config.Config; 042import org.ametys.runtime.i18n.I18nizableText; 043import org.ametys.runtime.parameter.ParameterHelper; 044import org.ametys.runtime.parameter.ParameterHelper.ParameterType; 045 046/** 047 * This element creates a ribbon button to schedule the archiving of a content 048 */ 049public class ScheduleArchivingClientSideElement extends StaticClientSideElement 050{ 051 /** I18n error key : content type error */ 052 private static final String __I18N_KEY_CONTENT_TYPE_ERROR = "PLUGINS_CMS_ARCHIVE_SCHEDULE_CONTENT_TYPE_ERROR"; 053 054 /** I18n error key : unexpected error */ 055 private static final String __I18N_KEY_UNEXPECTED_ERROR = "PLUGINS_CMS_ARCHIVE_SCHEDULE_UNEXPECTED_ERROR"; 056 057 private ObservationManager _observationManager; 058 private AmetysObjectResolver _resolver; 059 060 @Override 061 public void service(ServiceManager manager) throws ServiceException 062 { 063 super.service(manager); 064 _observationManager = (ObservationManager) manager.lookup(ObservationManager.ROLE); 065 _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 066 } 067 068 /** 069 * Set or remove the <code>ArchiveConstants.META_ARCHIVE_SCHEDULED_DATE</code> on a content. 070 * @param contentIds The ids of contents 071 * @param scheduledDateAsStr The schedule date as string 072 * @return the successful and failed contents 073 */ 074 @Callable 075 public Map<String, Object> setScheduledArchivingDate (List<String> contentIds, String scheduledDateAsStr) 076 { 077 Map<String, Object> results = new HashMap<>(); 078 079 // Error list 080 List<I18nizableText> failedContents = new ArrayList<>(); 081 082 // Success list, containing the contentId that have been successfully scheduled 083 List<String> successContents = new ArrayList<>(); 084 085 Date scheduledDate = (Date) ParameterHelper.castValue(scheduledDateAsStr, ParameterType.DATE); 086 087 if (StringUtils.isNotEmpty(scheduledDateAsStr)) 088 { 089 if (scheduledDate == null) 090 { 091 getLogger().error("Cannot cast value '" + scheduledDate + "' into type 'date'"); 092 throw new IllegalArgumentException("Invalid format for date value '" + scheduledDate + "'"); 093 } 094 095 // Date must be set at least after tomorrow 096 /*if (scheduledDate.compareTo(new DateMidnight().plusDays(1).toDate()) < 0) 097 { 098 getLogger().error("The scheduled date '" + scheduledDate + "' cannot be set before the current date"); 099 throw new IllegalArgumentException("The scheduled date '" + scheduledDate + "' cannot be set before the current date"); 100 }*/ 101 } 102 103 // For each content 104 for (String contentId : contentIds) 105 { 106 try 107 { 108 Content content = _resolver.resolveById(contentId); 109 110 if (content instanceof ModifiableMetadataAwareVersionableAmetysObject) 111 { 112 ModifiableMetadataAwareVersionableAmetysObject uContent = (ModifiableMetadataAwareVersionableAmetysObject) content; 113 ModifiableCompositeMetadata metadata = uContent.getUnversionedMetadataHolder(); 114 115 // Remove META_ARCHIVE_SCHEDULED_DATE and 116 // SCHEDULED_ARCHIVING_REMINDER_LAST_DATE if date is empty. 117 if (StringUtils.isEmpty(scheduledDateAsStr)) 118 { 119 if (metadata.hasMetadata(ArchiveConstants.META_ARCHIVE_SCHEDULED_DATE)) 120 { 121 metadata.removeMetadata(ArchiveConstants.META_ARCHIVE_SCHEDULED_DATE); 122 123 if (getLogger().isInfoEnabled()) 124 { 125 getLogger().info("Content with id : '" + uContent.getId() + "' does not have a scheduled archiving date anymore."); 126 } 127 } 128 129 if (metadata.hasMetadata(AlertsConstants.SCHEDULED_ARCHIVING_REMINDER_LAST_DATE)) 130 { 131 metadata.removeMetadata(AlertsConstants.SCHEDULED_ARCHIVING_REMINDER_LAST_DATE); 132 } 133 } 134 else 135 { 136 metadata.setMetadata(ArchiveConstants.META_ARCHIVE_SCHEDULED_DATE, scheduledDate); 137 } 138 139 if (uContent.needsSave()) 140 { 141 uContent.saveChanges(); 142 143 // report success 144 successContents.add(uContent.getId()); 145 146 // Notify observer 147 Map<String, Object> eventParams = new HashMap<>(); 148 eventParams.put(ObservationConstants.ARGS_CONTENT, content); 149 eventParams.put(ObservationConstants.ARGS_CONTENT_ID, contentId); 150 151 _observationManager.notify(new Event(ObservationConstants.EVENT_CONTENT_MODIFIED, _currentUserProvider.getUser(), eventParams)); 152 } 153 } 154 else 155 { 156 getLogger().error("Unable to set a scheduled archiving for the content : '" + content.getId() + "'. It is not a ModifiableMetadataAwareVersionableAmetysObject."); 157 158 // report error 159 List<String> i18nParams = new ArrayList<>(); 160 i18nParams.add(content.getTitle()); 161 failedContents.add(new I18nizableText("plugin.cms", __I18N_KEY_CONTENT_TYPE_ERROR, i18nParams)); 162 163 } 164 } 165 catch (Exception e) 166 { 167 getLogger().error("Unexpected exception while trying to schedule an archiving for the content : '" + contentId + "'."); 168 169 // report error 170 List<String> i18nParams = new ArrayList<>(); 171 i18nParams.add(contentId); 172 failedContents.add(new I18nizableText("plugin.cms", __I18N_KEY_UNEXPECTED_ERROR, i18nParams)); 173 } 174 } 175 176 results.put("error", failedContents); 177 results.put("success", successContents); 178 179 return results; 180 } 181 182 /** 183 * Gets the scheduled archiving dates of one or several contents 184 * @param contentIds the ids of the contents 185 * @return result the server's response in JSON 186 */ 187 @Callable 188 public Map<String, Object> getScheduledArchivingDate(List<String> contentIds) 189 { 190 Map<String, Object> results = new HashMap<> (); 191 Set<Date> dates = new HashSet<>(); 192 193 // Retrieves the date for each content 194 for (String contentId : contentIds) 195 { 196 Content content = _resolver.resolveById(contentId); 197 198 if (content instanceof ModifiableMetadataAwareVersionableAmetysObject) 199 { 200 Date date = ((ModifiableMetadataAwareVersionableAmetysObject) content).getUnversionedMetadataHolder().getDate(ArchiveConstants.META_ARCHIVE_SCHEDULED_DATE, null); 201 dates.add(date); 202 } 203 } 204 205 // Retrieves the closest date from current time. 206 dates.remove(null); 207 Date scheduledDate = getDateNearestToCurrent(dates); 208 209 // Generate the JSON 210 Map<String, Object> content = new HashMap<> (); 211 if (scheduledDate != null) 212 { 213 content.put("date", ParameterHelper.valueToString(scheduledDate)); 214 } 215 results.put("content", content); 216 217 return results; 218 } 219 220 private Date getDateNearestToCurrent(Set<Date> dates) 221 { 222 Date returnDate = null; 223 Date currentDate = new Date(); 224 225 for (Date date : dates) 226 { 227 if (date.compareTo(currentDate) >= 0 && (returnDate == null || date.compareTo(returnDate) < 0)) 228 { 229 returnDate = date; 230 } 231 } 232 return returnDate; 233 } 234 235 @Override 236 public List<Script> getScripts(boolean ignoreRights, Map<String, Object> contextParameters) 237 { 238 if (Config.getInstance().getValueAsBoolean("archive.scheduler.enabled")) 239 { 240 return super.getScripts(ignoreRights, contextParameters); 241 } 242 243 return new ArrayList<>(); 244 } 245}