001/* 002 * Copyright 2017 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.plugins.extraction.execution; 017 018import java.io.File; 019import java.util.HashMap; 020import java.util.LinkedHashMap; 021import java.util.List; 022import java.util.Map; 023import java.util.Map.Entry; 024 025import org.apache.avalon.framework.service.ServiceException; 026import org.apache.avalon.framework.service.ServiceManager; 027import org.apache.commons.lang.StringUtils; 028import org.apache.excalibur.source.Source; 029import org.apache.excalibur.source.SourceResolver; 030import org.apache.excalibur.source.impl.FileSource; 031import org.quartz.JobKey; 032import org.quartz.SchedulerException; 033 034import org.ametys.cms.contenttype.ContentType; 035import org.ametys.cms.contenttype.ContentTypeExtensionPoint; 036import org.ametys.core.schedule.Runnable; 037import org.ametys.core.ui.Callable; 038import org.ametys.core.ui.StaticClientSideElement; 039import org.ametys.core.user.User; 040import org.ametys.core.user.UserIdentity; 041import org.ametys.core.user.UserManager; 042import org.ametys.core.util.JSONUtils; 043import org.ametys.plugins.core.schedule.Scheduler; 044import org.ametys.plugins.extraction.ExtractionConstants; 045import org.ametys.plugins.extraction.execution.pipeline.PipelineManager; 046import org.ametys.runtime.i18n.I18nizableText; 047 048/** 049 * This client site element creates a button to execute an extraction 050 */ 051public class ExecuteExtractionClientSideElement extends StaticClientSideElement 052{ 053 private UserManager _userManager; 054 private ExtractionDefinitionReader _reader; 055 private SourceResolver _sourceResolver; 056 private JSONUtils _jsonUtils; 057 private Scheduler _scheduler; 058 private PipelineManager _pipelineManager; 059 private ContentTypeExtensionPoint _contentTypeExtensionPoint; 060 061 @Override 062 public void service(ServiceManager serviceManager) throws ServiceException 063 { 064 super.service(serviceManager); 065 _userManager = (UserManager) serviceManager.lookup(UserManager.ROLE); 066 _reader = (ExtractionDefinitionReader) serviceManager.lookup(ExtractionDefinitionReader.ROLE); 067 _sourceResolver = (SourceResolver) serviceManager.lookup(SourceResolver.ROLE); 068 _jsonUtils = (JSONUtils) serviceManager.lookup(JSONUtils.ROLE); 069 _scheduler = (Scheduler) serviceManager.lookup(Scheduler.ROLE); 070 _pipelineManager = (PipelineManager) serviceManager.lookup(PipelineManager.ROLE); 071 _contentTypeExtensionPoint = (ContentTypeExtensionPoint) serviceManager.lookup(ContentTypeExtensionPoint.ROLE); 072 } 073 074 /** 075 * Retrieve needed extraction parameters. 076 * @param definitionFile The extraction definition file path 077 * @return a <code>Map</code> containing parameters infos used to configure form to fill the parameters 078 * @throws Exception if an error occurs 079 */ 080 @Callable (right = ExtractionConstants.EXECUTE_EXTRACTION_RIGHT_ID) 081 public Map<String, Object> getExecutionParameters(String definitionFile) throws Exception 082 { 083 Map<String, Object> executionParameters = new LinkedHashMap<>(); 084 085 String definitionFilePath = ExtractionConstants.DEFINITIONS_DIR + definitionFile; 086 Source src = _sourceResolver.resolveURI(definitionFilePath); 087 File file = ((FileSource) src).getFile(); 088 089 if (!file.exists()) 090 { 091 throw new IllegalArgumentException("The file " + definitionFilePath + " does not exist."); 092 } 093 094 executionParameters.put("pipeline", _getPipelineInputConfig(definitionFile)); 095 096 Extraction extraction = _reader.readExtractionDefinitionFile(file); 097 098 Map<String, String> clasuesVariables = extraction.getQueryVariablesNamesAndContentTypes(); 099 List<String> optionalColumns = extraction.getDisplayOptionalColumnsNames(); 100 101 if (!clasuesVariables.isEmpty()) 102 { 103 Map<String, Object> clausesVariablesFieldSet = new HashMap<>(); 104 clausesVariablesFieldSet.put("role", "fieldset"); 105 clausesVariablesFieldSet.put("label", new I18nizableText(ExtractionConstants.PLUGIN_NAME, "PLUGINS_EXTRACTION_EXECUTE_EXTRACTION_CLAUSES_VARIABLES_FIELDSET_LABEL")); 106 107 Map<String, Object> clausesVariablesFieldSetElements = new HashMap<>(); 108 for (Map.Entry<String, String> clausesVariable : clasuesVariables.entrySet()) 109 { 110 clausesVariablesFieldSetElements.put(clausesVariable.getKey(), _getClauseVariableInputConfig(clausesVariable)); 111 } 112 clausesVariablesFieldSet.put("elements", clausesVariablesFieldSetElements); 113 114 executionParameters.put("clausesVariables", clausesVariablesFieldSet); 115 } 116 117 if (!optionalColumns.isEmpty()) 118 { 119 Map<String, Object> optionalColumnsFieldSet = new HashMap<>(); 120 optionalColumnsFieldSet.put("role", "fieldset"); 121 optionalColumnsFieldSet.put("label", new I18nizableText(ExtractionConstants.PLUGIN_NAME, "PLUGINS_EXTRACTION_EXECUTE_EXTRACTION_OPTIONAL_COLUMNS_FIELDSET_LABEL")); 122 123 Map<String, Object> optionalColumnsFieldSetElements = new HashMap<>(); 124 for (String optionalColumn : optionalColumns) 125 { 126 optionalColumnsFieldSetElements.put(optionalColumn, _getOptionalColumnsInputConfig(optionalColumn)); 127 } 128 optionalColumnsFieldSet.put("elements", optionalColumnsFieldSetElements); 129 130 executionParameters.put("optionalColumns", optionalColumnsFieldSet); 131 } 132 133 executionParameters.put("recipient", _getRecipientInputConfig()); 134 135 return executionParameters; 136 } 137 138 private Map<String, Object> _getPipelineInputConfig(String definitionFile) 139 { 140 Map<String, Object> inputConfig = new HashMap<>(); 141 142 inputConfig.put("label", new I18nizableText(ExtractionConstants.PLUGIN_NAME, "PLUGINS_EXTRACTION_EXECUTE_EXTRACTION_PIPELINE_INPUT_LABEL")); 143 inputConfig.put("description", new I18nizableText(ExtractionConstants.PLUGIN_NAME, "PLUGINS_EXTRACTION_EXECUTE_EXTRACTION_PIPELINE_INPUT_DESCRIPTION")); 144 inputConfig.put("type", "string"); 145 146 inputConfig.put("default-value", _pipelineManager.getDefaultPipeline()); 147 inputConfig.put("validation", _getMandatoryValidation()); 148 149 inputConfig.put("widget", "edition.select-pipeline"); 150 151 Map<String, Object> widgetParams = new HashMap<>(); 152 widgetParams.put("extraction", definitionFile); 153 inputConfig.put("widget-params", widgetParams); 154 155 return inputConfig; 156 } 157 158 private Map<String, Object> _getClauseVariableInputConfig(Entry<String, String> clausesVariable) 159 { 160 Map<String, Object> inputConfig = new HashMap<>(); 161 162 inputConfig.put("label", clausesVariable.getKey()); 163 inputConfig.put("description", new I18nizableText(ExtractionConstants.PLUGIN_NAME, "PLUGINS_EXTRACTION_EXECUTE_EXTRACTION_CLAUSES_VARIABLE_INPUTS_DESCRIPTION")); 164 165 inputConfig.put("type", "content"); 166 inputConfig.put("multiple", true); 167 168 String contentTypeId = clausesVariable.getValue(); 169 ContentType contentType = _contentTypeExtensionPoint.getExtension(contentTypeId); 170 171 String widget = contentType.isReferenceTable() ? "edition.select-referencetable-content" : "edition.select-content"; 172 inputConfig.put("widget", widget); 173 174 Map<String, Object> widgetParams = new HashMap<>(); 175 widgetParams.put("contentType", contentTypeId); 176 inputConfig.put("widget-params", widgetParams); 177 178 inputConfig.put("validation", _getMandatoryValidation()); 179 180 return inputConfig; 181 } 182 183 private Map<String, Object> _getOptionalColumnsInputConfig(String optionalColumn) 184 { 185 Map<String, Object> inputConfig = new HashMap<>(); 186 187 inputConfig.put("label", optionalColumn); 188 inputConfig.put("description", new I18nizableText(ExtractionConstants.PLUGIN_NAME, "PLUGINS_EXTRACTION_EXECUTE_EXTRACTION_OPTIONAL_COLUMNS_INPUTS_DESCRIPTION")); 189 190 inputConfig.put("type", "boolean"); 191 inputConfig.put("widget", "edition.checkbox"); 192 193 inputConfig.put("validation", _getMandatoryValidation()); 194 195 return inputConfig; 196 } 197 198 private Map<String, Object> _getRecipientInputConfig() 199 { 200 Map<String, Object> inputConfig = new HashMap<>(); 201 202 // Get current user email 203 String currentUserEmail = null; 204 UserIdentity currentUser = _currentUserProvider.getUser(); 205 206 String login = currentUser.getLogin(); 207 if (StringUtils.isNotBlank(login)) 208 { 209 String userPopulationId = currentUser.getPopulationId(); 210 User user = _userManager.getUser(userPopulationId, login); 211 currentUserEmail = user.getEmail(); 212 } 213 214 inputConfig.put("label", new I18nizableText(ExtractionConstants.PLUGIN_NAME, "PLUGINS_EXTRACTION_EXECUTE_EXTRACTION_RECIPIENT_INPUT_LABEL")); 215 inputConfig.put("description", new I18nizableText(ExtractionConstants.PLUGIN_NAME, "PLUGINS_EXTRACTION_EXECUTE_EXTRACTION_RECIPIENT_INPUT_DESCRIPTION")); 216 inputConfig.put("type", "string"); 217 inputConfig.put("default-value", currentUserEmail); 218 219 return inputConfig; 220 } 221 222 private Map<String, Object> _getMandatoryValidation() 223 { 224 Map<String, Object> mandatoryValidation = new HashMap<>(); 225 mandatoryValidation.put("mandatory", true); 226 return mandatoryValidation; 227 } 228 229 /** 230 * Execute the extraction 231 * @param definitionFilePath The extraction definition file path 232 * @param variables clauses variables and optional columns 233 * @param recipient An email will be sent at this address when the extraction is complete 234 * @param pipelineId The id of the extraction pipeline 235 * @return a Map with error if one occurs 236 * @throws Exception if an error occurs 237 */ 238 @Callable (right = ExtractionConstants.EXECUTE_EXTRACTION_RIGHT_ID) 239 public Map<String, Object> executeExtraction(String definitionFilePath, Map<String, Object> variables, String recipient, String pipelineId) throws Exception 240 { 241 Map<String, Object> result = new HashMap<>(); 242 243 try 244 { 245 String variablesAsString = _jsonUtils.convertObjectToJson(variables); 246 Runnable executeExtractionRunnable = new ExecuteExtractionRunnable(definitionFilePath, variablesAsString, recipient, pipelineId); 247 JobKey jobKey = new JobKey(executeExtractionRunnable.getId(), Scheduler.JOB_GROUP); 248 if (_scheduler.getScheduler().checkExists(jobKey)) 249 { 250 _scheduler.getScheduler().deleteJob(jobKey); 251 } 252 _scheduler.scheduleJob(executeExtractionRunnable); 253 getLogger().info("Scheduled extraction execution of " + definitionFilePath); 254 } 255 catch (SchedulerException e) 256 { 257 if (getLogger().isErrorEnabled()) 258 { 259 getLogger().error("An error occured when trying to schedule the extraction execution of " + definitionFilePath, e); 260 } 261 result.put("error", "scheduler-error"); 262 return result; 263 } 264 265 result.put("definitionFilePath", definitionFilePath); 266 return result; 267 } 268}