/*
-----------------------------------------------------------------------
--          			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;
	}
}