// The purpose of this behavior file is to process 
// the XML style document that is in program.input
// by using the traversal/visitor style programming
// supported by Demeter/Java.
// We use the generated visitors:
// PrintVisitor, DisplayVisitor, TraceVisitor, CopyVisitor and
// EqualVisitor.
// Instead of generating functions for printing, displaying, tracing,
// copying and comparing, we prefer to generate those visitors
// that you can combine flexibly with the desired traversals.

// We also write our own visitor for summing the quantities
// in a shoe order.

// Finally we show the composition of the SummingVisitor and
// TraceVisitor.

Main {
  public static void main(String args[]) throws Exception (@
    ShoeOrder m = ShoeOrder.parse(System.in);
    System.out.println("Print input: with concrete syntax");
    m.print();
    System.out.println();
    System.out.println("Display input: no concrete syntax");
    m.display();
    System.out.println();
    System.out.println("Show effect of TraceVisitor: where have we been?");
    m.trace();
    System.out.println();
    ShoeOrder s = m.copy();
    System.out.println();
    System.out.println(m);
    System.out.println("Copyed object");
    System.out.println();
    s.display();
    System.out.println();
    System.out.println("Is the copy the same as the original?");
    System.out.println( s.equal(m));
    System.out.println();
    System.out.println("Total");
    System.out.println(s.sum());
    System.out.println("Total with debugging");
    System.out.println(s.sumWithDebugging());
  @)
}

ShoeOrder {
  public void print() = toAll(PrintVisitor);
  public void display() = toAll(DisplayVisitor);
  public void trace() = toAll(TraceVisitor);
  public int sum() = toAllQuantities(SummingVisitor);

  // we don't have to name the traversal!
  // and we can compose visitors, if we like.
  public int sumWithDebugging() to Quantity (SummingVisitor, TraceVisitor);

  public ShoeOrder copy() (@ 
    CopyVisitor cv = new CopyVisitor(ShoeOrder.class);
    this.toAll(cv);
    return (ShoeOrder) cv.get_return_val();
  @)

  public boolean equal(Object o) (@ 
    EqualVisitor ev = new EqualVisitor(o);
    this.toAll(ev);
    return ev.get_return_val();
  @)

  traversal toAll(UniversalVisitor) 
    { to *;}
  traversal toAllQuantities(UniversalVisitor) 
    { to Quantity;}
} 

SummingVisitor {
  init (@ total = 0; @)
  before Quantity (@ System.out.println("sum " + total); 
	total = total + host.get_number().intValue(); @)
  return int (@ total @) 
}