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