/**
  * A program generator is typically (but not always) invoked with a command line with arguments
  * for the XML input file and output file.
  */
 public static void main(String[] args) {
   try {
     ProgramWriter out =
         args.length >= 2
             ? new ProgramWriter(new FileOutputStream(args[1]))
             : new ProgramWriter(System.out);
     CalculatedCollectionPG pg = new CalculatedCollectionPG();
     for (int j = 1; j <= args.length; ++j) {
       pg.properties.put("arg" + j, args[j - 1]);
     }
     pg.generate(new XPathContext(args[0]), out);
     out.close();
   } catch (Exception e) {
     e.printStackTrace();
   }
 }
  /** This method generates the output given a context and output stream */
  public boolean generate(XPathContext context, ProgramWriter out) {
    try {
      String collectionName = Strings.firstUpper(collection.getName());

      if (ejb) {
        out.print(" \n\t/**\n\t * @ejb:interface-method\n\t */");
      }
      out.print(" \n\tpublic java.util.Collection get");
      out.print(collectionName);
      out.print("() {");
      if (ejb) {
        out.print(
            " \n\t\tboolean cmtActivated = false;\n\t\tif (!org.openxava.hibernate.XHibernate.isCmt()) {\n\t\t\torg.openxava.hibernate.XHibernate.setCmt(true);\n\t\t\tcmtActivated = true;\n\t\t}");
      }
      out.print(" \n\t\ttry {");

      MetaCalculator calculator = collection.getMetaCalculator();
      String calculatorClass = calculator.getClassName();

      out.print(" \t\t\n\t\t\t");
      out.print(calculatorClass);
      out.print(" ");
      out.print(collection.getName());
      out.print("Calculator= (");
      out.print(calculatorClass);
      out.print(")\n\t\t\t\tgetMetaModel().getMetaCollection(\"");
      out.print(collection.getName());
      out.print("\").getMetaCalculator().createCalculator();");

      Iterator itSets = calculator.getMetaSetsWithoutValue().iterator();
      while (itSets.hasNext()) {
        MetaSet set = (MetaSet) itSets.next();
        String propertyNameInCalculator = Strings.firstUpper(set.getPropertyName());
        String propertyNameFrom = set.getPropertyNameFrom();
        MetaProperty p = metaModel.getMetaProperty(propertyNameFrom);
        if (propertyNameFrom.indexOf('.') >= 0) {
          if (p.isKey() || p.getMetaModel() instanceof MetaAggregate) {
            propertyNameFrom = Strings.firstUpper(Strings.change(propertyNameFrom, ".", "_"));
          } else {
            StringTokenizer st = new StringTokenizer(propertyNameFrom, ".");
            String ref = st.nextToken();
            String pro = st.nextToken();
            propertyNameFrom = Strings.firstUpper(ref) + "().get" + Strings.firstUpper(pro);
          }
        } else {
          propertyNameFrom = Strings.firstUpper(propertyNameFrom);
        }
        String getPropertyFrom = "boolean".equals(p.getTypeName()) ? "is" : "get";
        String value = set.getValue();
        if (set.hasValue()) {

          out.print(" \n\t\t\t");
          out.print(collection.getName());
          out.print("Calculator.set");
          out.print(propertyNameInCalculator);
          out.print("(\"");
          out.print(value);
          out.print("\");");

        } else {

          out.print("  \t\n\t\t\t");
          out.print(collection.getName());
          out.print("Calculator.set");
          out.print(propertyNameInCalculator);
          out.print("(");
          out.print(getPropertyFrom);
          out.print(propertyNameFrom);
          out.print("());");
        }
      } // else/sets
      if (IModelCalculator.class.isAssignableFrom(Class.forName(calculatorClass))) {

        out.print(" \n\t\t\t\t");
        out.print(collection.getName());
        out.print("Calculator.setModel(this);");
      }
      if (IEntityCalculator.class.isAssignableFrom(Class.forName(calculatorClass))) {

        out.print(" \n\t\t\t\t");
        out.print(collection.getName());
        out.print("Calculator.setEntity(this);");
      }
      if (IJDBCCalculator.class.isAssignableFrom(Class.forName(calculatorClass))) {

        out.print(" \n\t\t\t\t");
        out.print(collection.getName());
        out.print("Calculator.setConnectionProvider(getPortableContext());");
      }
      String calculateValueSentence = collection.getName() + "Calculator.calculate()";

      out.print(" \n\t\t\treturn ");
      out.print(Generators.generateCast("java.util.Collection", calculateValueSentence));
      out.print(
          ";\n\t\t}\n\t\tcatch (Exception ex) {\n\t\t\tex.printStackTrace();\n\t\t\tthrow new ");
      out.print(getException());
      out.print("(XavaResources.getString(\"generator.calculate_value_error\", \"");
      out.print(collection.getName());
      out.print("\", \"");
      out.print(metaModel.getName());
      out.print("\", ex.getLocalizedMessage()));\n\t\t}");
      if (ejb) {
        out.print(
            " \n\t\tfinally {\n\t\t\tif (cmtActivated) {\n\t\t\t\torg.openxava.hibernate.XHibernate.setCmt(false);\n\t\t\t}\n\t\t}");
      }
      out.print(" \t\t\t\t\n\t}");

    } catch (Exception e) {
      System.out.println("Exception: " + e.getMessage());
      e.printStackTrace();
      return false;
    }
    return true;
  }