out.println("  public double getValue(int unit1, int unit2) {"); out.println("    if (unit1 >= 0 && unit1 <= "+dC+".MAXUNIT &&\n"+
println(out,"  public double getValue(int unit1, int unit2) {"); println(out,"    if (unit1 >= 0 && unit1 <= "+dC+".MAXUNIT &&\n"+
    void writeClassDt(PrintWriter out, String context, String className) {      Vector mV = explodeC(p.get(context,"derivative"), '/');      final String dC = (String) mV.elementAt(0);      final String dtC = (String) mV.elementAt(1);      String dB = getBaseUnit(dC);      String dtB = getBaseUnit(dtC);      String baseabbrev = p.get(context, "baseabbrev");      if (baseabbrev == null) {        String ab1 = p.get(dC,"baseabbrev");        if (ab1 == null) ab1 = dB;        String ab2 = p.get(dtC,"baseabbrev");        if (ab2 == null) ab2 = dtB;        baseabbrev=ab1+"/"+ab2;      }      class UnitTuple {        String num;        String den;        String sden;        double factor;        UnitTuple(String n, String d) {          num = n;          den = d;          sden = unpluralize(den);          double nF = computeToFactor(dC,n);          double dF = computeToFactor(dtC, d);          factor = nF/dF;        }      }            ArrayList tuples = new ArrayList();      Vector numV = getUnitV(dC);      Vector denV = getUnitV(dtC);      for (Enumeration nE = numV.elements(); nE.hasMoreElements();) {        String nU = (String) nE.nextElement();        for (Enumeration dE = denV.elements(); dE.hasMoreElements();) {          String dU = (String) dE.nextElement();          tuples.add(new UnitTuple(nU,dU));        }      }      String isDep = p.get(context,"deprecated");      if (isDep!=null) {        out.println("/** @deprecated "+isDep+" **/");      }      // the class def      String ext = p.get(context,"extends");      if (ext == null) ext = "AbstractMeasure";      out.println("public final class "+className+" extends "+ext);      out.print("  implements Externalizable, Derivative");      String denC = p.get(dtC,"denominator_class");      if (denC != null) {        out.print(", "+denC);      }      out.println(" {");            // the storage      out.println("  // the value is stored as "+dB+"/"+unpluralize(dtB));      out.println("  private double theValue;");      out.println();      out.println("  /** No-arg constructor is only for use by serialization **/");      out.println("  public "+className+"() {}");      out.println();      // constructor      out.println("  // private constructor");      out.println("  private "+className+"(double v) {");      out.println("    theValue = v;");      out.println("  }");      out.println();      // public constructor      out.println("  /** @param unit One of the constant units of "+className+" **/");      out.println("  public "+className+"(double v, int unit) {");      out.println("    if (unit >= 0 && unit <= MAXUNIT)");      out.println("      theValue = v/convFactor[unit];");      out.println("    else");      out.println("      throw new UnknownUnitException();");      out.println("  }");      out.println();      out.println("  /** @param unit1 One of the constant units of "+dC+"\n"+                  "   *  @param unit2 One of the constant units of "+dtC+"\n"+                  "   **/");      out.println("  public "+className+"(double v, int unit1, int unit2) {");      out.println("    if (unit1 >= 0 && unit1 <= "+dC+".MAXUNIT &&\n"+                  "        unit2 >= 0 && unit2 <= "+dtC+".MAXUNIT)");      out.println("      theValue = v*"+dC+".convFactor[unit1]/"+dtC+".convFactor[unit2];");      out.println("    else");      out.println("      throw new UnknownUnitException();");      out.println("  }");      out.println();      out.println("  /** @param num An instance of "+dC+" to use as numerator\n"+                  "   *  @param den An instance of "+dtC+"to use as denominator\n"+                  "   **/");      out.println("  public "+className+"("+dC+" num, "+dtC+" den) {");      out.println("    theValue = num.getValue(0)/den.getValue(0);");      out.println("  }");      out.println();      out.println("  /** takes strings of the form \"Number unit\" **/");      out.println("  public "+className+"(String s) {");      out.println("    int i = indexOfType(s);");      out.println("    if (i < 0) throw new UnknownUnitException();");      out.println("    double n = Double.valueOf(s.substring(0,i).trim()).doubleValue();");      out.println("    String u = s.substring(i).trim().toLowerCase();");      out.print("    ");      for (Iterator ti = tuples.iterator(); ti.hasNext(); ) {        UnitTuple ut = (UnitTuple) ti.next();        out.println("if (u.equals(\""+                    toClassName(ut.num+"per"+ut.sden).toLowerCase()+                    "\")) ");        out.println("      theValue=n/"+ut.factor+";");        out.print("    else ");      }      out.println("\n      throw new UnknownUnitException();");      out.println("  }");      out.println();      // Named type factory methods      out.println("  // TypeNamed factory methods");      for (Iterator ti = tuples.iterator(); ti.hasNext(); ) {        UnitTuple ut = (UnitTuple) ti.next();        String unit = ut.num+"_per_"+ut.sden;        String unitName = toClassName(unit);        String fexpr="*"+(1.0/ut.factor)+"";        out.println("  public static final "+className+" new"+unitName+"(double v) {");        out.println("    return new "+className+"(v"+fexpr+");");        out.println("  }");        out.println("  public static final "+className+" new"+unitName+"(String s) {");        out.println("    return new "+className+"((Double.valueOf(s).doubleValue())"+fexpr+");");        out.println("  }");      }      out.println();      // common unit support - mostly a bogon      out.println();      out.println("  public int getCommonUnit() {");      String cus = p.get(context, "common");      if (cus == null) {         out.println("    return 0;");      } else {                Vector v = explodeC(cus,'/');        String n=(String)v.elementAt(0);        String d=(String)v.elementAt(1);        int i = 0;        for (Iterator ti = tuples.iterator(); ti.hasNext(); ) {          UnitTuple ut = (UnitTuple)ti.next();          if (n.equals(ut.num) && d.equals(ut.sden)) {            out.println("    return "+i+";");            break;          }          i++;        }        if (i==tuples.size()){          System.err.println("Couldn't find a matching tuple for \""+cus+"\".");          out.println("     return 0;");        }      }      out.println("  }");      out.println();      out.println("  public int getMaxUnit() { return MAXUNIT; }");      out.println();      out.println("  // unit names for getUnitName");      out.println("  private static final String unitNames[]={");      for (Iterator ti = tuples.iterator(); ti.hasNext(); ) {        UnitTuple ut = (UnitTuple)ti.next();        String unit = ut.num+"/"+ut.sden;        out.print("    \""+unit+"\"");        if (ti.hasNext())          out.println(",");        else          out.println();      }      out.println("  };");      out.println();      out.println("  /** @param unit One of the constant units of "+className+" **/");      out.println("  public final String getUnitName(int unit) {");      out.println("    return unitNames[unit];");      out.println("  }");      out.println();      // index typed factory methods      out.println("  // Index Typed factory methods");      out.println("  static final double convFactor[]={");      for (Iterator ti = tuples.iterator(); ti.hasNext(); ) {        UnitTuple ut = (UnitTuple)ti.next();        out.print("    "+ut.factor+"");        if (ti.hasNext())          out.println(",");        else          out.println();      }      out.println("  };");      out.println("  // indexes into factor array");      int i = 0;      for (Iterator ti = tuples.iterator(); ti.hasNext(); ) {        UnitTuple ut = (UnitTuple)ti.next();        String unit = ut.num+"_per_"+ut.sden;        String unitName = toConstantName(unit);        out.println("  public static final int "+unitName+" = "+i+";");        i++;      }      out.println("  static final int MAXUNIT = "+(i-1)+";");      out.println();      out.println("  // Index Typed factory methods");      out.println("  /** @param unit One of the constant units of "+className+" **/");      out.println("  public static final "+className+" new"+className+"(double v, int unit) {");      out.println("    if (unit >= 0 && unit <= MAXUNIT)");      out.println("      return new "+className+"(v*convFactor[unit]);");      out.println("    else");      out.println("      throw new UnknownUnitException();");      out.println("  }");      out.println();      out.println("  /** @param unit One of the constant units of "+className+" **/");      out.println("  public static final "+className+" new"+className+"(String s, int unit) {");      out.println("    if (unit >= 0 && unit <= MAXUNIT)");      out.println("      return new "+className+"((Double.valueOf(s).doubleValue())*convFactor[unit]);");      out.println("    else");      out.println("      throw new UnknownUnitException();");      out.println("  }");      out.println();      out.println("  // Index Typed factory methods");      out.println("  /** @param unit1 One of the constant units of "+dC+"\n"+                  "   *  @param unit2 One of the constant units of "+dtC+"\n"+                  "   **/");      out.println("  public static final "+className+" new"+className+"(double v, int unit1, int unit2) {");      out.println("    if (unit1 >= 0 && unit1 <= "+dC+".MAXUNIT &&\n"+                  "        unit2 >= 0 && unit2 <= "+dtC+".MAXUNIT)");      out.println("      return new "+className+"(v*"+dC+".convFactor[unit1]/"+dtC+".convFactor[unit2]);");      out.println("    else");      out.println("      throw new UnknownUnitException();");      out.println("  }");      out.println();      out.println("  /** @param num An instance of "+dC+" to use as numerator\n"+                  "   *  @param den An instance of "+dtC+"to use as denominator\n"+                  "   **/");      out.println("  public static final "+className+" new"+className+"("+dC+" num, "+dtC+" den) {");      out.println("    return new "+className+"(num.getValue(0)/den.getValue(0));");      out.println("  }");      out.println();      out.println("  /** @param unit1 One of the constant units of "+dC+"\n"+                  "   *  @param unit2 One of the constant units of "+dtC+"\n"+                  "   **/");      out.println("  public static final "+className+" new"+className+"(String s, int unit1, int unit2) {");      out.println("    if (unit1 >= 0 && unit1 <= "+dC+".MAXUNIT &&\n"+                  "        unit2 >= 0 && unit2 <= "+dtC+".MAXUNIT)");      out.println("      return new "+className+"((Double.valueOf(s).doubleValue())*"+dC+".convFactor[unit1]/"+dtC+".convFactor[unit2]);");      out.println("    else");      out.println("      throw new UnknownUnitException();");      out.println("  }");      out.println();      // abstractmeasure-level concretefactory      out.println("  // Support for AbstractMeasure-level constructor");      out.println("  public static final AbstractMeasure newMeasure(String s, int unit) {");      out.println("    return new"+className+"(s, unit);");      out.println("  }");      out.println("  public static final AbstractMeasure newMeasure(double v, int unit) {");      out.println("    return new"+className+"(v, unit);");      out.println("  }");      // getters      out.println("  // Unit-based Reader methods");      for (Iterator ti = tuples.iterator(); ti.hasNext(); ) {        UnitTuple ut = (UnitTuple)ti.next();        String unit = ut.num+"_per_"+ut.sden;        String unitName = toClassName(unit);        out.println("  public double get"+unitName+"() {");        out.println("    return (theValue*"+ut.factor+");");        out.println("  }");      }      out.println();      // unit-as-argument getter      out.println("  /** @param unit One of the constant units of "+className+" **/");      out.println("  public double getValue(int unit) {");      out.println("    if (unit >= 0 && unit <= MAXUNIT)");      out.println("      return (theValue*convFactor[unit]);");      out.println("    else");      out.println("      throw new UnknownUnitException();");      out.println("  }");      out.println();      out.println("  /** @param unit1 One of the constant units of "+dC+"\n"+                  "   *  @param unit2 One of the constant units of "+dtC+"\n"+                  "   **/");      out.println("  public double getValue(int unit1, int unit2) {");      out.println("    if (unit1 >= 0 && unit1 <= "+dC+".MAXUNIT &&\n"+                  "        unit2 >= 0 && unit2 <= "+dtC+".MAXUNIT)");      out.println("      return (theValue*"+dtC+".convFactor[unit2]/"+dC+".convFactor[unit1]);");      out.println("    else");      out.println("      throw new UnknownUnitException();");      out.println("  }");      out.println();      // equals et al      out.println("  public boolean equals(Object o) {");      out.println("    return ( o instanceof "+className+" &&");      out.println("             theValue == (("+className+") o).theValue);");      out.println("  }");      out.println("  public String toString() {");      out.println("    return Double.toString(theValue) + \""+                  baseabbrev+"\";");      out.println("  }");      out.println("  public int hashCode() {");      out.println("    return (new Double(theValue)).hashCode();");      out.println("  }");      out.println();      // derivative implementation      out.println("  // Derivative");      out.println("  public final Class getNumeratorClass() { return "+dC+".class; }");      out.println("  public final Class getDenominatorClass() { return "+dtC+".class; }");      out.println();      out.println("  private final static "+dC+" can_num = new "+dC+"(0.0,0);");      out.println("  public final Measure getCanonicalNumerator() { return can_num; }");      out.println("  private final static "+dtC+" can_den = new "+dtC+"(0.0,0);");      out.println("  public final Measure getCanonicalDenominator() { return can_den; }");            out.println("  public final Measure computeNumerator(Measure den) {\n"+                  "    if (!(den instanceof "+dtC+")) throw new IllegalArgumentException();\n"+                  "    return new "+dC+"(theValue*den.getValue(0),0);\n"+                  "  }");      out.println("  public final Measure computeDenominator(Measure num) {\n"+                  "    if (!(num instanceof "+dC+")) throw new IllegalArgumentException();\n"+                  "    return new "+dtC+"(num.getValue(0)/theValue,0);\n"+                  "  }");      out.println();      out.println("  // serialization");      out.println("  public void writeExternal(ObjectOutput out) throws IOException {\n"+                  "    out.writeDouble(theValue);\n"+                  "  }");      out.println("  public void readExternal(ObjectInput in) throws IOException {\n"+                  "    theValue = in.readDouble();\n"+                  "  }");      // that's all, folks      out.println("}");    }