/**
  * Get a {@link DNF} of all the possible output values.
  *
  * @return Disjunction of {@link Reasons}, where each Reason is of size one containing a {@link
  *     Parameter} for an outcome value, and all their names are the outcome name.
  */
 public DNF getOutputsExplanation() {
   DNF outputs = new DNF();
   String outcomeName = enactor.getOutcomeName();
   for (String outcomeValue : enactor.getOutcomeValues()) {
     outputs.add(new Reason(Parameter.instance(outcomeName, outcomeValue)));
   }
   return outputs;
 }
  /**
   * Get the current value of an attribute. This is normally the outcome value (i.e. of the output
   * attribute), but may also refer to an input attribute, depending on the name of the context.
   *
   * @param <T> the type of the value of the context
   * @param context to retrieve the value of, normally the outcome name (i.e. {@link
   *     Enactor#getOutcomeName()}, but may also be an input attribute name.
   * @return Parameter<T> where name is context, and value is of the context
   */
  @SuppressWarnings("unchecked")
  public <T extends Comparable<? super T>> Parameter<T> getWhatExplanation(String context) {
    T value;
    //		System.out.println("context = " + context);
    //		System.out.println("enactor.containsOutAttribute(context) = " +
    // enactor.containsOutAttribute(context));
    //		if (enactor.containsOutAttribute(context)) { // asking What about output
    if (enactor.getOutcomeName().equals(context)) {
      value = (T) enactor.getOutcomeValue();
    } else { // asking What about input
      value = enactor.getInWidgetState().getAttributeValue(context);
    }

    Parameter<T> p = Parameter.instance(context, value);
    return p;
  }
  /**
   * Get the outcome value if an alternative set of input values were provided instead of the
   * current input values.
   *
   * @param <T> the type of the outcome value
   * @param altInputs conjunction of alternative input values to ask about
   * @return Parameter<T> where name is the outcome name, and value is the resulting outcome value.
   */
  @SuppressWarnings("unchecked")
  public <T extends Comparable<? super T>> Parameter<T> getWhatIfExplanation(Reason altInputs) {
    // check which enactorRef has its query satisfied by the widgetState
    String outcomeName = enactor.getOutcomeName();
    String outcomeValue = null;

    // TODO replace by directly crunching through enactor? But need to be non-mutative

    // create modified widget stub from altInputs
    ComponentDescription altWidgetState = enactor.getInWidgetState().clone();
    altWidgetState.addNonConstantAttributes(altInputs.toAttributes()); // to replace some attributes

    for (EnactorReference enactorRef : enactor.getReferences()) {
      AbstractQueryItem<?, ?> query = enactorRef.getConditionQuery();
      Boolean queryResult = query.match(altWidgetState);

      //			System.out.println("getWhatIfExplanation queryResult = " + queryResult);
      //			System.out.println("getWhatIfExplanation enactorRef.getOutcomeValue() = " +
      // enactorRef.getOutcomeValue());
      //			System.out.println("getWhatIfExplanation query = " + query);

      if (queryResult != null && queryResult) {
        // TODO: this is a non-scalable way of handling the special case for sequences
        if (enactorRef instanceof HmmEnactorReference) {
          outcomeValue = ((HmmQueryItem) query).getLastOutcomeValueSequence().toString();
        } else { // Rules or Classifier
          outcomeValue =
              enactorRef
                  .getOutcomeValue(); // this only works for Rule ERs, not classifier, which need to
                                      // set value
        }

        break;
      }
    }

    if (outcomeValue == null) {
      return null;
    } // no rule satisfied by state, so no valid reaction

    // return output of selected enactorRef
    Parameter<T> p = Parameter.instance(outcomeName, (T) outcomeValue);
    return p;
  }
 /**
  * Get the timestamp of when the outcome value of the enactor was changed.
  *
  * @return Parameter<Date> where name is {@link Widget.TIMESTAMP}, and value is a java.util.Date
  */
 protected Parameter<Date> getWhenExplanation() {
   long timestamp = enactor.getInWidgetState().getAttributeValue(Widget.TIMESTAMP);
   Date date = new Date(timestamp);
   Parameter<Date> exp = Parameter.instance(Widget.TIMESTAMP, date);
   return exp;
 }