/* Copyright 2012-2015 SAP SE
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package eu.aniketos.securebpmn.export.aslan.export;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.securebpmn2.ActivityAction;
import org.eclipse.securebpmn2.BindingOfDuty;
import org.eclipse.securebpmn2.Permission;
/**
* Creates the ASLan representation of a SecureBPMN BindingOfDuty element.
*
*
*/
public class BindingOfDutyExport {
/**
* Generates the ASLan representation of the provided BindingOfDuty element
* and sends the output to the provided AslanFileBuilder.
*
* @param bod
* The BindingOfDuty element for which the representation should
* be generated.
* @param afb
* The AslanFileBuilder the output is sent to.
*/
public static void createBindingOfDutyElements(BindingOfDuty bod,
AslanFileBuilder afb) {
if (bod.isDynamicEnforcement())
return;
List<String> assignTasks = new ArrayList<String>();
List<String> claimTasks = new ArrayList<String>();
List<String> completeTasks = new ArrayList<String>();
for (Permission p : bod.getPermissions()) {
if (p.getActions().size() == 0) {
System.err
.println("[WARNING] The permission with name=\""
+ p.getPName()
+ "\" and id=\""
+ p.getId()
+ "\" has no action. This should never happen! Check your .activiti diagram file.");
continue;
}
// Permissions only have one Action
if (p.getActions().get(0) instanceof ActivityAction) {
ActivityAction a = (ActivityAction) p.getActions().get(0);
if (a.getActionName().equals("Complete")) {
completeTasks.add(a.getActivity().getId());
} else if (a.getActionName().equals("Claim")) {
claimTasks.add(a.getActivity().getId());
} else if (a.getActionName().equals("Assign")) {
assignTasks.add(a.getActivity().getId());
} else if (a.getActionName().equals("Full Access")) {
assignTasks.add(a.getActivity().getId());
claimTasks.add(a.getActivity().getId());
completeTasks.add(a.getActivity().getId());
}
}
}
if (assignTasks.size() > 1) {
// TODO what to check? only executed() is persistent...
}
if (claimTasks.size() > 1) {
// TODO what to check? only executed() is persistent...
}
if (completeTasks.size() > 1) {
// safe default assumptions
int maxUsers = 1;
int numActions = completeTasks.size();
if (bod.getMaxUsers() == null) {
System.out
.println("[SCVM-EXPORT-ASLAN] maximum users for BoD \""
+ bod.getId() + "\" not set, using " + maxUsers
+ ".");
} else {
if (bod.getMaxUsers() < 1) {
System.err
.println("[SCVM-EXPORT-ASLAN] invalid input for maximum users at BoD \""
+ bod.getId()
+ "\", using "
+ maxUsers
+ ".");
} else {
maxUsers = bod.getMaxUsers();
}
}
if (bod.getSameUserActionCount() == null) {
System.out
.println("[SCVM-EXPORT-ASLAN] number of actions for BoD \""
+ bod.getId()
+ "\" not set, using "
+ numActions + ".");
} else {
if (bod.getSameUserActionCount() > completeTasks.size()
|| bod.getSameUserActionCount() < 1) {
System.err
.println("[SCVM-EXPORT-ASLAN] invalid input for number of actions at BoD \""
+ bod.getId()
+ "\", using "
+ numActions
+ ".");
} else {
numActions = bod.getSameUserActionCount();
}
}
// calculate numeric partitions
final List<int[]> allPartitions = ExportUtil
.generateIntegerPartitions(completeTasks.size());
// select invalid partitions
List<int[]> selectedPartitions = new ArrayList<int[]>();
for (int[] part : allPartitions) {
boolean invalidSummandFound = false;
for (int i : part) {
if (i != numActions)
invalidSummandFound = true;
}
if (part.length > 0
&& (part.length > maxUsers || invalidSummandFound)) {
selectedPartitions.add(part);
}
}
// create goals for partitions
String[] tasks = new String[completeTasks.size()];
for (int i = 0; i < completeTasks.size(); i++) {
tasks[i] = completeTasks.get(i);
}
List<int[]> permList = ExportUtil
.generateLocationPermutations(tasks.length);
for (int[] part : selectedPartitions) {
// we assume that tasks.lengh equals the sum of each partition
List<List<Set<String>>> sets = new ArrayList<List<Set<String>>>();
// loop over index permutations
for (int[] perm : permList) {
int indexStart = 0;
// list of sets (parts of the partition) for the current
// permutation
List<Set<String>> setList = new ArrayList<Set<String>>();
// create the sets
for (int partLength : part) {
Set<String> partTasks = new HashSet<String>();
// get the tasks and add them to the set
for (int i = 0; i < partLength; i++) {
partTasks.add(tasks[perm[indexStart + i] - 1]);
}
indexStart += partLength;
setList.add(partTasks);
}
// check if partition config already exists
boolean newSet = true;
for (List<Set<String>> presentSetList : sets) {
if (presentSetList.equals(setList)) {
newSet = false;
break;
}
}
// add partition config if new
if (newSet) {
sets.add(setList);
}
}
// create goals for this partition
for (List<Set<String>> setArray : sets) {
// generate goal
int numUsers = setArray.size();
int numTasks = tasks.length;
List<String> natVars = new ArrayList<String>();
StringBuilder goalString = new StringBuilder();
goalString.append("(");
// generate user variables
for (int i = 0; i < numUsers; i++) {
afb.addType("user", "U" + i);
if (i > 0)
goalString.append(",");
goalString.append("U" + i);
}
// generate task nat variables
for (int i = 0; i < numTasks; i++) {
String currentVar = afb.addNatVar();
natVars.add(currentVar);
goalString.append("," + currentVar);
}
goalString.append("):=");
// generate "executed" facts
int natVarPos = 0;
for (int i = 0; i < numUsers; i++) {
for (String currentTask : setArray.get(i)) {
goalString.append(" executed(U" + i + ",task("
+ currentTask + ","
+ natVars.get(natVarPos) + ")).");
natVarPos++;
}
}
// generate "not equal" facts
StringBuilder neqString = new StringBuilder();
for (int i = 0; i < numUsers - 1; i++) {
for (int j = i + 1; j < numUsers; j++) {
neqString.append("& not(equal(U" + i + ",U" + j
+ "))");
}
}
// add goal
String finalGoalString = goalString.toString();
afb.addGoal(
"bod_" + bod.getId() + "_",
finalGoalString.substring(0,
finalGoalString.length() - 1)
+ neqString.toString());
}
}
}
}
}