CHESSIoT_Dev_old-master/org.polarsys.chess.m2m/src/org/polarsys/chess/m2m/blackbox/VSLUtils.java
/*
-----------------------------------------------------------------------
--          			CHESS M2M plugin							 --
--                                                                   --
--                    Copyright (C) 2011-2012                        --
--                 University of Padova, ITALY                       --
--                                                                   --
-- Author: Alessandro Zovi         azovi@math.unipd.it 		         --
--                                                                   --
-- All rights reserved. This program and the accompanying materials  --
-- are made available under the terms of the Eclipse Public License  --
-- v1.0 which accompanies this distribution, and is available at     --
-- http://www.eclipse.org/legal/epl-v20.html                         --
-----------------------------------------------------------------------
 */

package org.polarsys.chess.m2m.blackbox;

import java.util.ArrayList;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.m2m.qvt.oml.blackbox.java.Operation;
import org.eclipse.m2m.qvt.oml.blackbox.java.Operation.Kind;
import org.eclipse.m2m.qvt.oml.util.IContext;
import org.eclipse.papyrus.MARTE.MARTE_AnalysisModel.SAM.SaSharedResource;
import org.eclipse.papyrus.MARTE.MARTE_DesignModel.SRM.SW_Interaction.SwMutualExclusionResource;
import org.eclipse.papyrus.MARTE.MARTE_Foundations.Alloc.Assign;
import org.eclipse.papyrus.MARTE.MARTE_Foundations.GRM.MutualExclusionResource;
import org.eclipse.papyrus.MARTE.MARTE_Foundations.NFPs.NfpConstraint;
import org.eclipse.papyrus.MARTE_Library.GRM_BasicTypes.ProtectProtocolKind;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.Comment;
import org.eclipse.uml2.uml.Constraint;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.InstanceSpecification;
import org.eclipse.uml2.uml.LiteralString;
import org.eclipse.uml2.uml.Slot;
import org.eclipse.uml2.uml.ValueSpecification;
import org.polarsys.chess.chessmlprofile.Predictability.DeploymentConfiguration.HardwareBaseline.CH_HwProcessor;
import org.polarsys.chess.chessmlprofile.Predictability.RTComponentModel.CHRtSpecification;
import org.polarsys.chess.validator.constraints.StringParser;


/**
 * MARTE VSL utility class for QVT-o transformation.
 */
public class VSLUtils {

	/**
	 * returns the 'pattern' data (MARTE).
	 * 
	 * <p>
	 * i.e. periodic(period=(value=0.6,unit=ms))
	 *
	 * @param context the QVT context
	 * @param self the VSL string to be analyzed
	 * @return the 'pattern' data, or null if no data was found
	 */
	@Operation(kind = Kind.HELPER, contextual = true, withExecutionContext = true)
	public static String getArrivalPatternType(IContext context, String self) {
		String regex = "(\\w*)\\s*\\((.*)\\)";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(self);
		if (matcher.find())
			return matcher.group(1).trim();
		context.getLog().log("No ArrivalPattern detected");
		return null;

	}// end parseArrivalPattern

	/**
	 * Checks if is real number.
	 *
	 * @param n the string to be parsed
	 * @return true, if is real number
	 */
	private static boolean isRealNumber(String n) {
		try {
			Double.parseDouble(n);
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	/**
	 * VSL parsing: receives an NFP_Integer value and parses the selected
	 * property
	 * 
	 * <p>
	 * i.e. (value=6)
	 *
	 * @param context the context
	 * @param self the self
	 * @return the parsed value of the property
	 */
	@Operation(kind = Kind.OPERATION, contextual = true, withExecutionContext = true)
	public static String normalizeNFPInteger(IContext context, String self) {

		if (self == null)
			return "(value = 0)";
		// If it is a shorthand notation, just the number (e.g. "1")
		try {
			return "(value = " + Integer.valueOf(self).toString() + ")";
		} catch (Exception e) {
			// continue with normal parsing
		}
		self = parseGetFirstValidVSL(self);
		if (self == null) {
			return "(value = 0)";
		}

		String regex = "\\(([^\\(\\)]*)\\)"; // same example -> 1:
												// value=2,statQ=min | 2:
												// value=3,statQ=max
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(self);

		if (!matcher.find()) {
			return "MALFORMED INPUT";
		}

		return "(value = " + parseInteger(matcher.group(1), "value") + ")";
	}

	/**
	 * Some properties can store multiple values. This method returns the fist
	 * valid one, in our case: the one with no statQ=calc
	 * 
	 * @param inputText
	 *            text to check
	 * 
	 * @return the first valid VSL expression
	 */
	private static String parseGetFirstValidVSL(String inputText) {
		// e.g. [ (statQ=calc) , ( value =2.0 ), (value= 3.8,statq=calc)] -> (
		// value =2.0 )

		Vector<String> splittedText = new Vector<String>();
		String outText = null;
		if (inputText == null) {
			return null;
		}
		// SPLIT
		String regex = "(\\(.*?\\))"; // ? -> non greedy
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(inputText);
		while (matcher.find()) {
			if (matcher.groupCount() > 0) {
				splittedText.add(matcher.group(1));
			}
		}
		// SELECT FIRST VALID
		if (splittedText == null || splittedText.size() == 0) {
			return null;
		}
		// check if there is one with no statQ=calc
		for (int i = 0; i < splittedText.size(); i++) {
			String inText = splittedText.get(i);
			String regexStatQ = "statQ\\s*=\\s*calc"; // ? -> non greedy
			pattern = Pattern.compile(regexStatQ);
			matcher = pattern.matcher(inText);
			if (!matcher.find()) {
				return inText;
			}
		}// no? -> then, take the first one with statQ=calc
		for (int i = 0; i < splittedText.size(); i++) {
			String inText = splittedText.get(i);
			String regexStatQ = "statQ\\s*=\\s*calc"; // ? -> non greedy
			pattern = Pattern.compile(regexStatQ);
			matcher = pattern.matcher(inText);
			if (matcher.find()) {
				return inText;
			}
		}
		// END
		splittedText.clear();
		return outText;
	}// parseGetFirstValidVSL

	/**
	 * VSL parsing: utility function used by parse_NFPInteger
	 * 
	 * <p>
	 * i.e. [0..34[
	 * 
	 * @param propertiesText
	 *            VSL formatted input string
	 * 
	 * @param propertyName
	 *            "value", "source", "statQ" ...
	 * 
	 * @return the parsed value of the property
	 */
	private static String parseInteger(String propertiesText,
			String propertyName) {

		if (propertiesText == null)
			return "MALFORMED INPUT";

		String regex; // example: value=2,statQ=min
		Pattern pattern;
		Matcher matcher;

		if (propertyName.equals("value")) {

			regex = "\\s*" + propertyName + "\\s*=\\s*(\\d+)";
			pattern = Pattern.compile(regex);
			matcher = pattern.matcher(propertiesText);

			if (!matcher.find()) {
				return "MALFORMED INPUT";
			}

			return matcher.group(1);

		} else if (propertyName.equals("source")) {

			regex = "\\s*source\\s*=\\s*(est|meas|calc|req)";
			pattern = Pattern.compile(regex);
			matcher = pattern.matcher(propertiesText);

			// if(matcher.groupCount()<2)return "NOT FOUND";
			if (!matcher.find()) {
				return "MALFORMED INPUT";
			}

			return matcher.group(1);

		} else if (propertyName.equals("statQ")) {

			regex = "\\s*statQ\\s*=\\s*(min|max)";
			pattern = Pattern.compile(regex);
			matcher = pattern.matcher(propertiesText);

			// if(matcher.groupCount()<2)return "NOT FOUND";
			if (!matcher.find()) {
				return "MALFORMED INPUT";
			}

			return matcher.group(1);

		} else {
			return "NOT IMPLEMENTED";
		}
	}

	/**
	 * VSL parsing: receives an NFP_Duration value and parses the property
	 * selected
	 * 
	 * <p>
	 * i.e. (value=0.6,unit=ms)
	 *
	 * @param context the context
	 * @param self            VSL formatted input string
	 * @param propertyName            property whose value we want
	 * @return the parsed value of the property
	 */
	@Operation(kind = Kind.HELPER, contextual = true, withExecutionContext = true)
	public static String parseNFPDuration(IContext context, String self,
			String propertyName) {

		if (self == null)
			return "MALFORMED INPUT";
		self = parseGetFirstValidVSL(self);
		if (self == null) {
			return "MALFORMED INPUT";
		}

		String regex = "\\((.*)\\)";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(self);
		if (!matcher.find()) {
			context.getLog().log("WARNING: can't parse NFP_Duration ");
			return "MALFORMED INPUT";
		}
		String propertiesText = matcher.group(1);

		if (propertyName.equals("source")) {

			regex = "\\s*source\\s*=\\s*([est|meas|calc|req])";
			pattern = Pattern.compile(regex);
			matcher = pattern.matcher(propertiesText);

			// if(matcher.groupCount()<2)return "NOT FOUND";
			if (!matcher.find()) {
				context.getLog()
						.log("WARNING: NFP_Duration doesn't have a valid value for \"source\" ");
				return "MALFORMED INPUT";
			}

			return matcher.group(1);

		} else if (propertyName.equals("value") || propertyName.equals("best")
				|| propertyName.equals("worst")) {

			// Extract Value
			String theValue, theUnit;
			regex = "\\s*" + propertyName + "\\s*=\\s*(\\d+\\.*\\d*)";
			pattern = Pattern.compile(regex);
			matcher = pattern.matcher(propertiesText);

			// if(matcher.groupCount()<2)return "NOT FOUND";
			if (!matcher.find()) {
				context.getLog().log("WARNING: can't parse NFP_Duration ");
				return "MALFORMED INPUT";
			}

			theValue = matcher.group(1);

			// MAST needs a real value not an integer (if the VSL is correct it
			// should be a real anyway,
			// but I check in case it isn't correctly formed)
			regex = "\\s*" + propertyName + "\\s*=\\s*(\\d+\\.+\\d+)";
			pattern = Pattern.compile(regex);
			matcher = pattern.matcher(propertiesText);
			if (!matcher.find()) {
				theValue += ".0";
			}

			// Extract Units
			regex = "\\s*unit\\s*=\\s*(\\w+)";
			pattern = Pattern.compile(regex);
			matcher = pattern.matcher(propertiesText);
			if (matcher.find()) {
				theUnit = matcher.group(1);
			} else {
				theUnit = "s";
			}

			if (theUnit.equals("s")) {
				return theValue;
			} else if (theUnit.equals("ms")) {
				return theValue + "E-3";
			} else if (theUnit.equals("us")) {
				return theValue + "E-6";
			} else if (theUnit.equals("ns")) {
				return theValue + "E-9";
			}

			context.getLog().log("WARNING: can't parse NFP_Duration ");
			return "MALFORMED INPUT";

		} else {
			context.getLog().log("WARNING: can't parse NFP_Duration ");
			return "NOT IMPLEMENTED";
		}

	}// end parseNFP_Duration

	/**
	 * Parses the nfp real.
	 *
	 * @param context the context
	 * @param self the self
	 * @param propertyName the property name
	 * @return the string
	 */
	@Operation(kind = Kind.OPERATION, contextual = true, withExecutionContext = true)
	public static String parseNFPReal(IContext context, String self,
			String propertyName) {

		if (self == null) {
			return "MALFORMED INPUT";
		}
		// If it is a shorthand notation, just the number (e.g. "1.0")
		try {
			return Double.valueOf(self).toString();
		} catch (Exception e) {
			// continue with normal parsing
		}

		self = parseGetFirstValidVSL(self);
		if (self == null) {
			return "MALFORMED INPUT";
		}

		String regex = "\\((.*)\\)";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(self);
		if (!matcher.find()) {
			return "MALFORMED INPUT";
		}

		if (matcher.groupCount() < 1)
			return "";

		String propertiesText = matcher.group(1);

		regex = "\\s*" + propertyName + "\\s*=\\s*(\\d+\\.*\\d*)";
		pattern = Pattern.compile(regex);
		matcher = pattern.matcher(propertiesText);

		if (!matcher.find()) {
			return "MALFORMED INPUT";
		}

		return matcher.group(1);

	}// end parseNFP_Real

	/**
	 * Sets the ceiling.
	 *
	 * @param context the context
	 * @param self the self
	 * @param ceiling the ceiling
	 */
	@Operation(kind = Kind.OPERATION, contextual = true, withExecutionContext = true)
	public static void setCeiling(IContext context,
			org.eclipse.uml2.uml.Class self, String ceiling) {
		if (ceiling == null)
			return;
		if (ceiling.isEmpty())
			return;
		for (EObject e : self.getStereotypeApplications()) {
			if (e instanceof SaSharedResource) {
				SaSharedResource s = (SaSharedResource) e;

				if (!isRealNumber(ceiling))
					ceiling = parseNFPReal(context, ceiling, "value");
				s.setCeiling(ceiling);
			}
			// else if (e instanceof SwMutualExclusionResource){
			// SwMutualExclusionResource s = (SwMutualExclusionResource) e;
			// if (isRealNumber(ceiling))
			// ceiling = "(value = "+ ceiling +" , source = req)";
			// else
			// ceiling = "(value = "+ parseNFPReal(context, ceiling, "value")
			// +" , source = req)";
			// s.setCeiling(ceiling);
			// }
		}
	}

	/**
	 * Sets the ceiling2.
	 *
	 * @param context the context
	 * @param self the self
	 * @param ceiling the ceiling
	 */
	@Operation(kind = Kind.OPERATION, contextual = true, withExecutionContext = true)
	public static void setCeiling2(IContext context,
			org.eclipse.uml2.uml.Class self, String ceiling) {
		if (ceiling == null)
			return;
		if (ceiling.isEmpty())
			return;
		for (EObject e : self.getStereotypeApplications()) {
			if (e instanceof SwMutualExclusionResource) {
				SwMutualExclusionResource s = (SwMutualExclusionResource) e;
				if (!isRealNumber(ceiling))
					ceiling = parseNFPReal(context, ceiling, "value");
				s.setCeiling(ceiling);
			}
		}
	}

	/**
	 * Sets the ceiling3.
	 *
	 * @param context the context
	 * @param self the self
	 * @param ceiling the ceiling
	 */
	@Operation(kind = Kind.OPERATION, contextual = true, withExecutionContext = true)
	public static void setCeiling3(IContext context,
			org.eclipse.uml2.uml.Class self, String ceiling) {
		if (ceiling == null)
			return;
		if (ceiling.isEmpty())
			return;
		for (EObject e : self.getStereotypeApplications()) {
			if (e instanceof MutualExclusionResource) {
				MutualExclusionResource s = (MutualExclusionResource) e;

				if (!isRealNumber(ceiling))	
					ceiling =parseNFPReal(context, ceiling, "value");
				s.setCeiling(ceiling);
			}
		}
	}

	/**
	 * Sets the protect kind.
	 *
	 * @param context the context
	 * @param self the self
	 * @param type the type
	 */
	@Operation(kind = Kind.OPERATION, contextual = true, withExecutionContext = true)
	public static void setProtectKind(IContext context,
			org.eclipse.uml2.uml.Class self, String type) {
		for (EObject e : self.getStereotypeApplications()) {
			if (e instanceof SaSharedResource) {
				SaSharedResource s = (SaSharedResource) e;
				ProtectProtocolKind a = ProtectProtocolKind.getByName(type);
				s.setProtectKind(a);
			}
			// else if (e instanceof SwMutualExclusionResource){
			// SwMutualExclusionResource s = (SwMutualExclusionResource) e;
			// ProtectProtocolKind a = ProtectProtocolKind.getByName(type);
			// s.setProtectKind(a);
			// }
		}

	}

	/**
	 * Sets the protect kind2.
	 *
	 * @param context the context
	 * @param self the self
	 * @param type the type
	 */
	@Operation(kind = Kind.OPERATION, contextual = true, withExecutionContext = true)
	public static void setProtectKind2(IContext context,
			org.eclipse.uml2.uml.Class self, String type) {
		for (EObject e : self.getStereotypeApplications()) {
			if (e instanceof SwMutualExclusionResource) {
				SwMutualExclusionResource s = (SwMutualExclusionResource) e;
				ProtectProtocolKind a = ProtectProtocolKind.getByName(type);
				s.setProtectKind(a);
			}
		}
	}

	/**
	 * Sets the protect kind3.
	 *
	 * @param context the context
	 * @param self the self
	 * @param type the type
	 */
	@Operation(kind = Kind.OPERATION, contextual = true, withExecutionContext = true)
	public static void setProtectKind3(IContext context,
			org.eclipse.uml2.uml.Class self, String type) {
		for (EObject e : self.getStereotypeApplications()) {
			if (e instanceof MutualExclusionResource) {
				MutualExclusionResource s = (MutualExclusionResource) e;
				ProtectProtocolKind a = ProtectProtocolKind.getByName(type);
				s.setProtectKind(a);
			}
		}
	}

	/**
	 * Port to slots by rule.
	 *
	 * @param context the context
	 * @param self the self
	 * @param onPort the on port
	 * @param rule the rule
	 * @return the e list
	 */
	@Deprecated	
	@Operation(kind = Kind.HELPER, contextual = true, withExecutionContext = true)
	public static EList<Slot> portToSlotsByRule(IContext context,
			org.eclipse.uml2.uml.InstanceSpecification self, org.eclipse.uml2.uml.Port onPort, org.eclipse.uml2.uml.Constraint rule) {
		EList<Slot> list = new BasicEList<Slot>();
		/*
		String values[] = rule.getSpecification().stringValue().trim().split(" ");
		ArrayList<int[]> boundsList = new ArrayList<int[]>();
		for (String value : values) {
			boundsList.add(getBounds(value));
		}
		
		for (Slot slot : self.getSlots()) {
			IdentifSlot id = getStereotypeApplication(slot, IdentifSlot.class);
			
			if (id != null && slot.getDefiningFeature() == onPort && isInBounds(id.getId(), boundsList)) {
				list.add(slot);
			}
			else if (slot.getDefiningFeature() == onPort) {
				list.add(slot);
			}
		}*/
		
		return list;
	}
	
	/**
	 * Gets the slot instances.
	 *
	 * @param context the context
	 * @param self the self
	 * @param inst the inst
	 * @return the slot instances
	 */
	@Operation(kind = Kind.HELPER, contextual = true, withExecutionContext = true)
	public static EList<Slot> getSlotInstances(IContext context,
			org.eclipse.uml2.uml.Comment self,
			org.eclipse.uml2.uml.Package inst) {
		EList<Slot> list = new BasicEList<Slot>();

		Assign ass = getStereotypeApplication(self, Assign.class);
		Slot slotInst = extractFirstSlot(ass.getFrom());
		
		if (slotInst == null)
			return list;

		InstanceSpecification originatingInst = slotInst.getOwningInstance();

		if (!inst.allOwnedElements().contains(slotInst))
			return list;

		EList<Element> asslist = ass.getFrom();
		for (Element elem : asslist){
			list.add((Slot) elem);
		}
		
		return list;
		
		/*
		int[] bounds = getBounds(self);

		if (bounds != null) {
			for (Element el : instFull.allOwnedElements()) {

				IdentifInstance id = getStereotypeApplication(el,
						IdentifInstance.class);

				if (!(el instanceof InstanceSpecification && id != null))
					continue;
				InstanceSpecification y = (InstanceSpecification) el;

				if (isInBounds(id.getId(), bounds)
						&& id.getSourceInstanceSpec() == originatingInst) {

					Slot x = slotFromInstance(slotInst, y);
					if (x != null)
						list.add(x);
				}

			}
		} else {
			for (Element el : instFull.allOwnedElements()) {
				IdentifInstance id = getStereotypeApplication(el,
						IdentifInstance.class);

				if (!(el instanceof InstanceSpecification && id != null && id
						.getSourceInstanceSpec() == originatingInst))
					continue;
				InstanceSpecification y = (InstanceSpecification) el;

				Slot x = slotFromInstance(slotInst, y);
				if (x != null)
					list.add(x);
			}
		}
		return list;
		*/
	}

	/**
	 * Slot from instance.
	 *
	 * @param slotInst the slot inst
	 * @param el the el
	 * @return the slot
	 */
	private static Slot slotFromInstance(Slot slotInst,
			InstanceSpecification el) {
		for (Element e : el.getOwnedElements()) {
			if (!(e instanceof Slot)) continue;
			Slot slot = (Slot) e;
			if(slot.getDefiningFeature().equals(slotInst.getDefiningFeature())){
				return (Slot) e;
			}
		}
		return null;
	}
	
	/**
	 * Gets the instances.
	 *
	 * @param context the context
	 * @param self the self
	 * @param inst the inst
	 * @return the instances
	 */
	@Operation(kind = Kind.HELPER, contextual = true, withExecutionContext = true)
	public static EList<InstanceSpecification> getInstances(IContext context,
			org.eclipse.uml2.uml.Comment self,
			org.eclipse.uml2.uml.Package inst) {
		EList<InstanceSpecification> list = new BasicEList<InstanceSpecification>();

		Assign ass = getStereotypeApplication(self, Assign.class);
		InstanceSpecification originatingInst = extractFirstInstance(ass.getFrom());
		
		if (originatingInst == null)
			return list;
		
//		if (!inst.allOwnedElements().contains(originatingInst))
//			return list;
		
		EList<Element> asslist = ass.getFrom();
		for (Element elem : asslist){
			list.add((InstanceSpecification) elem);
		}
		
		
		return list;
		
		/*
		int[] bounds = getBounds(self);
		
		if (bounds != null)
			for (Element el : instFull.allOwnedElements()) {
				
				IdentifInstance id = getStereotypeApplication(el,
						IdentifInstance.class);
				
				if (el instanceof InstanceSpecification && id != null) {
					if (isInBounds(id.getId(), bounds))
//							&& id.getSourceInstanceSpec() == originatingInst)
						list.add((InstanceSpecification) el);
				}
			}
		else
			for (Element el : instFull.allOwnedElements()) {
				IdentifInstance id = getStereotypeApplication(el,
						IdentifInstance.class);
				if (el instanceof InstanceSpecification && id != null){
//						&& id.getSourceInstanceSpec() == originatingInst) {
					list.add((InstanceSpecification) el);
				}
			}

		return list;*/
	}

//	@Operation(kind = Kind.HELPER, contextual = true, withExecutionContext = true)
//	public static EList<InstanceSpecification> getInstances(IContext context,
//			org.eclipse.uml2.uml.Comment self) {
//		EList<InstanceSpecification> list = new BasicEList<InstanceSpecification>();
//		if (!self.getAnnotatedElements().isEmpty()) {
//			// TODO assumption: one and only nfpConstrant
//			Constraint a = getNfpConstraint(self.getAnnotatedElements());
//			System.out.println(a.getSpecification().stringValue());
//		}
//
//		return list;
//	}
	
	/**
 * Extract first slot.
 *
 * @param from the from
 * @return the slot
 */
private static Slot extractFirstSlot(EList<Element> from) {
		for (Element element : from) {
			if (element instanceof Slot) {
				Slot sl = (Slot) element;
				return sl;
			}
		}
		return null;
	}
	
	/**
	 * Extract first instance.
	 *
	 * @param from the from
	 * @return the instance specification
	 */
	private static InstanceSpecification extractFirstInstance(EList<Element> from) {
		for (Element element : from) {
			if (element instanceof InstanceSpecification) {
				InstanceSpecification is = (InstanceSpecification) element;
				return is;
			}
		}
		return null;
	}

	/**
	 * Checks if is referring id.
	 *
	 * @param context the context
	 * @param self the self
	 * @param id the id
	 * @return the boolean
	 */
	@Operation(kind = Kind.HELPER, contextual = true, withExecutionContext = true)
	public static Boolean isReferringId(IContext context,
			org.eclipse.uml2.uml.Comment self, Integer id) {
		
		int[] bounds = getBounds(self);
		
		//if there are no bounds the comment refers to all the instance ids
		if (bounds == null)
			return true;
		
		return isInBounds(id, bounds);
	}

	/**
	 * Checks if is in bounds.
	 *
	 * @param id the id
	 * @param bounds the bounds
	 * @return the boolean
	 */
	private static Boolean isInBounds(int id, int[] bounds) {
		return id >= bounds[0] && id <= bounds[1];
	}
	
	/**
	 * Checks if is in bounds.
	 *
	 * @param id the id
	 * @param bounds the bounds
	 * @return the boolean
	 */
	private static Boolean isInBounds(int id, java.util.List<int[]> bounds) {
		for (int[] b : bounds) {
			if (isInBounds(id, b))
				return true;
		}
		return false;
	}
	
	/**
	 * Gets the bounds.
	 *
	 * @param comment the comment
	 * @return the bounds
	 */
	private static int[] getBounds(Comment comment) {
		if (!comment.getAnnotatedElements().isEmpty()) {
			// TODO assumption: one and only nfpConstrant
			Constraint a = getNfpConstraint(comment.getAnnotatedElements());
			
			String value = a.getSpecification().stringValue();

			return getBounds(value);
			
		}

		return null;
	}

	//match all variants of "    [  1   ..   10   ]   " result: [1, 10]
	//match all variants of "    [  1   ]   		  " result: [1, 1]
	//match all variants of "      10   			  " result: [10, 10]
	/**
	 * Gets the bounds.
	 *
	 * @param value the value
	 * @return the bounds
	 */
	private static int[] getBounds(String value) {
		String regex = "\\s*\\[\\s*(\\d+)\\s*\\.*\\s*(\\d+)\\]\\s*";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(value);
		int[] b = new int[2];

		if (matcher.find() && matcher.groupCount() == 2) {
			String begin_ = matcher.group(1);
			String end_ = matcher.group(2);
			b[0] = Integer.parseInt(begin_);
			b[1] = Integer.parseInt(end_);
			return b;
		}
		
		regex = "\\s*\\[\\s*(\\d+)\\s*\\]\\s*";
		pattern = Pattern.compile(regex);
		matcher = pattern.matcher(value);
		if (matcher.find() && matcher.groupCount() == 1) {
			String begin_ = matcher.group(1);
			b[0] = Integer.parseInt(begin_);
			b[1] = b[0];
			return b;
		}
		
		regex = "\\s*(\\d+)\\s*";
		pattern = Pattern.compile(regex);
		matcher = pattern.matcher(value);
		if (matcher.find() && matcher.groupCount() == 1) {
			String begin_ = matcher.group(1);
			b[0] = Integer.parseInt(begin_);
			b[1] = b[0];
			return b;
		}
		
		return null;
	}

	/**
	 * Gets the nfp constraint.
	 *
	 * @param list the list
	 * @return the nfp constraint
	 */
	private static Constraint getNfpConstraint(EList<Element> list) {
		for (Element element : list) {
			if (element instanceof Constraint) {
				if (getStereotypeApplication(element, NfpConstraint.class) != null)
					return (Constraint) element;
			}
		}
		return null;
	}
	
	/**
	 * Gets the wcet.
	 *
	 * @param context the context
	 * @param self the self
	 * @return the wcet
	 */
	@Operation(kind = Kind.HELPER, contextual = true, withExecutionContext = true)
	public  static String getWCET(IContext context, Comment self) {
		CHRtSpecification chRtSpecification = getStereotypeApplication(self, CHRtSpecification.class);
		StringParser sp = new StringParser();
		double x = -1;
		String wcet = chRtSpecification.getLocalWCET();
		if(wcet!=null){
			x = sp.getValueNFP(wcet);
		}
		if(x != -1)
			return wcet;
		
		wcet = chRtSpecification.getWCET();
		
		if(wcet!=null){
			x = sp.getValueNFP(wcet);
		}
		if(x != -1)
			return wcet;
		return "ERROR!";
	}

	/**
	 * Gets the stereotype application.
	 *
	 * @param <T> the generic type
	 * @param element the element
	 * @param stereotypeClass the stereotype class
	 * @return the stereotype application
	 */
	@SuppressWarnings("unchecked")
	private static <T extends EObject> T getStereotypeApplication(
			Element element, Class<T> stereotypeClass) {
		for (EObject stereoApplication : element.getStereotypeApplications()) {
			if (stereotypeClass.isInstance(stereoApplication)) {
				return (T) stereoApplication;
			}
		}
		return null;
	}
	
	/**
	 * Gets the number of cores for a given CPU instance. The number of cores is derived from the associated classifier.
	 *
	 * @param context the QVT context
	 * @param cpu the cpu instance
	 * @return the number of cores
	 */
	@Operation(kind = Kind.HELPER, contextual = true, withExecutionContext = true)
	public  static Integer getNumberOfCores(IContext context, InstanceSpecification cpu) {
		Integer i = 1;
		Classifier classifier = cpu.getClassifiers().get(0);
		CH_HwProcessor x = getStereotypeApplication(classifier, CH_HwProcessor.class);
		if(x == null || x.getNbCores() == null)
			return i;

		try {
			i = Integer.parseInt(x.getNbCores());
		} catch (NumberFormatException e) {
			//let it be 1...
		}
		return i;
	}
	
	
	/**
	 * Gets the core (as String) constraining the given <<Assign>> Comment.
	 *
	 * @param context the QVT context
	 * @param self the <<Assign>> Comment
	 * @return the core (as String)
	 */
	@Operation(kind = Kind.HELPER, contextual = true, withExecutionContext = true)
	public  static String getCoreFromContraint(IContext context, Comment self) {
		try {
			Assign assign = getStereotypeApplication(self, Assign.class);
			for (NfpConstraint nfpc : assign.getImpliedConstraint()) {
				Constraint cc = nfpc.getBase_Constraint();
				ValueSpecification spec = cc.getSpecification();
				if(spec.getName().equalsIgnoreCase("core")){
					LiteralString value = (LiteralString) spec;
					return value.getValue();
				}
			}
		} catch (Exception e) {
			//TODO ugly piece of code I know....
		}
		return null;
	}
	
	/**
	 * Gets the supertask (as String) constraining the given <<Assign>> Comment.
	 *
	 * @param context the QVT context
	 * @param self the <<Assign>> Comment
	 * @return the supertask (as String)
	 */
	@Operation(kind = Kind.HELPER, contextual = true, withExecutionContext = true)
	public  static String getSupertaskFromContraint(IContext context, Comment self) {
		try {
			Assign assign = getStereotypeApplication(self, Assign.class);
			for (NfpConstraint nfpc : assign.getImpliedConstraint()) {
				Constraint cc = nfpc.getBase_Constraint();
				ValueSpecification spec = cc.getSpecification();
				if(spec.getName().equalsIgnoreCase("supertask")){
					LiteralString value = (LiteralString) spec;
					return value.getValue();
				}
			}
		} catch (Exception e) {
			//TODO ugly piece of code I know....
		}
		return null;
	}
	
	
	/**
	 * Gets the context from constraint.
	 *
	 * @param context the context
	 * @param self the self
	 * @return the context from constraint
	 */
	@Operation(kind = Kind.HELPER, contextual = true, withExecutionContext = true)
	public  static String getContextFromContraint(IContext context, Comment self) {
		try {
			Assign assign = getStereotypeApplication(self, Assign.class);
			for (NfpConstraint nfpc : assign.getImpliedConstraint()) {
				Constraint cc = nfpc.getBase_Constraint();
				ValueSpecification spec = cc.getSpecification();
				if(spec.getName().equalsIgnoreCase("context")){
					LiteralString value = (LiteralString) spec;
					return value.getValue();
				}
			}
		} catch (Exception e) {
			//TODO ugly piece of code I know....
		}
		return null;
	}
}