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.ArrayList; 020import java.util.HashMap; 021import java.util.LinkedHashMap; 022import java.util.List; 023import java.util.Map; 024import java.util.Map.Entry; 025 026import org.apache.avalon.framework.service.ServiceException; 027import org.apache.avalon.framework.service.ServiceManager; 028import org.apache.commons.lang.StringUtils; 029import org.apache.excalibur.source.Source; 030import org.apache.excalibur.source.SourceResolver; 031import org.apache.excalibur.source.impl.FileSource; 032import org.quartz.JobKey; 033import org.quartz.SchedulerException; 034 035import org.ametys.core.schedule.Runnable; 036import org.ametys.core.ui.Callable; 037import org.ametys.core.ui.StaticClientSideElement; 038import org.ametys.core.user.User; 039import org.ametys.core.user.UserIdentity; 040import org.ametys.core.user.UserManager; 041import org.ametys.core.util.JSONUtils; 042import org.ametys.plugins.core.schedule.Scheduler; 043import org.ametys.plugins.extraction.ExtractionConstants; 044import org.ametys.plugins.extraction.ExtractionHelper; 045import org.ametys.runtime.i18n.I18nizableText; 046 047/** 048 * This client site element creates a button to execute an extraction 049 */ 050public class ExecuteExtractionClientSideElement extends StaticClientSideElement 051{ 052 private UserManager _userManager; 053 private ExtractionDefinitionReader _reader; 054 private SourceResolver _sourceResolver; 055 private JSONUtils _jsonUtils; 056 private Scheduler _scheduler; 057 private ExtractionHelper _extractionHelper; 058 059 @Override 060 public void service(ServiceManager serviceManager) throws ServiceException 061 { 062 super.service(serviceManager); 063 _userManager = (UserManager) serviceManager.lookup(UserManager.ROLE); 064 _reader = (ExtractionDefinitionReader) serviceManager.lookup(ExtractionDefinitionReader.ROLE); 065 _sourceResolver = (SourceResolver) serviceManager.lookup(SourceResolver.ROLE); 066 _jsonUtils = (JSONUtils) serviceManager.lookup(JSONUtils.ROLE); 067 _scheduler = (Scheduler) serviceManager.lookup(Scheduler.ROLE); 068 _extractionHelper = (ExtractionHelper) serviceManager.lookup(ExtractionHelper.ROLE); 069 } 070 071 /** 072 * Retrieve needed extraction parameters. 073 * @param definitionFile The extraction definition file path 074 * @return a <code>Map</code> containing parameters infos used to configure form to fill the parameters 075 * @throws Exception if an error occurs 076 */ 077 @Callable (right = "Extraction_Rights_ExecuteExtraction") 078 public Map<String, Object> getExecutionParameters(String definitionFile) throws Exception 079 { 080 Map<String, Object> executionParamerters = new LinkedHashMap<>(); 081 082 String definitionFilePath = ExtractionConstants.DEFINITIONS_DIR + definitionFile; 083 Source src = _sourceResolver.resolveURI(definitionFilePath); 084 File file = ((FileSource) src).getFile(); 085 086 if (!file.exists()) 087 { 088 throw new IllegalArgumentException("The file " + definitionFilePath + " does not exist."); 089 } 090 091 executionParamerters.put("format", _getFormatInputConfig()); 092 executionParamerters.put("stylesheetForXML", _getStylesheetInputConfigForXMLFormat()); 093 executionParamerters.put("stylesheetForPDF", _getStylesheetInputConfigForPDFFormat()); 094 095 Extraction extraction = _reader.readExtractionDefinitionFile(file); 096 097 Map<String, String> clasuesVariables = extraction.getQueryVariablesNamesAndContentTypes(); 098 List<String> optionalColumns = extraction.getDisplayOptionalColumnsNames(); 099 if (!clasuesVariables.isEmpty() || !optionalColumns.isEmpty()) 100 { 101 List<Map<String, Object>> variablesFieldSets = new ArrayList<>(); 102 if (!clasuesVariables.isEmpty()) 103 { 104 Map<String, Object> clausesVariablesFieldSet = new HashMap<>(); 105 clausesVariablesFieldSet.put("role", "fieldset"); 106 clausesVariablesFieldSet.put("label", new I18nizableText(ExtractionConstants.PLUGIN_NAME, "PLUGINS_EXTRACTION_EXECUTE_EXTRACTION_CLAUSES_VARIABLES_FIELDSET_LABEL")); 107 108 Map<String, Object> clausesVariablesFieldSetElements = new HashMap<>(); 109 for (Map.Entry<String, String> clausesVariable : clasuesVariables.entrySet()) 110 { 111 clausesVariablesFieldSetElements.put(clausesVariable.getKey(), _getClauseVariableInputConfig(clausesVariable)); 112 } 113 clausesVariablesFieldSet.put("elements", clausesVariablesFieldSetElements); 114 115 variablesFieldSets.add(clausesVariablesFieldSet); 116 } 117 118 if (!optionalColumns.isEmpty()) 119 { 120 Map<String, Object> optionalColumnsFieldSet = new HashMap<>(); 121 optionalColumnsFieldSet.put("role", "fieldset"); 122 optionalColumnsFieldSet.put("label", new I18nizableText(ExtractionConstants.PLUGIN_NAME, "PLUGINS_EXTRACTION_EXECUTE_EXTRACTION_OPTIONAL_COLUMNS_FIELDSET_LABEL")); 123 124 Map<String, Object> optionalColumnsFieldSetElements = new HashMap<>(); 125 for (String optionalColumn : optionalColumns) 126 { 127 optionalColumnsFieldSetElements.put(optionalColumn, _getOptionalColumnsInputConfig(optionalColumn)); 128 } 129 optionalColumnsFieldSet.put("elements", optionalColumnsFieldSetElements); 130 131 variablesFieldSets.add(optionalColumnsFieldSet); 132 } 133 134 executionParamerters.put("fieldsets", variablesFieldSets); 135 } 136 137 executionParamerters.put("recipient", _getRecipientInputConfig()); 138 139 return executionParamerters; 140 } 141 142 private Map<String, Object> _getFormatInputConfig() 143 { 144 Map<String, Object> inputConfig = new HashMap<>(); 145 146 inputConfig.put("label", new I18nizableText(ExtractionConstants.PLUGIN_NAME, "PLUGINS_EXTRACTION_EXECUTE_EXTRACTION_FORMAT_INPUT_LABEL")); 147 inputConfig.put("description", new I18nizableText(ExtractionConstants.PLUGIN_NAME, "PLUGINS_EXTRACTION_EXECUTE_EXTRACTION_FORMAT_INPUT_DESCRIPTION")); 148 inputConfig.put("type", "string"); 149 150 List<Map<String, Object>> enumeration = new ArrayList<>(); 151 152 // XML format 153 Map<String, Object> xmlOption = new HashMap<>(); 154 xmlOption.put("value", "xml"); 155 xmlOption.put("label", new I18nizableText(ExtractionConstants.PLUGIN_NAME, "PLUGINS_EXTRACTION_EXECUTE_EXTRACTION_FORMAT_INPUT_XML_LABEL")); 156 enumeration.add(xmlOption); 157 158 // PDF format 159 Map<String, Object> pdfOption = new HashMap<>(); 160 pdfOption.put("value", "pdf"); 161 pdfOption.put("label", new I18nizableText(ExtractionConstants.PLUGIN_NAME, "PLUGINS_EXTRACTION_EXECUTE_EXTRACTION_FORMAT_INPUT_PDF_LABEL")); 162 enumeration.add(pdfOption); 163 164 inputConfig.put("enumeration", enumeration); 165 inputConfig.put("default-value", "xml"); 166 inputConfig.put("validation", _getMandatoryValidation()); 167 168 return inputConfig; 169 } 170 171 private Map<String, Object> _getStylesheetInputConfigForPDFFormat() 172 { 173 Map<String, Object> inputConfig = _getStylesheetInputConfig(); 174 inputConfig.put("validation", _getMandatoryValidation()); 175 inputConfig.put("disableCondition", _getStylesheetInputDisabledCondition("pdf")); 176 return inputConfig; 177 } 178 179 private Map<String, Object> _getStylesheetInputConfigForXMLFormat() 180 { 181 Map<String, Object> inputConfig = _getStylesheetInputConfig(); 182 inputConfig.put("disableCondition", _getStylesheetInputDisabledCondition("xml")); 183 return inputConfig; 184 } 185 186 private Map<String, Object> _getStylesheetInputConfig() 187 { 188 Map<String, Object> inputConfig = new HashMap<>(); 189 190 inputConfig.put("label", new I18nizableText(ExtractionConstants.PLUGIN_NAME, "PLUGINS_EXTRACTION_EXECUTE_EXTRACTION_XSLT_FILE_INPUT_LABEL")); 191 inputConfig.put("description", new I18nizableText(ExtractionConstants.PLUGIN_NAME, "PLUGINS_EXTRACTION_EXECUTE_EXTRACTION_XSLT_FILE_INPUT_DESCRIPTION")); 192 inputConfig.put("type", "string"); 193 194 try 195 { 196 // Try to build enumeration for XSLT files 197 List<Map<String, Object>> enumeration = new ArrayList<>(); 198 199 Map<Object, I18nizableText> entries = _extractionHelper.getExtractionStylesheets(); 200 for (Object entryKey : entries.keySet()) 201 { 202 Map<String, Object> option = new HashMap<>(); 203 option.put("value", entryKey); 204 option.put("label", entries.get(entryKey)); 205 enumeration.add(option); 206 } 207 208 inputConfig.put("enumeration", enumeration); 209 } 210 catch (Exception e) 211 { 212 getLogger().error("Unable to provide enumeration elements for extraction stylesheets", e); 213 } 214 215 return inputConfig; 216 } 217 218 private Map<String, Object> _getStylesheetInputDisabledCondition(String value) 219 { 220 Map<String, Object> condition = new HashMap<>(); 221 condition.put("id", "format"); 222 condition.put("operator", "neq"); 223 condition.put("value", value); 224 225 List<Map<String, Object>> conditions = new ArrayList<>(); 226 conditions.add(condition); 227 228 Map<String, Object> disabledCondition = new HashMap<>(); 229 disabledCondition.put("condition", conditions); 230 return disabledCondition; 231 } 232 233 private Map<String, Object> _getClauseVariableInputConfig(Entry<String, String> clausesVariable) 234 { 235 Map<String, Object> inputConfig = new HashMap<>(); 236 237 inputConfig.put("label", clausesVariable.getKey()); 238 inputConfig.put("description", new I18nizableText(ExtractionConstants.PLUGIN_NAME, "PLUGINS_EXTRACTION_EXECUTE_EXTRACTION_CLAUSES_VARIABLE_INPUTS_DESCRIPTION")); 239 240 inputConfig.put("type", "content"); 241 inputConfig.put("widget", "edition.select-content"); 242 243 Map<String, Object> widgetParams = new HashMap<>(); 244 widgetParams.put("contentType", clausesVariable.getValue()); 245 inputConfig.put("widget-params", widgetParams); 246 247 inputConfig.put("validation", _getMandatoryValidation()); 248 249 return inputConfig; 250 } 251 252 private Map<String, Object> _getOptionalColumnsInputConfig(String optionalColumn) 253 { 254 Map<String, Object> inputConfig = new HashMap<>(); 255 256 inputConfig.put("label", optionalColumn); 257 inputConfig.put("description", new I18nizableText(ExtractionConstants.PLUGIN_NAME, "PLUGINS_EXTRACTION_EXECUTE_EXTRACTION_OPTIONAL_COLUMNS_INPUTS_DESCRIPTION")); 258 259 inputConfig.put("type", "boolean"); 260 inputConfig.put("widget", "edition.checkbox"); 261 262 inputConfig.put("validation", _getMandatoryValidation()); 263 264 return inputConfig; 265 } 266 267 private Map<String, Object> _getRecipientInputConfig() 268 { 269 Map<String, Object> inputConfig = new HashMap<>(); 270 271 // Get current user email 272 String currentUserEmail = null; 273 UserIdentity currentUser = _currentUserProvider.getUser(); 274 275 String login = currentUser.getLogin(); 276 if (StringUtils.isNotBlank(login)) 277 { 278 String userPopulationId = currentUser.getPopulationId(); 279 User user = _userManager.getUser(userPopulationId, login); 280 currentUserEmail = user.getEmail(); 281 } 282 283 inputConfig.put("label", new I18nizableText(ExtractionConstants.PLUGIN_NAME, "PLUGINS_EXTRACTION_EXECUTE_EXTRACTION_RECIPIENT_INPUT_LABEL")); 284 inputConfig.put("description", new I18nizableText(ExtractionConstants.PLUGIN_NAME, "PLUGINS_EXTRACTION_EXECUTE_EXTRACTION_RECIPIENT_INPUT_DESCRIPTION")); 285 inputConfig.put("type", "string"); 286 inputConfig.put("default-value", currentUserEmail); 287 288 return inputConfig; 289 } 290 291 private Map<String, Object> _getMandatoryValidation() 292 { 293 Map<String, Object> mandatoryValidation = new HashMap<>(); 294 mandatoryValidation.put("mandatory", true); 295 return mandatoryValidation; 296 } 297 298 /** 299 * Execute the extraction 300 * @param definitionFilePath The extraction definition file path 301 * @param variables clauses variables and optional columns 302 * @param recipient An email will be sent at this address when the extraction is complete 303 * @param format The format of the extraction result 304 * @param xsltFilePath The stylesheet to apply on extraction result 305 * @return a Map with error if one occurs 306 * @throws Exception if an error occurs 307 */ 308 @Callable (right = "Extraction_Rights_ExecuteExtraction") 309 public Map<String, Object> executeExtraction(String definitionFilePath, Map<String, Object> variables, String recipient, String format, String xsltFilePath) throws Exception 310 { 311 Map<String, Object> result = new HashMap<>(); 312 313 try 314 { 315 String variablesAsString = _jsonUtils.convertObjectToJson(variables); 316 Runnable executeExtractionRunnable = new ExecuteExtractionRunnable(definitionFilePath, variablesAsString, recipient, format, xsltFilePath); 317 JobKey jobKey = new JobKey(executeExtractionRunnable.getId(), Scheduler.JOB_GROUP); 318 if (_scheduler.getScheduler().checkExists(jobKey)) 319 { 320 _scheduler.getScheduler().deleteJob(jobKey); 321 } 322 _scheduler.scheduleJob(executeExtractionRunnable); 323 getLogger().info("Scheduled extraction execution of " + definitionFilePath); 324 } 325 catch (SchedulerException e) 326 { 327 if (getLogger().isErrorEnabled()) 328 { 329 getLogger().error("An error occured when trying to schedule the extraction execution of " + definitionFilePath, e); 330 } 331 result.put("error", "scheduler-error"); 332 return result; 333 } 334 335 result.put("definitionFilePath", definitionFilePath); 336 return result; 337 } 338}