/** * */ package org.feature.transform.splot2fm; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import org.apache.log4j.Logger; 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.EPackage; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.emftext.term.propositional.expression.BinaryOperator; import org.emftext.term.propositional.expression.FeatureRef; import org.emftext.term.propositional.expression.Nested; import org.emftext.term.propositional.expression.Not; import org.emftext.term.propositional.expression.Or; import org.emftext.term.propositional.expression.Term; import org.emftext.term.propositional.expression.UnaryOperator; import org.emftext.term.propositional.expression.resource.expression.util.ExpressionResourceUtil; import org.feature.model.utilities.FeatureModelInit; import org.js.model.feature.Constraint; import org.js.model.feature.Feature; import org.js.model.feature.FeatureFactory; import org.js.model.feature.FeaturePackage; import org.js.model.feature.resource.eft.mopp.EftResourceFactory; /** * @author <a href="mailto:info@juliaschroeter.de">Julia Schroeter</a> * */ public class TextExpressionParser { private static Logger log = Logger.getLogger(TextExpressionParser.class); public static Set<Feature> getFeaturesFromTerm(Term term) { Set<Feature> constrainedFeatures = new LinkedHashSet<Feature>(); Set<FeatureRef> references = getFeatureRefsFromTerm(term); for (FeatureRef featureRef : references) { constrainedFeatures.add(featureRef.getFeature()); } return constrainedFeatures; } public static Set<FeatureRef> getFeatureRefsFromTerm(Term term) { Set<FeatureRef> constrainedFeatures = new LinkedHashSet<FeatureRef>(); if (term instanceof BinaryOperator) { BinaryOperator binTerm = (BinaryOperator) term; Term leftTerm = binTerm.getOperand1(); constrainedFeatures.addAll(getFeatureRefsFromTerm(leftTerm)); Term rightTerm = binTerm.getOperand2(); constrainedFeatures.addAll(getFeatureRefsFromTerm(rightTerm)); } else if (term instanceof UnaryOperator) { UnaryOperator unaryTerm = (UnaryOperator) term; Term singleTerm = unaryTerm.getOperand(); constrainedFeatures.addAll(getFeatureRefsFromTerm(singleTerm)); } else if (term instanceof FeatureRef) { FeatureRef featureRefTerm = (FeatureRef) term; constrainedFeatures.add(featureRefTerm); } return constrainedFeatures; } /** * parses a String expression and creates a feature constraint. * @param expression * @param fm * @return */ public static Constraint createFeatureConstraint(String expression, URI modelURI) { Constraint constraint = null; Term term = parseExpression(expression, modelURI); constraint = createExcludes(term); if (constraint == null) { constraint = createRequires(term); } return constraint; } /** * parse a constraint expression and return the term model * * @param expression as String * @param featuremodelURI an uri to create a temporary file from * @return */ private static Term parseExpression(String expression, URI modelURI) { Term term = null; InputStream inputStream = new ByteArrayInputStream(expression.getBytes()); ResourceSet resourceSet = new ResourceSetImpl(); // EPackage.Registry.INSTANCE.put(FeaturePackage.eNS_URI, FeaturePackage.eINSTANCE); resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("eft", new EftResourceFactory()); resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("feature", FeatureFactory.eINSTANCE); if (inputStream != null) { URI uri = modelURI.trimFileExtension().trimFragment(); String uriString = uri.toString(); log.debug("FeaturemodelURI: " + uriString); uri = URI.createURI(uriString); uri = uri.appendFileExtension("_" + inputStream.hashCode()); uri = uri.appendFileExtension("expression"); log.debug("Expression resource created for URI " + uri); Resource resource = resourceSet.createResource(uri); try { resource.load(inputStream, Collections.EMPTY_MAP); EList<EObject> contents = resource.getContents(); // an expression must contain only one Term if (contents.size() == 1 && contents.get(0) instanceof org.emftext.term.propositional.expression.Constraint) { org.emftext.term.propositional.expression.Constraint constraint = (org.emftext.term.propositional.expression.Constraint) contents.get(0); term = constraint.getTerm(); } boolean resolved = ExpressionResourceUtil.resolveAll(resource); if (resolved) { log.debug("All proxies of the expression have been resolved."); } else { // log.warn("Not all proxies of the expression could be resolved."); } } catch (IOException e) { log.warn("Could not load temporary expression resource '" + uri + "'."); } } return term; } private static Constraint createRequires(Feature left, Feature right) { String id = "c_" + "imply" + left.getId() + "_" + right.getId(); return FeatureModelInit.createImplyConstraint(left, right, id); } private static Constraint createExcludes(List<Feature> notFeatures) { Constraint createExclude = null; if (2 == notFeatures.size()) { Feature left = notFeatures.get(0); Feature right = notFeatures.get(1); String id = "c_" + "exclude" + left.getId() + "_" + right.getId(); createExclude = FeatureModelInit.createExcludeConstraint(left, right, id); } return createExclude; } public static Constraint createRequires(Term term) { Feature right = null; Feature left = null; Set<FeatureRef> features = getFeatureRefsFromTerm(term); if (features.size() == 2) { for (FeatureRef featureRef : features) { EObject container = featureRef.eContainer(); if (container instanceof Nested) { container = unnestContainer((Nested) container); } if (container instanceof Not) { left = featureRef.getFeature(); } else if (container instanceof Or) { right = featureRef.getFeature(); } } } return createRequires(left, right); } public static Constraint createExcludes(Term term) { List<Feature> notFeatures = new ArrayList<Feature>(2); Set<FeatureRef> features = getFeatureRefsFromTerm(term); if (features.size() == 2) { for (FeatureRef featureRef : features) { EObject container = featureRef.eContainer(); if (container instanceof Nested) { container = unnestContainer((Nested) container); } if (container instanceof Not) { EObject containerofNot = container.eContainer(); if (containerofNot instanceof Nested) { containerofNot = unnestContainer((Nested) containerofNot); } if (containerofNot instanceof Or) { notFeatures.add(featureRef.getFeature()); } } } } return createExcludes(notFeatures); } private static Term unnestContainer(Nested container) { EObject eContainer = container.eContainer(); if (eContainer instanceof Nested) { return unnestContainer((Nested) eContainer); } Term term = null; if (eContainer != null && eContainer instanceof Term) { term = (Term) eContainer; } return term; } }