code: package cgm;
  
  import java.util.HashMap;
  import java.util.Set;
  
  public class Task extends Refinement {
  
  	private HashMap<String, HashMap<Context, Float>> providedQualityLevels;
  	private boolean lessIsMore;
  
  	@Override
  	public int myType() {
  		return Refinement.TASK;
  	}
  
  	public Task(boolean lessIsMore) {
  		providedQualityLevels = new HashMap<String, HashMap<Context, Float>>();
  		this.lessIsMore = lessIsMore;
  	}
  
  	public Task() {
  		providedQualityLevels = new HashMap<String, HashMap<Context, Float>>();
  		this.lessIsMore = false;
  	}
  
  	public void setProvidedQuality(Context context, String metric, double value) {
  		HashMap<Context, Float> map;
  
  		if (providedQualityLevels.containsKey(metric)) {
  			map = providedQualityLevels.get(metric);
  			map.put(context, new Float(value));
  		} else {
  			map = new HashMap<Context, Float>();
  			map.put(context, new Float(value));
  			providedQualityLevels.put(metric, map);
  		}
  	}
  
  	public float myProvidedQuality(String metric, Set<Context> current) throws MetricNotFoundException {
  		float myQuality = 0;
  		boolean set = false;
  
  		if (providedQualityLevels.get(metric) != null && providedQualityLevels.get(metric).containsKey(null)) {
  			myQuality = providedQualityLevels.get(metric).get(null);
  			set = true;
  		}
  		for (Context context : current) {
  			if (providedQualityLevels.get(metric) != null && providedQualityLevels.get(metric).get(context) != null) {
  				if (!set) {
  					myQuality = providedQualityLevels.get(metric).get(context).floatValue();
  					set = true;
  				} else {
  					if (lessIsMore) {
  						if (myQuality > providedQualityLevels.get(metric).get(context).floatValue()) {
  							myQuality = providedQualityLevels.get(metric).get(context).floatValue();
  						}
  					} else if (myQuality < providedQualityLevels.get(metric).get(context).floatValue()) {
  						myQuality = providedQualityLevels.get(metric).get(context).floatValue();
  					}
  				}
  			}
  
  		}
  		if (!set)
  			throw (new MetricNotFoundException());
  		return myQuality;
  	}
  
  	public boolean abidesByInterpretation(Interpretation interp, Set<Context> current) {
  		boolean feasible = true;
  
  		if (interp==null){
  			return true;
  		}
  		for (QualityConstraint qc : interp.getQualityConstraints(current)) {
  			try {
  				if (!qc.abidesByQC(myProvidedQuality(qc.getMetric(), current), qc.getMetric())) {
  					feasible = false;
  				}
  			} catch (MetricNotFoundException e) {
  			}
  		}
  		if (interp.getQualityConstraints(null) != null)
  			for (QualityConstraint qc : interp.getQualityConstraints(null)) {
  				try {
  					if (!qc.abidesByQC(myProvidedQuality(qc.getMetric(), current), qc.getMetric())) {
  						feasible = false;
  					}
  				} catch (MetricNotFoundException e) {
  				}
  			}
  		return feasible;
  	}
  
  	@Override
  	public Plan isAchievable(Set<Context> current, Interpretation interp) {
  		if (!this.isApplicable(current)) {
  			return null;
  		}
  		if (abidesByInterpretation(interp, current)) {
  			return new Plan(this);
  		} else {
  			return null;
  		}
  	}
  }
  