package org.feature.model.utilities;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.eclipse.core.resources.IFile;
import org.eclipse.emf.common.util.EList;
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.js.model.feature.Attribute;
import org.js.model.feature.AttributeConstraint;
import org.js.model.feature.AttributeOperand;
import org.js.model.feature.AttributeReference;
import org.js.model.feature.AttributeValue;
import org.js.model.feature.Constraint;
import org.js.model.feature.Domain;
import org.js.model.feature.Feature;
import org.js.model.feature.FeatureConstraint;
import org.js.model.feature.FeatureFactory;
import org.js.model.feature.FeatureModel;
import org.js.model.feature.Group;
import org.js.model.feature.Relop;
import org.js.model.feature.edit.FeatureModelHelper;
public final class FeatureModelInit {
public static String id_prefix = "id_";
public static String attribute_cardinality = "cardinality";
public static String delimiter = "_";
public static String whitespace = " ";
public static String attribute_type_string = "String";
public static String attribute_id = "id";
private static Logger log = Logger.getLogger(FeatureModelInit.class);
/**
* Create the featuremodel and initialize it.
*
* @return
*/
public static FeatureModel initFeatureModel() {
FeatureModel featureModel = FeatureFactory.eINSTANCE.createFeatureModel();
return featureModel;
}
private static Group createFeatureGroup(Feature parentFeature) {
Group newGroup = FeatureFactory.eINSTANCE.createGroup();
EcoreUtil.setID(newGroup, getRandomId());
// newGroup.setId(getRandomId());
parentFeature.getGroups().add(newGroup);
return newGroup;
}
public static Group createFeatureGroup(Feature parentFeature, int min, int max, String id) {
Group group = createFeatureGroup(parentFeature);
// group.setId(id);
EcoreUtil.setID(group, id);
group.setMinCardinality(min);
group.setMaxCardinality(max);
return group;
}
private static Feature createFeature(String name, String id) {
Feature newFeature = FeatureFactory.eINSTANCE.createFeature();
newFeature.setName(name);
// createAttribute(newFeature, attribute_id, id, attribute_type_string);
EcoreUtil.setID(newFeature, id);
// newFeature.setId(id);
return newFeature;
}
/**
* create a feature in a group
*
* @param parent
* @param name
* @param id
* @return
*/
public static Feature createGroupFeature(Group parent, String name, String id) {
Feature newFeature = createFeature(name, id);
Group group = (Group) parent;
group.getChildFeatures().add(newFeature);
return newFeature;
}
/**
* create a feature in a group
*
* @param parent
* @param name
* @param id
* @return
*/
public static Feature createGroupFeature(Feature parent, String name, String id, String groupId) {
Group parentgroup = null;
EList<Group> groups = parent.getGroups();
for (Group group : groups) {
String parentFeatureGroupId = group.getId();
if (groupId.equals(parentFeatureGroupId)){
parentgroup = group;
break;
}
}
return createGroupFeature(parentgroup, name, id);
}
/**
* create a single feature and a single group containing only the single feature.
*
* @param node
* @param name
* @param id
* @param optional
* @return
*/
public static Feature createSingleFeature(Feature parent, String name, String id, boolean optional, String groupId) {
Group group = null;
int min = (optional) ? 0 : 1;
int max = 1;
group = createFeatureGroup(parent, min, max, groupId);
Feature newFeature = createFeature(name, id);
group.getChildFeatures().add(newFeature);
return newFeature;
}
/**
* create a single feature and a single group containing only the single feature.
*
* @param node
* @param name
* @param id
* @param optional
* @return
*/
public static Feature createSingleFeature(Group parent, String name, String id) {
Feature newFeature = createFeature(name, id);
parent.getChildFeatures().add(newFeature);
return newFeature;
}
/**
* create the root feature
*
* @param fm
* @param rootName
* @param id
* @return
*/
public static Feature createRootFeature(FeatureModel fm, String rootName, String id) {
Feature feature = FeatureFactory.eINSTANCE.createFeature();
feature.setName(rootName);
EcoreUtil.setID(feature, id);
// feature.setId(id);
// createAttribute(feature, attribute_id, id, attribute_type_string);
// root feature is mandatory
fm.setRoot(feature);
return feature;
}
/**
* create a new imply constraint
* @param left
* @param right
* @return
*/
public static Constraint createImplyConstraint(Feature left, Feature right, String id){
FeatureConstraint constraint = FeatureFactory.eINSTANCE.createImply();
constraint.setLeftOperand(left);
constraint.setRightOperand(right);
constraint.setId(id);
return constraint;
}
/**
* create a new exclude constraint
* @param left
* @param right
* @return
*/
public static Constraint createExcludeConstraint(Feature left, Feature right, String id){
FeatureConstraint constraint = FeatureFactory.eINSTANCE.createExclude();
constraint.setLeftOperand(left);
constraint.setRightOperand(right);
constraint.setId(id);
return constraint;
}
/**
* create a new Attribute Constraint
* @param left
* @param right
* @param id
* @param operator
* @return
*/
public static Constraint createAttributeConstraint(AttributeOperand left, AttributeOperand right, String id, Relop operator){
AttributeConstraint constraint = FeatureFactory.eINSTANCE.createAttributeConstraint();
constraint.setOperator(operator);
constraint.setLeftOperand(left);
constraint.setRightOperand(right);
constraint.setId(id);
return constraint;
}
public static AttributeOperand createAttibuteOperand(Attribute attribute){
AttributeReference attributeReference = FeatureFactory.eINSTANCE.createAttributeReference();
attributeReference.setAttribute(attribute);
attributeReference.setFeature(attribute.getFeature());
return attributeReference;
}
public static AttributeOperand createAttibuteOperand(String value, int intValue){
AttributeValue attributeValue = FeatureFactory.eINSTANCE.createAttributeValue();
attributeValue.setName(value);
attributeValue.setInt(intValue);
return attributeValue;
}
/**
* save the feature model in the file system.
*
* @param model
* @param fileName
*/
public static void persistFMFeatureModel(FeatureModel model, String fileName) {
ResourceSet set = new ResourceSetImpl();
URI modelURI = URI.createFileURI(fileName);
Resource modelResource = set.createResource(modelURI);
modelResource.getContents().add(model);
try {
modelResource.save(null);
log.info("Featuremodel saved to " + fileName);
ResourceUtil.refreshModelResource(modelResource);
} catch (IOException e) {
log.error("Could not save featuremodel to path " + fileName);
}
}
private static String getRandomId() {
String id = id_prefix;
id += RandomStringUtils.randomNumeric(6);
return id;
}
/**
* add an attribute to a feature.
*
* @param feature
* @param name
* @param value
* @param type
*/
public static void createAttribute(Feature feature, String name, String value, Domain attributeDomain) {
Attribute attribute = FeatureFactory.eINSTANCE.createAttribute();
attribute.setName(name);
attribute.setValue(value);
attribute.setDomain(attributeDomain);
feature.getAttributes().add(attribute);
}
/**
* set an attribute value. if the attribute does not exist, create it.
*
* @param feature
* @param name
* @param value
* @param type
*/
public static void setAttribute(Feature feature, String name, String value, Domain attributeDomain) {
// check if attribute is already available
EList<Attribute> attributes = feature.getAttributes();
boolean attrExists = false;
for (Attribute attribute : attributes) {
String attrName = attribute.getName();
Feature attrFeature = attribute.getFeature();
if (StringUtils.equals(attrName, name) && (EcoreUtil.equals(attrFeature, feature))) {
attribute.setValue(value);
attrExists = true;
break;
}
}
if (!attrExists) {
createAttribute(feature, name, value, attributeDomain);
}
}
public static List<Feature> getAllAchestorFeatures(Feature feature) {
List<Feature> anchestors = new ArrayList<Feature>();
Feature consideredFeature = feature;
while (consideredFeature != null) {
consideredFeature = getParentFeature(consideredFeature);
if (consideredFeature != null) anchestors.add(consideredFeature);
}
return anchestors;
}
/**
* get the parent feature of the given feature. May return null, if the given feature is the root feature.
*
* @param childFeature
* @return
*/
public static Feature getParentFeature(Feature childFeature) {
Feature parentFeature = null;
if (childFeature != null) {
EObject groupContainer = childFeature.eContainer();
if (groupContainer != null && groupContainer instanceof Group) {
Group parentGroup = (Group) groupContainer;
parentFeature = (Feature) parentGroup.eContainer();
}
}
return parentFeature;
}
/**
* get an attribute by its name
*
* @param feature
* @param attributeName
* @return
*/
public static Attribute getAttribute(Feature feature, String attributeName) {
Attribute attribute = null;
EList<Attribute> attributes = feature.getAttributes();
for (Attribute att : attributes) {
String name = att.getName();
if (StringUtils.equals(name, attributeName)) {
attribute = att;
break;
}
}
return attribute;
}
/**
* get all features contained in a feature model.
*
* @param featuremodel
* @return
*/
public static Set<Feature> getAllFeatures(FeatureModel featuremodel) {
FeatureModelHelper helper = new FeatureModelHelper(featuremodel);
return helper.getAllFeatures();
}
/**
* get featuremodel constraints
*
* @param featuremodel
* @param language
* @return
*/
public static List<Constraint> getConstraints(FeatureModel featuremodel, String language) {
return featuremodel.getConstraints();
}
/**
* initialize a featuremodel from an Ifile.
*
* @param file
* @return
*/
public static FeatureModel getFeatureModel(IFile file, ResourceSet resourceSet) {
FeatureModel featuremodel = null;
EObject object = ResourceUtil.getModel(file, resourceSet);
if (object instanceof FeatureModel) {
featuremodel = (FeatureModel) object;
}
return featuremodel;
}
/**
* Makes feature ids unique.
*
* @param allFeatures
*/
public static boolean makeFeatureIdsUnique(Set<Feature> allFeatures) {
boolean isChanged = false;
List<Feature> featuresToCompare = new ArrayList<Feature>(allFeatures.size());
featuresToCompare.addAll(allFeatures);
for (Feature current : allFeatures) {
featuresToCompare.remove(current);
for (Feature next : featuresToCompare) {
String currentFeatureId = current.getId();
String nextFeatureId = next.getId();
if (currentFeatureId.equals(nextFeatureId)) {
int hash = current.hashCode();
currentFeatureId += hash;
log.info("Feature id changed. Was: '" + current.getId() + "' Is: '" + currentFeatureId + "'.");
current.setId(currentFeatureId);
isChanged = true;
break;
}
}
}
return isChanged;
}
/**
* Makes feature names unique.
*
* @param allFeatures
*/
public static boolean makeFeatureIdsUnique(FeatureModel featureModel) {
boolean isChanged = false;
if (featureModel != null) {
Set<Feature> allFeatures = getAllFeatures(featureModel);
isChanged = makeFeatureIdsUnique(allFeatures);
}
return isChanged;
}
}