View Javadoc
1   /*
2    * Copyright (c) 2002-2022, City of Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  /*
35   * To change this license header, choose License Headers in Project Properties.
36   * To change this template file, choose Tools | Templates
37   * and open the template in the editor.
38   */
39  package fr.paris.lutece.plugins.workflow.service;
40  
41  import fr.paris.lutece.plugins.workflowcore.business.workflow.Workflow;
42  import fr.paris.lutece.plugins.workflowcore.business.state.State;
43  import fr.paris.lutece.plugins.workflowcore.business.action.Action;
44  import fr.paris.lutece.plugins.workflowcore.service.task.ITask;
45  
46  /**
47   *
48   * @author seboo
49   */
50  public class WorkflowGraphExportService
51  {
52  
53      private static final String KEY_GRAPH = "graph TD";
54      private static final String KEY_ASSIGN_LABEL_START = "[\"";
55      private static final String KEY_ASSIGN_LABEL_END = "\"]";
56      private static final String KEY_ASSIGN_ACTIONS_START = " --> |\"";
57      private static final String KEY_ASSIGN_ACTIONS_END = "\"| ";
58      private static final String KEY_ASSIGN_ALTERNATIVE_ACTION_PREFIX = "fa:fa-ban ";
59      private static final String KEY_ASSIGN_DEFAULT_ACTION_PREFIX = "fa:fa-check ";
60      private static final String KEY_NEWLINE = "<br /> ";
61      private static final String KEY_CLICK = "click";
62      private static final String STATE_URL_PART = "/jsp/admin/plugins/workflow/ModifyState.jsp?id_state=";
63      private static final String NEWLINE = "\n";
64  
65      /**
66       * Export workflow as Mermaid MD graph
67       * 
68       * @param wf
69       * @param locale
70       * @return the markdown definition of the workflow
71       */
72      public static String generate( Workflow wf, String strBaseUrl )
73      {
74          StringBuilder sb = new StringBuilder( KEY_GRAPH ).append( NEWLINE );
75  
76          // list states
77          for ( State state : wf.getAllStates( ) )
78          {
79              sb.append( state.getId( ) ).append( KEY_ASSIGN_LABEL_START ).append( state.getName( ).replaceAll( "\"", "'" ) ).append( KEY_ASSIGN_LABEL_END )
80                      .append( NEWLINE );
81          }
82  
83          // list actions with tasks
84          for ( Action action : wf.getAllActions( ) )
85          {
86              for ( Integer idState : action.getListIdStateBefore( ) )
87              {
88              	sb.append( idState ).append( KEY_ASSIGN_ACTIONS_START )
89              		.append( getDefaultTransitionType( action ) )
90              		.append( getTransitionLabel( action ) )
91                      .append( KEY_ASSIGN_ACTIONS_END ).append( action.getStateAfter( ).getId( ) ).append( NEWLINE );
92              	
93              	if ( action.getAlternativeStateAfter( ) != null && action.getAlternativeStateAfter( ).getId( ) > 0)
94                  {
95              		sb.append( idState ).append( KEY_ASSIGN_ACTIONS_START )
96  	            		.append( getAlternativeTransitionType( action ) )	
97  	            		.append( getTransitionLabel( action ) )
98  	                    .append( KEY_ASSIGN_ACTIONS_END ).append( action.getAlternativeStateAfter( ).getId( ) ).append( NEWLINE );
99          	
100                 }
101             }
102         }
103 
104         if ( strBaseUrl != null )
105         {
106             // add links
107             for ( State state : wf.getAllStates( ) )
108             {
109                 sb.append( KEY_CLICK ).append( " " ).append( state.getId( ) ).append( " \"" ).append( strBaseUrl ).append( STATE_URL_PART )
110                         .append( state.getId( ) ).append( "\"" ).append( NEWLINE );
111             }
112         }
113 
114         return sb.toString( );
115     }
116 
117     /**
118      * get labels for actions and tasks
119      * 
120      * @param action
121      * @return the label
122      */
123     private static String getTransitionLabel( Action action )
124     {
125         StringBuilder sb = new StringBuilder( action.getName( ) );
126 
127         if ( action.getAllTasks( ) == null )
128             return sb.toString( );
129 
130         for ( ITask task : action.getAllTasks( ) )
131         {
132             sb.append( KEY_NEWLINE ).append( " * " ).append( task.getTaskType( ).getTitle( ) );
133         }
134 
135         return sb.toString( ).replaceAll( "\"", "'" );
136     }
137     
138     private static String getDefaultTransitionType( Action action )
139     {
140     	if ( action.getAlternativeStateAfter( ) != null && action.getAlternativeStateAfter( ).getId( ) > 0)
141     	{
142     		return KEY_ASSIGN_DEFAULT_ACTION_PREFIX ;
143     	}
144     	else
145     	{
146     		return "";
147     	}
148     }
149     
150     private static String getAlternativeTransitionType( Action action )
151     {
152     	if ( action.getAlternativeStateAfter( ) != null && action.getAlternativeStateAfter( ).getId( ) > 0)
153     	{
154     		return KEY_ASSIGN_ALTERNATIVE_ACTION_PREFIX ;
155     	}
156     	else
157     	{
158     		return "";
159     	}
160     }
161 
162 }