package context.arch.intelligibility.presenters; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang.StringUtils; import context.arch.enactor.Enactor; import context.arch.intelligibility.Explanation; import context.arch.intelligibility.expression.Comparison; import context.arch.intelligibility.expression.DNF; import context.arch.intelligibility.expression.Expression; import context.arch.intelligibility.expression.Negated; import context.arch.intelligibility.expression.Parameter; import context.arch.intelligibility.expression.Reason; import context.arch.intelligibility.query.Query; /** * A basic {@link Presenter} that renders {@link Explanation} based on its content {@link DNF}. * If renders each explanation as a String. It only handles the content {@link Expression} * based on whether it is a DNF, {@link Reason} or {@link Parameter}. * @author Brian Y. Lim * * @see Presenter * @see Explanation * @see Expression * @see DNF * @see Enactor */ public class StringPresenter extends Presenter<String> { /** * Creates a StringPresenter associated to an enactor * @param enactor to get its {@link Explainer} from. */ public StringPresenter(Enactor enactor) { super(enactor); } @Override public String render(Explanation explanation) { Query query = explanation.getQuery(); String question = query.getQuestion(); DNF expression = explanation.getContent(); String text; if (question == null) { text = ""; // empty } text = renderDNF(expression); return text.trim(); } /** * Root method for rendering an explanation content. * @param dnf from {@link Explanation#getContent()} * @return the full string representation of the expression. */ protected String renderDNF(DNF dnf) { List<String> reasons = new ArrayList<String>(); for (Reason reason : dnf) { reasons.add(renderReason(reason)); } final String separator = System.getProperty("line.separator") + "or"; return StringUtils.join(reasons, separator); } /** * Render a single reason in the explanation content. * @param conjunction from a {@link DNF} * @return the string representation of this single reason */ protected String renderReason(Reason conjunction) { String s = ""; int i = 0; for (Parameter<?> exp : conjunction) { s += System.getProperty("line.separator") + ++i + ") " + renderLiteral(exp); } return s; } /** * Render a single literal in a {@link Reason}. * @param literal from a Reason. * @return the string representation of this single literal. */ protected String renderLiteral(Parameter<?> literal) { if (literal instanceof Comparison<?>) { Comparison<?> c = (Comparison<?>)literal; return c.toPrettyString(descExplainer); } else if (literal instanceof Negated<?>) { return "not " + ((Negated<?>)literal).getChildExpression().toPrettyString(descExplainer); } else if (literal instanceof Parameter<?>) { Parameter<?> p = (Parameter<?>)literal; // String context = p.getName(); // if (p.getValue() == null) { return descExplainer.getPrettyName(context); } // return descExplainer.getPrettyName(context) + // " is " + // descExplainer.getPrettyValue(context, p.getValue().toString()) + // descExplainer.getUnit(context); return p.toPrettyString(descExplainer); } return literal.toString(); } }