001/* 002 * Copyright 2023 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.workflow.dao; 017 018import java.util.ArrayList; 019import java.util.HashMap; 020import java.util.HashSet; 021import java.util.List; 022import java.util.Map; 023import java.util.Optional; 024import java.util.Set; 025import java.util.stream.Collectors; 026 027import org.apache.avalon.framework.component.Component; 028import org.apache.avalon.framework.context.Context; 029import org.apache.avalon.framework.service.ServiceException; 030import org.apache.avalon.framework.service.ServiceManager; 031import org.apache.avalon.framework.service.Serviceable; 032 033import org.ametys.core.ui.Callable; 034import org.ametys.core.util.I18nUtils; 035import org.ametys.core.util.StringUtils; 036import org.ametys.plugins.workflow.component.WorkflowLanguageManager; 037import org.ametys.plugins.workflow.support.I18nHelper; 038import org.ametys.plugins.workflow.support.WorflowRightHelper; 039import org.ametys.plugins.workflow.support.WorkflowHelper; 040import org.ametys.plugins.workflow.support.WorkflowSessionHelper; 041import org.ametys.runtime.i18n.I18nizableText; 042 043import com.opensymphony.workflow.loader.ActionDescriptor; 044import com.opensymphony.workflow.loader.DescriptorFactory; 045import com.opensymphony.workflow.loader.ResultDescriptor; 046import com.opensymphony.workflow.loader.StepDescriptor; 047import com.opensymphony.workflow.loader.WorkflowDescriptor; 048 049/** 050 * The workflow action DAO 051 */ 052public class WorkflowTransitionDAO implements Component, Serviceable 053{ 054 /** The component's role */ 055 public static final String ROLE = WorkflowTransitionDAO.class.getName(); 056 057 /** The default label for actions */ 058 public static final I18nizableText DEFAULT_ACTION_NAME = new I18nizableText("plugin.workflow", "PLUGIN_WORKFLOW_DEFAULT_ACTION_LABEL"); 059 060 /** Default path for svg action icons */ 061 private static final String __DEFAULT_SVG_ACTION_ICON_PATH = "plugin:cms://resources/img/history/workflow/action_0_16.png"; 062 063 /** Default path for node action icons */ 064 private static final String __DEFAULT_ACTION_ICON_PATH = "/plugins/cms/resources/img/history/workflow/action_0_16.png"; 065 066 /** The workflow session helper */ 067 protected WorkflowSessionHelper _workflowSessionHelper; 068 069 /** The workflow right helper */ 070 protected WorflowRightHelper _workflowRightHelper; 071 072 /** The Workflow Language Manager */ 073 protected WorkflowLanguageManager _workflowLanguageManager; 074 075 /** The workflow helper */ 076 protected WorkflowHelper _workflowHelper; 077 078 /** The workflow step DAO */ 079 protected WorkflowStepDAO _workflowStepDAO; 080 081 /** The helper for i18n translations and catalogs */ 082 protected I18nHelper _i18nHelper; 083 084 /** The i18n utils */ 085 protected I18nUtils _i18nUtils; 086 087 /** The context */ 088 protected Context _context; 089 090 public void service(ServiceManager smanager) throws ServiceException 091 { 092 _workflowSessionHelper = (WorkflowSessionHelper) smanager.lookup(WorkflowSessionHelper.ROLE); 093 _workflowHelper = (WorkflowHelper) smanager.lookup(WorkflowHelper.ROLE); 094 _workflowRightHelper = (WorflowRightHelper) smanager.lookup(WorflowRightHelper.ROLE); 095 _i18nHelper = (I18nHelper) smanager.lookup(I18nHelper.ROLE); 096 _workflowLanguageManager = (WorkflowLanguageManager) smanager.lookup(WorkflowLanguageManager.ROLE); 097 _workflowStepDAO = (WorkflowStepDAO) smanager.lookup(WorkflowStepDAO.ROLE); 098 _i18nUtils = (I18nUtils) smanager.lookup(I18nUtils.ROLE); 099 } 100 101 /** 102 * Get the transition infos to initialize creation/edition form fields 103 * @param workflowName the current workflow name 104 * @param transitionId the current transition's id, can be null 105 * @return the transition values and a list of taken ids 106 */ 107 @Callable(rights = Callable.CHECKED_BY_IMPLEMENTATION) 108 public Map<String, Object> getTransitionInfos(String workflowName, Integer transitionId) 109 { 110 WorkflowDescriptor workflowDescriptor = _workflowSessionHelper.getWorkflowDescriptor(workflowName, false); 111 112 // Check user right 113 _workflowRightHelper.checkEditRight(workflowDescriptor); 114 115 Map<String, Object> transitionInfos = new HashMap<>(); 116 Set<Integer> transitionIds = _workflowHelper.getAllActions(workflowDescriptor); 117 I18nizableText labelKey = DEFAULT_ACTION_NAME; 118 if (transitionId != null) 119 { 120 transitionIds.remove(transitionId); 121 transitionInfos.put("id", transitionId); 122 ActionDescriptor action = workflowDescriptor.getAction(transitionId); 123 labelKey = getActionLabel(action); 124 125 transitionInfos.put("finalStep", action.getUnconditionalResult().getStep()); 126 } 127 transitionInfos.put("ids", transitionIds); 128 129 Map<String, String> translations = _workflowSessionHelper.getTranslation(workflowName, labelKey); 130 if (translations == null) 131 { 132 translations = new HashMap<>(); 133 translations.put(_workflowLanguageManager.getCurrentLanguage(), _i18nHelper.translateKey(workflowDescriptor.getName(), labelKey, DEFAULT_ACTION_NAME)); 134 } 135 transitionInfos.put("labels", translations); 136 137 return transitionInfos; 138 } 139 140 /** 141 * Get a set of transitions already defined in current workflow beside initialActions 142 * @param workflowName the current workflow name 143 * @param parentStepId the current selected step 144 * @return a set containing maps of actions properties 145 */ 146 @Callable(rights = Callable.CHECKED_BY_IMPLEMENTATION) 147 public Set<Map<String, Object>> getAvailableActions(String workflowName, Integer parentStepId) 148 { 149 WorkflowDescriptor workflowDescriptor = _workflowSessionHelper.getWorkflowDescriptor(workflowName, false); 150 151 // Check user right 152 _workflowRightHelper.checkReadRight(workflowDescriptor); 153 154 155 Set<Map<String, Object>> availableActions = new HashSet<>(); 156 if (0 != parentStepId) // generic actions can't be used as initial actions 157 { 158 StepDescriptor parentStep = workflowDescriptor.getStep(parentStepId); 159 List<ActionDescriptor> actions = parentStep.getActions(); 160 161 List<StepDescriptor> steps = workflowDescriptor.getSteps(); 162 for (StepDescriptor step: steps) 163 { 164 List<ActionDescriptor> outgoingActions = step.getActions(); 165 for (ActionDescriptor outgoingAction: outgoingActions) 166 { 167 if (!actions.contains(outgoingAction)) 168 { 169 availableActions.add(_getActionInfos(workflowName, outgoingAction)); 170 } 171 } 172 } 173 } 174 return availableActions; 175 } 176 177 private Map<String, Object> _getActionInfos(String workflowName, ActionDescriptor action) 178 { 179 Map<String, Object> actionInfos = new HashMap<>(); 180 int actionId = action.getId(); 181 actionInfos.put("id", actionId); 182 actionInfos.put("label", getActionLabel(workflowName, action) + " (" + actionId + ")"); 183 return actionInfos; 184 } 185 186 /** 187 * Create a new transition 188 * @param workflowName the current workflow name 189 * @param parentStepId the parent step id 190 * @param transitionId the id for the transition to create 191 * @param labels the multilinguals labels for the transition 192 * @param finalStepId the id for the transition's unconditional result 193 * @return a map with error message or with transition's id if succesfull 194 */ 195 @Callable(rights = Callable.CHECKED_BY_IMPLEMENTATION) 196 public Map<String, Object> createTransition(String workflowName, Integer parentStepId, int transitionId, Map<String, String> labels, int finalStepId) 197 { 198 WorkflowDescriptor workflowDescriptor = _workflowSessionHelper.getWorkflowDescriptor(workflowName, true); 199 200 // Check user right 201 _workflowRightHelper.checkEditRight(workflowDescriptor); 202 203 if (_workflowHelper.getAllActions(workflowDescriptor).contains(transitionId)) 204 { 205 return Map.of("message", "duplicate-id"); 206 } 207 208 DescriptorFactory factory = new DescriptorFactory(); 209 ActionDescriptor action = factory.createActionDescriptor(); 210 action.setId(transitionId); 211 I18nizableText actionNameI18nKey = _i18nHelper.generateI18nKey(workflowName, "ACTION", transitionId); 212 action.setName(actionNameI18nKey.toString()); 213 ResultDescriptor finalStep = factory.createResultDescriptor(); 214 finalStep.setStep(finalStepId); 215 action.setUnconditionalResult(finalStep); 216 217 if (isInitialStep(parentStepId)) 218 { 219 workflowDescriptor.addInitialAction(action); 220 } 221 else 222 { 223 StepDescriptor stepDescriptor = workflowDescriptor.getStep(parentStepId); 224 stepDescriptor.getActions().add(action); 225 } 226 227 _workflowSessionHelper.updateTranslations(workflowName, actionNameI18nKey, labels); 228 _generateActionDescription(workflowName, actionNameI18nKey, labels); 229 _workflowSessionHelper.updateWorkflowDescriptor(workflowDescriptor); 230 231 return _getActionProperties(workflowDescriptor, action, parentStepId); 232 } 233 234 private Map<String, Object> _getActionProperties(WorkflowDescriptor workflowDescriptor, ActionDescriptor action, Integer stepId) 235 { 236 Map<String, Object> results = new HashMap<>(); 237 results.put("actionId", action.getId()); 238 results.put("actionLabels", getActionLabel(workflowDescriptor.getName(), action)); 239 results.put("stepId", stepId); 240 results.put("stepLabel", _workflowStepDAO.getStepLabel(workflowDescriptor, stepId)); 241 results.put("workflowId", workflowDescriptor.getName()); 242 243 return results; 244 } 245 246 private boolean isInitialStep(Integer stepIdToInt) 247 { 248 return stepIdToInt == 0; 249 } 250 251 /** 252 * Add an existing transition to current step 253 * @param workflowName the current workflow name 254 * @param parentStepId the current selected step id 255 * @param transitionIds a list of ids corresponding to the transitions to add to current step 256 * @return the first transition id and its parent sted id 257 */ 258 @Callable(rights = Callable.CHECKED_BY_IMPLEMENTATION) 259 public Map<String, Object> addTransitions(String workflowName, Integer parentStepId, List<Integer> transitionIds) 260 { 261 WorkflowDescriptor workflowDescriptor = _workflowSessionHelper.getWorkflowDescriptor(workflowName, true); 262 263 // Check user right 264 _workflowRightHelper.checkEditRight(workflowDescriptor); 265 266 Map<String, Object> results = new HashMap<>(); 267 268 if (parentStepId != 0) 269 { 270 StepDescriptor step = workflowDescriptor.getStep(parentStepId); 271 for (Integer id : transitionIds) 272 { 273 ActionDescriptor action = _getAction(workflowDescriptor, id); 274 step.getActions().add(action); 275 if (!action.isCommon()) 276 { 277 _updateWorkflowCommonAction(workflowDescriptor, id, action); 278 } 279 else 280 { 281 step.getCommonActions().add(id); 282 } 283 } 284 _workflowSessionHelper.updateWorkflowDescriptor(workflowDescriptor); 285 results = _getActionProperties(workflowDescriptor, workflowDescriptor.getAction(transitionIds.get(0)), parentStepId); 286 } 287 else 288 { 289 results.put("message", "initial-step"); 290 } 291 292 return results; 293 } 294 295 private ActionDescriptor _getAction(WorkflowDescriptor workflowDescriptor, Integer actionId) 296 { 297 ActionDescriptor action = workflowDescriptor.getAction(actionId); 298 if (action == null) 299 { 300 Map<Integer, ActionDescriptor> commonActions = workflowDescriptor.getCommonActions(); 301 action = commonActions.get(actionId); 302 } 303 return action; 304 } 305 306 /** 307 * Set action as 'common' in steps using it 308 * @param workflowDescriptor the current workflow 309 * @param actionId id of current action 310 * @param action the action 311 */ 312 protected void _updateWorkflowCommonAction(WorkflowDescriptor workflowDescriptor, int actionId, ActionDescriptor action) 313 { 314 List<StepDescriptor> stepsToUpdate = new ArrayList<>(); 315 List<StepDescriptor> steps = workflowDescriptor.getSteps(); 316 317 //remove individual action from steps 318 for (StepDescriptor step : steps) 319 { 320 if (step.getAction(actionId) != null) 321 { 322 step.getActions().remove(action); 323 stepsToUpdate.add(step); 324 } 325 } 326 //set action as common in workflow 327 workflowDescriptor.addCommonAction(action); 328 329 //put back action in steps as common action 330 for (StepDescriptor step : stepsToUpdate) 331 { 332 step.getCommonActions().add(actionId); 333 step.getActions().add(action); 334 } 335 } 336 337 /** 338 * Rename the transition 339 * @param workflowName the workflow name 340 * @param stepId id of selected step 341 * @param actionId the transition's id 342 * @param newMainLabel the new label in current language 343 * @return a map with error message or with transition's infos if succesfull 344 */ 345 @Callable(rights = Callable.CHECKED_BY_IMPLEMENTATION) 346 public Map<String, Object> editTransitionLabel(String workflowName, Integer stepId, Integer actionId, String newMainLabel) 347 { 348 WorkflowDescriptor workflowDescriptor = _workflowSessionHelper.getWorkflowDescriptor(workflowName, true); 349 350 // Check user right 351 _workflowRightHelper.checkEditRight(workflowDescriptor); 352 353 ActionDescriptor action = workflowDescriptor.getAction(actionId); 354 _updateActionName(workflowName, action); 355 I18nizableText actionKey = getActionLabel(action); 356 _workflowSessionHelper.updateTranslations(workflowName, actionKey, Map.of(_workflowLanguageManager.getCurrentLanguage(), newMainLabel)); 357 358 _generateActionDescription(workflowName, actionKey, Map.of(_workflowLanguageManager.getCurrentLanguage(), newMainLabel)); 359 360 return _getActionProperties(workflowDescriptor, action, stepId); 361 } 362 363 private void _updateActionName(String workflowName, ActionDescriptor action) 364 { 365 String defaultCatalog = _workflowHelper.getWorkflowCatalog(workflowName); 366 I18nizableText actionKey = getActionLabel(action); 367 368 if (!defaultCatalog.equals(actionKey.getCatalogue())) 369 { 370 String newName = new I18nizableText(defaultCatalog, actionKey.getKey()).toString(); 371 action.setName(newName); 372 } 373 } 374 375 /** 376 * Edit the transition 377 * @param workflowName the workflow name 378 * @param stepId id of selected step 379 * @param oldId the transition's former id 380 * @param newId the transition's new id 381 * @param labels the transition's multilingual labels 382 * @param finalStepId the transition's unconditional result id 383 * @return a map with error message or with transition's infos if succesfull 384 */ 385 @Callable(rights = Callable.CHECKED_BY_IMPLEMENTATION) 386 public Map<String, Object> editTransition(String workflowName, Integer stepId, Integer oldId, Integer newId, Map<String, String> labels, Integer finalStepId) 387 { 388 WorkflowDescriptor workflowDescriptor = _workflowSessionHelper.getWorkflowDescriptor(workflowName, true); 389 390 // Check user right 391 _workflowRightHelper.checkEditRight(workflowDescriptor); 392 393 ActionDescriptor action = workflowDescriptor.getAction(oldId); 394 395 if (!newId.equals(oldId)) 396 { 397 if (_workflowHelper.getAllActions(workflowDescriptor).contains(newId)) 398 { 399 return Map.of("message", "duplicate-id"); 400 } 401 if (action.isCommon()) 402 { 403 //Don't change edit order below: first update steps then update action 404 workflowDescriptor.getCommonActions().remove(oldId, action); 405 List<StepDescriptor> steps = workflowDescriptor.getSteps(); 406 for (StepDescriptor step: steps) 407 { 408 if (step.getAction(oldId) != null) 409 { 410 List<Integer> commonActions = step.getCommonActions(); 411 commonActions.remove(commonActions.indexOf(oldId)); 412 commonActions.add(newId); 413 } 414 } 415 action.setId(newId); 416 workflowDescriptor.getCommonActions().put(newId, action); 417 } 418 else 419 { 420 action.setId(newId); 421 } 422 } 423 424 DescriptorFactory factory = new DescriptorFactory(); 425 ResultDescriptor finalStep = factory.createResultDescriptor(); 426 finalStep.setStep(finalStepId); 427 action.setUnconditionalResult(finalStep); 428 429 _updateActionName(workflowName, action); 430 I18nizableText actionKey = getActionLabel(action); 431 _workflowSessionHelper.updateTranslations(workflowName, actionKey, labels); 432 433 _generateActionDescription(workflowName, actionKey, labels); 434 435 _workflowSessionHelper.updateWorkflowDescriptor(workflowDescriptor); 436 437 return _getActionProperties(workflowDescriptor, action, stepId); 438 } 439 440 private void _generateActionDescription(String workflowName, I18nizableText actionKey, Map<String, String> labels) 441 { 442 I18nizableText actionDescriptionI18nKey = new I18nizableText(actionKey.getCatalogue(), actionKey.getKey() + "_ACTION_DESCRIPTION"); 443 444 Map<String, String> descriptionValues = labels.entrySet() 445 .stream() 446 .collect(Collectors.toMap( 447 e -> e.getKey(), 448 e -> _getDescriptionValue(e.getValue(), e.getKey()) 449 ) 450 ); 451 452 _workflowSessionHelper.updateTranslations(workflowName, actionDescriptionI18nKey, descriptionValues); 453 } 454 455 private String _getDescriptionValue(String label, String lang) 456 { 457 I18nizableText descriptionPrefixI18nText = new I18nizableText("plugin.workflow", "PLUGINS_WORKFLOW_CREATE_TRANSITION_DEFAULT_DESRIPTION", List.of(StringUtils.escapeHTML(label))); 458 return _i18nUtils.translate(descriptionPrefixI18nText, lang); 459 } 460 461 /** 462 * Remove transition from step 463 * @param workflowName the current workflow name 464 * @param parentStepId the parent step id to remove the transition from 465 * @param transitionId the id for the transition to remove 466 * @return empty map if successfull 467 */ 468 @Callable(rights = Callable.CHECKED_BY_IMPLEMENTATION) 469 public Map<String, Object> removeTransition(String workflowName, Integer parentStepId, Integer transitionId) 470 { 471 WorkflowDescriptor workflowDescriptor = _workflowSessionHelper.getWorkflowDescriptor(workflowName, true); 472 473 // Check user right 474 _workflowRightHelper.checkEditRight(workflowDescriptor); 475 476 ActionDescriptor actionToRemove = null; 477 if (isInitialStep(parentStepId)) 478 { 479 actionToRemove = workflowDescriptor.getInitialAction(transitionId); 480 _workflowSessionHelper.removeTranslation(workflowName, new I18nizableText("application", actionToRemove.getName())); 481 workflowDescriptor.getInitialActions().remove(actionToRemove); 482 } 483 else 484 { 485 StepDescriptor stepDescriptor = workflowDescriptor.getStep(parentStepId); 486 actionToRemove = workflowDescriptor.getAction(transitionId); 487 stepDescriptor.getActions().remove(actionToRemove); 488 if (actionToRemove.isCommon()) 489 { 490 List<Integer> commonActions = stepDescriptor.getCommonActions(); 491 commonActions.remove(commonActions.indexOf(transitionId)); 492 _manageCommonAction(workflowDescriptor, actionToRemove); 493 } 494 else 495 { 496 I18nizableText actionKey = getActionLabel(actionToRemove); 497 _workflowSessionHelper.removeTranslation(workflowName, actionKey); //use actionKey instead of action.getName() in case plugin's name is in the name 498 } 499 } 500 _workflowSessionHelper.updateWorkflowDescriptor(workflowDescriptor); 501 502 return _getActionProperties(workflowDescriptor, actionToRemove, parentStepId); 503 } 504 505 /** 506 * Verify that the action is still used by multiple steps. If not anymore, replace the action by a non common copy 507 * @param workflowDescriptor the current workflow 508 * @param action the action removed 509 */ 510 protected void _manageCommonAction(WorkflowDescriptor workflowDescriptor, ActionDescriptor action) 511 { 512 Map<Integer, ActionDescriptor> commonActions = workflowDescriptor.getCommonActions(); 513 Integer id = action.getId(); 514 if (commonActions.containsKey(id)) 515 { 516 List<StepDescriptor> steps = workflowDescriptor.getSteps(); 517 int numberOfUse = _getNumberOfUse(id, steps); 518 if (numberOfUse == 1) 519 { 520 //only way to unset common in action is to replace it with a new copy 521 StepDescriptor parentStep = _getParentStep(steps, id).get(); 522 List<Integer> stepCommonActions = parentStep.getCommonActions(); 523 stepCommonActions.remove(stepCommonActions.indexOf(id)); 524 parentStep.getActions().remove(action); 525 workflowDescriptor.getCommonActions().remove(id, action); 526 ActionDescriptor actionCopy = _copyAction(action); 527 parentStep.getActions().add(actionCopy); 528 _workflowSessionHelper.updateWorkflowDescriptor(workflowDescriptor); 529 } 530 } 531 } 532 533 private Optional<StepDescriptor> _getParentStep(List<StepDescriptor> steps, int actionId) 534 { 535 return steps.stream().filter(s -> s.getAction(actionId) != null).findFirst(); 536 } 537 538 private ActionDescriptor _copyAction(ActionDescriptor actionToCopy) 539 { 540 DescriptorFactory factory = new DescriptorFactory(); 541 ActionDescriptor action = factory.createActionDescriptor(); 542 action.setId(actionToCopy.getId()); 543 action.setName(actionToCopy.getName()); 544 action.setUnconditionalResult(actionToCopy.getUnconditionalResult()); 545 action.getConditionalResults().addAll(actionToCopy.getConditionalResults()); 546 action.setMetaAttributes(actionToCopy.getMetaAttributes()); 547 action.setRestriction(actionToCopy.getRestriction()); 548 action.getPreFunctions().addAll(actionToCopy.getPreFunctions()); 549 action.getPostFunctions().addAll(actionToCopy.getPostFunctions()); 550 551 return action; 552 } 553 554 /** 555 * Get the number of steps using the action 556 * @param workflowName the current workflow's name 557 * @param actionId the current action's id 558 * @return the number of steps using the action 559 */ 560 @Callable(rights = Callable.CHECKED_BY_IMPLEMENTATION) 561 public int getNumberOfUse(String workflowName, Integer actionId) 562 { 563 WorkflowDescriptor workflow = _workflowSessionHelper.getWorkflowDescriptor(workflowName, false); 564 565 _workflowRightHelper.checkReadRight(workflow); 566 567 return _getNumberOfUse(actionId, workflow.getSteps()); 568 } 569 570 private int _getNumberOfUse(Integer actionId, List<StepDescriptor> steps) 571 { 572 int stepSize = steps.size(); 573 int numberOfUse = 0; 574 int index = 0; 575 while (index < stepSize) 576 { 577 if (steps.get(index).getAction(actionId) != null) 578 { 579 numberOfUse++; 580 } 581 index++; 582 } 583 return numberOfUse; 584 } 585 586 /** 587 * Get the translated action label 588 * @param workflowName the workflow's unique name 589 * @param action current action 590 * @return the action label 591 */ 592 public String getActionLabel(String workflowName, ActionDescriptor action) 593 { 594 I18nizableText label = getActionLabel(action); 595 return _i18nHelper.translateKey(workflowName, label, DEFAULT_ACTION_NAME); 596 } 597 598 /** 599 * Get the action's icon path 600 * @param workflowName name of current workflow 601 * @param action current action 602 * @return the icon's path 603 */ 604 public String getActionIconPath(String workflowName, ActionDescriptor action) 605 { 606 I18nizableText label = getActionLabel(action); 607 label = _workflowSessionHelper.getOldLabelKeyIfCloned(workflowName, label); 608 return _workflowHelper.getElementIconPath(label, __DEFAULT_ACTION_ICON_PATH); 609 } 610 611 /** 612 * Get the action's icon path as base 64 for svg's links 613 * @param workflowName name of current workflow 614 * @param action current action 615 * @return the icon's path as base 64 616 */ 617 public String getActionIconPathAsBase64(String workflowName, ActionDescriptor action) 618 { 619 I18nizableText label = getActionLabel(action); 620 label = _workflowSessionHelper.getOldLabelKeyIfCloned(workflowName, label); 621 return _workflowHelper.getElementIconAsBase64(label, __DEFAULT_SVG_ACTION_ICON_PATH); 622 } 623 624 /** 625 * Get the action label as i18n 626 * @param action the current action 627 * @return the label as i18n 628 */ 629 public I18nizableText getActionLabel(ActionDescriptor action) 630 { 631 return new I18nizableText("application", action.getName()); 632 } 633}