package org.js.model.workflow.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.CommonPlugin;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jwt.meta.model.core.Model;
import org.eclipse.jwt.meta.model.core.PackageableElement;
import org.eclipse.jwt.meta.model.processes.Action;
import org.feature.model.utilities.ResourceUtil;
import org.js.graph.transform.stagemodel.StageModel;
import org.js.model.feature.Attribute;
import org.js.model.feature.Constraint;
import org.js.model.feature.Feature;
import org.js.model.feature.FeatureModel;
import org.js.model.feature.FeatureState;
import org.js.model.feature.Imply;
import org.js.model.rbac.AccessControlModel;
import org.js.model.rbac.Role;
import org.js.model.workflow.ACMConnector;
import org.js.model.workflow.EFMContainer;
import org.js.model.workflow.Log;
import org.js.model.workflow.RoleConnector;
import org.js.model.workflow.StagingConnector;
/**
* This class is used as help methods.
*
* @author Xi
*
*
*/
public class WorkflowUtil {
public static final String WORKFLOW_FILE_EXTENSION = "workflow";
public static final String WORKFLOW_VIEW_FILE_EXTENSION = "workflow_view";
public static final String WORKFLOW_CONF_FILE_EXTENSION = "workflow_conf";
public static final int MANDATORY_GROUP = 1;
public static final int OPTINAL_GROUP = 2;
public static final int ALTERNATIVE_GROUP = 3;
public static final int OR_GROUP = 4;
public static URI featureModeluri = null;
/**
* get the workflow view resource for the given workflow resource.
*
* @param workflowResource
* @return workflow view resource
*/
public static Resource getWorkflowViewReousrce(Resource workflowResource) {
URI workflowViewUri = workflowResource.getURI().trimFileExtension().appendFileExtension(WORKFLOW_VIEW_FILE_EXTENSION);
ResourceSet resourceSet = new ResourceSetImpl();
return resourceSet.getResource(workflowViewUri, true);
}
/**
* get the workflow configuration resource for the given workflow resource.
*
* @param workflowResource
* @return workflow configration resource
*/
public static Resource getWorkflowConfReousrce(Resource workflowResource) {
URI workflowConfUri = workflowResource.getURI().trimFileExtension().appendFileExtension(WORKFLOW_CONF_FILE_EXTENSION);
ResourceSet resourceSet = new ResourceSetImpl();
return resourceSet.getResource(workflowConfUri, true);
}
/**
* get the resource for the given uri.
*
* @param uri
* @return
*/
public static Resource getResource(URI uri) {
ResourceSet resourceSet = new ResourceSetImpl();
return resourceSet.getResource(uri, true);
}
/**
* get the resource for the given url.
*
* @param fileresource
* @return
*/
public static Resource getResource(URL fileresource) {
String path = fileresource.getPath();
URI uri = URI.createFileURI(path);
ResourceSet resourceSet = new ResourceSetImpl();
return resourceSet.getResource(uri, true);
}
/**
* get uri for the given file.
*
* @param file
* @return
*/
public static URI getURI(File file) {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IPath location = Path.fromOSString(file.getAbsolutePath());
IFile newFile = workspace.getRoot().getFileForLocation(location);
URI newFileUri = URI.createPlatformResourceURI(newFile.getFullPath().toOSString(), true);
return newFileUri;
}
public static org.eclipse.jwt.meta.model.organisations.Role getWorkflowRole(Role role, Model workflow) {
org.eclipse.jwt.meta.model.organisations.Role workflowRole = null;
EList<PackageableElement> workflowElements = workflow.getElements();
stop: for (PackageableElement packageableElement : workflowElements) {
if (packageableElement instanceof org.eclipse.jwt.meta.model.organisations.Role) {
org.eclipse.jwt.meta.model.organisations.Role jwtRole = (org.eclipse.jwt.meta.model.organisations.Role) packageableElement;
RoleConnector connector = (RoleConnector) WorkflowConfUtil.getAspectInstance(jwtRole, WorkflowConfUtil.ROLE_ASPECT);
Role referencedRole = connector.getRoleref();
if (EcoreUtil.equals(referencedRole, role)) {
workflowRole = jwtRole;
break stop;
}
}
}
return workflowRole;
}
/**
* store the stakeholder's inputs temporarily.
*
* @param stakeholderName
* @param stakeholderTypeName
* @param stakeholderGroupName
* @param acm
* @param shTypes
* @return
*/
public static StakeholderInput analyzeShInput(String stakeholderName, String stakeholderTypeName, String stakeholderGroupName,
AccessControlModel acm, EList<org.js.model.rbac.Role> shTypes) {
org.js.model.rbac.Role stakeholderType = null;
org.js.model.rbac.Role stakeholderGroupLeader = null;
for (org.js.model.rbac.Role role : shTypes) {
if (role.getId().equals(stakeholderTypeName)) {
stakeholderType = role;
break;
}
}
// for (Group group : acm.getGroups()) {
// if (group.getRepresents().getId().equals(stakeholderGroupName)) {
// stakeholderGroupLeader = group.getRepresents();
// break;
// }
// }
for (org.js.model.rbac.Role role : acm.getRoles()) {
if (role.getId().equals(stakeholderGroupName)) {
stakeholderGroupLeader = role;
break;
}
}
return new StakeholderInput(stakeholderName, stakeholderType, stakeholderGroupLeader);
}
public static org.js.model.rbac.Role getRBACRole(Model model, String name) {
AccessControlModel acm = getAccessControlModel(model);
return getRBACRole(acm, name);
}
public static AccessControlModel getAccessControlModel(Model workflow) {
ACMConnector acmConnector = (ACMConnector) WorkflowConfUtil.getAspectInstance(workflow, WorkflowConfUtil.ACM_ASPECT);
AccessControlModel acm = acmConnector.getAcmref();
return acm;
}
public static StageModel getStageModel(Model workflow) {
StagingConnector stagingConnector =
(StagingConnector) WorkflowConfUtil.getAspectInstance(workflow, WorkflowConfUtil.STAGEMODEL_ASPECT);
StageModel sm = stagingConnector.getStageModel();
return sm;
}
/**
* get the role in acm with the given name.
*
* @param acm
* @param name
* @return
*/
public static org.js.model.rbac.Role getRBACRole(AccessControlModel acm, String name) {
EList<org.js.model.rbac.Role> roles = acm.getRoles();
for (org.js.model.rbac.Role role : roles) {
if (role.getId().equals(name)) {
return role;
}
}
return null;
}
/**
* get the role referenced by the given action.
*
* @param action
* @return
*/
public static org.js.model.rbac.Role getRBACRole(Action action) {
RoleConnector roleConnector = null;
if (action.getPerformedBy() != null) {
roleConnector =
((RoleConnector) WorkflowConfUtil.getAspectInstance(((Action) action).getPerformedBy(), WorkflowConfUtil.ROLE_ASPECT));
}
if (roleConnector != null && roleConnector.getRoleref() != null) {
return roleConnector.getRoleref();
}
return null;
}
/**
* copy a file.
*
* @param oldPath
* @param newPath
* @return
*/
public static File copyFile(String oldPath, String newPath) {
try {
int byteread = 0;
File oldfile = new File(oldPath);
if (oldfile.exists()) {
InputStream inStream = new FileInputStream(oldPath);
FileOutputStream fs = new FileOutputStream(newPath);
byte[] buffer = new byte[1444];
while ((byteread = inStream.read(buffer)) != -1) {
fs.write(buffer, 0, byteread);
}
inStream.close();
return new File(newPath);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* get the efm model from the given uri.
*
* @param uri
* @return
*/
public static FeatureModel getFeatureModel(URI uri) {
ResourceSet resourceSet = new ResourceSetImpl();
Resource rbacRes = resourceSet.getResource(uri, true);
try {
rbacRes.load(Collections.EMPTY_MAP);
} catch (IOException e) {
e.printStackTrace();
}
TreeIterator<EObject> rbacIt = rbacRes.getAllContents();
FeatureModel fm = null;
while (rbacIt.hasNext()) {
EObject object = rbacIt.next();
if (object instanceof FeatureModel) {
fm = (FeatureModel) object;
}
}
return fm;
}
/**
* handle the relation and constraint of the given feature in the efm.
*
* @param feauture
* @param featureModel
*/
public static void handleFeatureLogic(Feature feature, FeatureModel featureModel) {
// if the feature is selected
if (feature.getConfigurationState().equals(FeatureState.SELECTED)) {
for (org.js.model.feature.Group group : feature.getGroups()) {
// if feature is mandatory
if (group.getMinCardinality() * group.getMaxCardinality() == 1) {
if (group.getChildFeatures().size() == 1) {
Feature subFeature = group.getChildFeatures().get(0);
subFeature.setConfigurationState(FeatureState.SELECTED);
handleFeatureLogic(subFeature, featureModel);
}
}
}
for (Constraint constraint : featureModel.getConstraints()) {
// TODO: here only implies express is handled, we still need to
// handle the other expresses
if (constraint instanceof Imply) {
Imply expression = (Imply) constraint;
if (expression.getLeftOperand() instanceof Feature) {
Feature operand1 = expression.getLeftOperand();
if (operand1.getId().equals(feature.getId())) {
Feature operand2 = expression.getRightOperand();
operand2.setConfigurationState(FeatureState.SELECTED);
handleFeatureLogic(operand2, featureModel);
}
}
}
}
} else {
// if the feature is deselected
for (org.js.model.feature.Group group : feature.getGroups()) {
for (Feature subFeature : group.getChildFeatures()) {
subFeature.setConfigurationState(FeatureState.DESELECTED);
handleFeatureLogic(subFeature, featureModel);
}
}
for (Constraint contraint : featureModel.getConstraints()) {
// TODO: here only implies express is handled, we still need to
// handle the other expresses
if (contraint instanceof Imply) {
Imply expression = (Imply) contraint;
Feature operand2 = expression.getRightOperand();
if (operand2.getId().equals(feature.getId())) {
Feature operand1 = expression.getLeftOperand();
operand1.setConfigurationState(FeatureState.DESELECTED);
handleFeatureLogic(operand1, featureModel);
}
}
}
}
}
/**
* save stakeholder's configuration into the feature model.
*
* @param log
* @param featureModel
*/
public static void handleFM(Log log, FeatureModel featureModel) {
// for (ConfigurationOperation configDecision : log.getConfigurationOperations()) {
// if (configDecision instanceof FeatureOperation) {
// Feature feature = ReferenceResolverUtil.findFeature(((FeatureOperation) configDecision).getFeature().getId(),
// featureModel);
// if (RbacHelper.isSelectFeatureOperation(configDecision)) {
// feature.setConfigurationState(FeatureState.SELECTED);
// } else {
// feature.setConfigurationState(FeatureState.DESELECTED);
// }
// // handleFeatureLogic(feature, featureModel);
// } else {
// if (RbacHelper.isSelectDomainValueOperation(configDecision)) {
// AttributeValueOperation operation = ((AttributeValueOperation) configDecision);
// Attribute oldAttribute = operation.getAttribute();
// String attributeName = oldAttribute.getName();
// String featureName = oldAttribute.getFeature().getId();
// Feature newFeature = ReferenceResolverUtil.findFeature(featureName, featureModel);
// Attribute newAttribute = ReferenceResolverUtil.findAttributeForFeature(attributeName, newFeature);
// int value = operation.getValue();
// String valueString = FeatureModelHelper.getAttributeValue(value, operation.getAttribute());
// newAttribute.setValue(valueString);
// }
// }
// }
URI uri = featureModel.eResource().getURI();
ResourceUtil.persistModel(featureModel, uri);
}
/**
* get the group which contains the given feature.
*
* @param feature
* @param root
* @return
*/
public static org.js.model.feature.Group getGroup(Feature feature, Feature root) {
org.js.model.feature.Group featureGroup = null;
for (org.js.model.feature.Group group : root.getGroups()) {
if (group.getChildFeatures().contains(feature)) {
return group;
} else {
for (Feature subFeature : group.getChildFeatures()) {
featureGroup = getGroup(feature, subFeature);
if (featureGroup != null) {
return featureGroup;
}
}
}
}
return null;
}
/**
* get the group which contains the given feature.
*
* @param feature
* @param featureModel
* @return
*/
public static org.js.model.feature.Group getGroup(Feature feature, FeatureModel featureModel) {
return getGroup(feature, featureModel.getRoot());
}
/**
* get the group type.
*
* @param group
* @return
*/
public static int getGroupType(org.js.model.feature.Group group) {
int type = 0;
int minCard = group.getMinCardinality();
int maxCard = group.getMaxCardinality();
int size = group.getChildFeatures().size();
if (minCard * maxCard == 1) {
if (size == 1) {
type = MANDATORY_GROUP;
} else {
type = ALTERNATIVE_GROUP;
}
} else if (minCard == 0 && maxCard == 1 && size == 1) {
type = OPTINAL_GROUP;
} else if (minCard == 1 && maxCard == size && size > 1) {
type = OR_GROUP;
}
return type;
}
/**
* get the direct parent feature of the given child feature.
*
* @param childFeature
* @param root
* @return
*/
public static Feature getParentFeature(Feature childFeature, Feature root) {
Feature parentFeature = null;
for (org.js.model.feature.Group group : root.getGroups()) {
for (Feature feature : group.getChildFeatures()) {
if (feature == childFeature) {
parentFeature = root;
return parentFeature;
} else {
parentFeature = getParentFeature(childFeature, feature);
if (parentFeature != null) {
return parentFeature;
}
}
}
}
return null;
}
/**
* get all parent features of the given feature.
*
* @param childFeature
* @param featureModel
* @return
*/
public static ArrayList<Feature> getParentFeatures(Feature childFeature, FeatureModel featureModel) {
ArrayList<Feature> parentFeatures = new ArrayList<Feature>();
Feature parentFeature = getParentFeature(childFeature, featureModel.getRoot());
while (parentFeature != null) {
parentFeatures.add(parentFeature);
parentFeature = getParentFeature(parentFeature, featureModel.getRoot());
}
return parentFeatures;
}
/**
* get all mandatory features of the given feature.
*
* @param childFeature
* @return
*/
public static ArrayList<Feature> getMandatoryChildFeatures(Feature childFeature) {
ArrayList<Feature> mandarotyChildFeatures = new ArrayList<Feature>();
for (org.js.model.feature.Group group : childFeature.getGroups()) {
if (WorkflowUtil.getGroupType(group) == WorkflowUtil.MANDATORY_GROUP) {
for (Feature feature : group.getChildFeatures()) {
mandarotyChildFeatures.add(feature);
mandarotyChildFeatures.addAll(getMandatoryChildFeatures(feature));
}
}
}
return mandarotyChildFeatures;
}
/**
* get all child features of the given feature.
*
* @param childFeature
* @return
*/
public static ArrayList<Feature> getChildFeatures(Feature childFeature) {
ArrayList<Feature> childFeatures = new ArrayList<Feature>();
for (org.js.model.feature.Group group : childFeature.getGroups()) {
for (Feature feature : group.getChildFeatures()) {
childFeatures.add(feature);
childFeatures.addAll(getChildFeatures(feature));
}
}
return childFeatures;
}
/**
* get all features that are in the same group.
*
* @param feature
* @param featureModel
* @return
*/
public static ArrayList<Feature> getGroupFeatures(Feature feature, FeatureModel featureModel) {
ArrayList<Feature> groupFeatures = new ArrayList<Feature>();
org.js.model.feature.Group group = getGroup(feature, featureModel.getRoot());
if (group != null) {
groupFeatures.addAll(group.getChildFeatures());
}
return groupFeatures;
}
/**
* get all right operands which are included in the implies constraints.
*
* @param feature
* @param featureModel
* @return
*/
public static ArrayList<Feature> getImpliesConstraintRightOperands(Feature feature, FeatureModel featureModel) {
ArrayList<Feature> constraintFeatures = new ArrayList<Feature>();
EList<Constraint> constraints = featureModel.getConstraints();
for (Constraint constraint : constraints) {
if (constraint instanceof Imply) {
Imply expression = (Imply) constraint;
Feature operand1 = expression.getLeftOperand();
if (operand1.getId().equals(feature.getId())) {
Feature operand2 = expression.getRightOperand();
constraintFeatures.add(operand2);
}
}
}
return constraintFeatures;
}
/**
* get all left operands which are included in the implies constraints.
*
* @param feature
* @param featureModel
* @return
*/
public static ArrayList<Feature> getImpliesConstraintLeftOperands(Feature feature, FeatureModel featureModel) {
ArrayList<Feature> constraintFeatures = new ArrayList<Feature>();
EList<Constraint> constraints = featureModel.getConstraints();
for (Constraint constraint : constraints) {
if (constraint instanceof Imply) {
Imply expression = (Imply) constraint;
Feature operand2 = expression.getRightOperand();
if (operand2.getId().equals(feature.getId())) {
Feature operand1 = expression.getLeftOperand();
constraintFeatures.add(operand1);
}
}
}
return constraintFeatures;
}
/**
* trace the configured efm of the previous action
*
* @param workflowModel
* @param role
* @param action
* @return feature model
*/
public static FeatureModel tracePreEFM(Model workflowModel, Role role, Action action) {
Action preAction = WorkflowModelUtil.getPrecedeAction(action);
FeatureModel oldFM = null;
if (preAction == null) { // it is the first enabled action
// get original efm
ACMConnector acmConnector = (ACMConnector) WorkflowConfUtil.getAspectInstance(workflowModel, WorkflowConfUtil.ACM_ASPECT);
AccessControlModel acm = acmConnector.getAcmref();
oldFM = acm.getFeatureModel();
} else {
// get the efm of previous action
EFMContainer efmContainer = (EFMContainer) WorkflowConfUtil.getAspectInstance(preAction, WorkflowConfUtil.EFM_ASPECT);
oldFM = efmContainer.getEfmref();
}
// copy efm file for the added action
URI oldFMUri = oldFM.eResource().getURI();
String oldFileName = oldFMUri.lastSegment();
URI resolvedFile = CommonPlugin.resolve(oldFMUri);
IFile oldFile = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(resolvedFile.toFileString()));
String oldFilePath = oldFile.getFullPath().toString();
String newFileName = role.getId() + "." + oldFMUri.fileExtension();
String newFilePath = oldFilePath.replace(oldFileName, newFileName);
File newFile = WorkflowUtil.copyFile(oldFilePath, newFilePath);
// get the uri of the added file
URI newFileUri = WorkflowUtil.getURI(newFile);
// add efm reference
FeatureModel newFM = WorkflowUtil.getFeatureModel(newFileUri);
EFMContainer efmContainer = (EFMContainer) WorkflowConfUtil.getAspectInstance(action, WorkflowConfUtil.EFM_ASPECT);
if (newFM == null) {
System.out.println("the previuos action has no efm!");
} else {
WorkflowConfUtil.setEFM(efmContainer, newFM);
}
return newFM;
}
/**
* get all features of the given feature model.
*
* @param featureModel
* @return
*/
public static ArrayList<Feature> getFeatures(FeatureModel featureModel) {
ArrayList<Feature> features = new ArrayList<Feature>();
features.add(featureModel.getRoot());
features.addAll(getChildFeatures(featureModel.getRoot()));
return features;
}
/**
* get all attributes of features in the given feature model.
*
* @param feaureModel
* @return
*/
public static ArrayList<Attribute> getAttributes(FeatureModel feaureModel) {
ArrayList<Attribute> attributes = new ArrayList<Attribute>();
for (Feature feature : getFeatures(feaureModel)) {
if (feature.getAttributes().size() > 0) {
attributes.addAll(feature.getAttributes());
}
}
return attributes;
}
public static org.eclipse.jwt.meta.model.organisations.Role getRole(Model workflow, Action action) {
org.eclipse.jwt.meta.model.organisations.Role workflowRole = null;
Role rbacRole = getRBACRole(action);
if (rbacRole != null) {
workflowRole = WorkflowModelUtil.getRole(workflow, rbacRole.getId());
}
return workflowRole;
}
}