1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
|
package com.c2kernel.lifecycle.instance.stateMachine;
import java.io.Serializable;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.c2kernel.common.AccessRightsException;
import com.c2kernel.common.InvalidDataException;
import com.c2kernel.common.ObjectNotFoundException;
import com.c2kernel.lifecycle.instance.Activity;
import com.c2kernel.lookup.AgentPath;
import com.c2kernel.lookup.RolePath;
import com.c2kernel.persistency.outcome.Schema;
import com.c2kernel.process.Gateway;
import com.c2kernel.utils.CastorHashMap;
import com.c2kernel.utils.LocalObjectLoader;
import com.c2kernel.utils.Logger;
public class Transition implements Serializable {
int id;
String name;
int originStateId;
int targetStateId;
State originState;
State targetState;
String reservation;
String enabledProp; // Boolean property that permits this transition e.g. 'Skippable'
// activation properties
boolean requiresActive = true; // Whether the activity must be active for this transition to be available
boolean finishing; // whether the target state is a finishing state;
// permissions
String roleOverride;
TransitionOutcome outcome;
TransitionScript script;
public Transition() {
}
public Transition(int id, String name, int originStateId, int targetStateId) {
super();
this.id = id;
this.name = name;
this.originStateId = originStateId;
this.targetStateId = targetStateId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public State getOriginState() {
return originState;
}
public void setOriginState(State originState) {
this.originState = originState;
}
public State getTargetState() {
return targetState;
}
public void setTargetState(State targetState) {
this.targetState = targetState;
finishing = targetState.finished;
}
public String getEnabledProp() {
return enabledProp;
}
public void setEnabledProp(String enabledProp) {
this.enabledProp = enabledProp;
}
public boolean isRequiresActive() {
return requiresActive;
}
public boolean isFinishing() {
return finishing;
}
public void setRequiresActive(boolean requiresActive) {
this.requiresActive = requiresActive;
}
public String getRoleOverride() {
return roleOverride;
}
public void setRoleOverride(String roleOverride) {
this.roleOverride = roleOverride;
}
public TransitionOutcome getOutcome() {
return outcome;
}
public void setOutcome(TransitionOutcome outcome) {
this.outcome = outcome;
}
public TransitionScript getScript() {
return script;
}
public void setScript(TransitionScript script) {
this.script = script;
}
public String getReservation() {
return reservation;
}
public void setReservation(String reservation) {
this.reservation = reservation;
}
protected boolean resolveStates(HashMap<Integer, State> states) {
boolean allFound = true;
if (states.keySet().contains(originStateId)) {
originState = states.get(originStateId);
originState.addPossibleTransition(this);
}
else
allFound = false;
if (states.keySet().contains(targetStateId))
targetState = states.get(targetStateId);
else
allFound = false;
return allFound;
}
public int getOriginStateId() {
return originStateId;
}
public void setOriginStateId(int originStateId) {
this.originStateId = originStateId;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getTargetStateId() {
return targetStateId;
}
public void setTargetStateId(int targetStateId) {
this.targetStateId = targetStateId;
}
public String getPerformingRole(Activity act, AgentPath agent) throws ObjectNotFoundException, AccessRightsException {
// check available
if (!isEnabled(act.getProperties()))
throw new AccessRightsException("Transition '"+name+"' is disabled by the '"+enabledProp+"' property.", "");
// check active
if (isRequiresActive() && !act.getActive())
throw new AccessRightsException("Activity must be active to perform this transition", "");
RolePath role = null;
String overridingRole = resolveValue(roleOverride, act.getProperties());
boolean override = overridingRole != null;
boolean isOwner = false, isOwned = true;
// Check agent name
String agentName = act.getCurrentAgentName();
if (agentName != null && agentName.length() >0) {
if (agent.getAgentName().equals(agentName))
isOwner = true;
}
else isOwned = false;
// determine transition role
if (override) {
role = Gateway.getLDAPLookup().getRoleManager().getRolePath(overridingRole);
}
else {
String actRole = act.getCurrentAgentRole();
if (actRole != null && actRole.length() > 0)
role = Gateway.getLDAPLookup().getRoleManager().getRolePath(actRole);
}
// Decide the access
if (isOwned && !override && !isOwner)
throw new AccessRightsException("Agent '"+agent.getAgentName()
+"' cannot perform this transition because the activity '"+act.getName()+"' is currently owned by "+agentName, null);
if (role != null) {
if (agent.hasRole(role))
return role.getName();
else if (agent.hasRole("Admin"))
return "Admin";
else
throw new AccessRightsException("Agent '"+agent.getAgentName()
+"' does not hold a suitable role '"+role.getName()+"' for the activity "+act.getName(), null);
}
else
return null;
}
public String getReservation(Activity act, AgentPath agent) {
if (reservation == null || reservation.length() == 0)
reservation = targetState.finished?"clear":"set";
String reservedAgent = act.getCurrentAgentName();
if (reservation.equals("set"))
reservedAgent = agent.getAgentName();
else if (reservation.equals("clear"))
reservedAgent = "";
return reservedAgent;
}
private static String resolveValue(String key, CastorHashMap props) {
if (key==null) return null;
String result = key;
Pattern propField = Pattern.compile("\\$\\{(.+?)\\}");
Matcher propMatcher = propField.matcher(result);
while (propMatcher.find()) {
String propName = propMatcher.group(1);
Object propValue = props.get(propName);
Logger.msg(8, "Replacing Property "+propName+" as "+propValue);
String propValString = propValue==null?"":propValue.toString();
result = result.replace("${"+propName+"}", propValString);
}
return result;
}
public boolean isEnabled(CastorHashMap props) {
if (enabledProp == null)
return true;
return (Boolean)props.get(enabledProp);
}
public boolean hasOutcome(CastorHashMap actProps) {
if (outcome == null || actProps == null) return false;
String outcomeName = resolveValue(outcome.schemaName, actProps);
if (outcomeName == null || outcomeName.length() == 0)
return false;
String outcomeVersion = resolveValue(outcome.schemaVersion, actProps);
if (outcomeVersion == null || outcomeVersion.length() == 0)
return false;
return true;
}
public Schema getSchema(CastorHashMap actProps) throws InvalidDataException, ObjectNotFoundException {
if (hasOutcome(actProps))
try {
return LocalObjectLoader.getSchema(resolveValue(outcome.schemaName, actProps),
Integer.parseInt(resolveValue(outcome.schemaVersion, actProps)));
} catch (NumberFormatException ex) {
throw new InvalidDataException("Bad schema version number: "+outcome.schemaVersion+" ("+resolveValue(outcome.schemaVersion, actProps)+")", "");
}
else
return null;
}
public String getScriptName(CastorHashMap actProps) {
return resolveValue(script.scriptName, actProps);
}
public int getScriptVersion(CastorHashMap actProps) throws InvalidDataException {
try {
return Integer.parseInt(resolveValue(script.scriptVersion, actProps));
} catch (NumberFormatException ex) {
throw new InvalidDataException("Bad Script version number: "+script.scriptVersion+" ("+resolveValue(script.scriptVersion, actProps)+")", "");
}
}
public boolean hasScript(CastorHashMap actProps) {
if (script == null || actProps == null) return false;
String scriptName = getScriptName(actProps);
if (scriptName == null || scriptName.length() == 0)
return false;
String scriptVersion = resolveValue(script.scriptVersion, actProps);
if (scriptVersion == null || scriptVersion.length() == 0)
return false;
return true;
}
}
|