private void generateClass(TreeLogger logger, GeneratorContext context) {

    // get print writer that receives the source code
    PrintWriter printWriter = null;
    printWriter = context.tryCreate(logger, packageName, className);
    // print writer if null, source code has ALREADY been generated, return
    if (printWriter == null) {
      return;
    }

    // init composer, set class properties, create source writer
    ClassSourceFileComposerFactory composer = null;
    composer = new ClassSourceFileComposerFactory(packageName, className);
    composer.addImplementedInterface("org.pentaho.ui.xul.gwt.binding.TypeController");
    composer.addImport("org.pentaho.ui.xul.gwt.binding.*");
    composer.addImport("java.util.Map");
    composer.addImport("java.util.HashMap");
    composer.addImport("org.pentaho.ui.xul.XulException");

    SourceWriter sourceWriter = null;
    sourceWriter = composer.createSourceWriter(context, printWriter);

    // generator constructor source code
    generateConstructor(sourceWriter);

    writeMethods(sourceWriter);

    // close generated class
    sourceWriter.outdent();
    sourceWriter.println("}");

    // commit generated class
    context.commit(logger, printWriter);
  }
  public String generate(TreeLogger logger, GeneratorContext context, String typeName)
      throws UnableToCompleteException {
    // .println("Introspector Generate.");
    try {
      this.objectType = context.getTypeOracle().getType("java.lang.Object");
    } catch (NotFoundException ex) {
      logger.log(TreeLogger.ERROR, typeName, ex);

      return null;
    }

    List<BeanResolver> introspectables =
        this.getIntrospectableTypes(logger, context.getTypeOracle());

    MethodWrapper[] methods = this.findMethods(logger, introspectables);

    ClassSourceFileComposerFactory mcf =
        new ClassSourceFileComposerFactory(this.packageName, this.methodsImplementationName);
    mcf.addImport(Method.class.getCanonicalName());

    PrintWriter methodsPrintWriter =
        context.tryCreate(logger, this.packageName, this.methodsImplementationName);

    if (methodsPrintWriter != null) {
      SourceWriter methodsWriter = mcf.createSourceWriter(context, methodsPrintWriter);
      this.writeMethods(logger, methods, methodsWriter);
      methodsWriter.println("}");
      context.commit(logger, methodsPrintWriter);
    }

    ClassSourceFileComposerFactory cfcf =
        new ClassSourceFileComposerFactory(this.packageName, this.implementationName);
    cfcf.addImplementedInterface(typeName);
    cfcf.addImport("java.util.HashMap");
    cfcf.addImport(Method.class.getCanonicalName());
    cfcf.addImport(com.totsp.gwittir.introspection.Property.class.getCanonicalName());
    cfcf.addImport(com.totsp.gwittir.introspection.BeanDescriptor.class.getCanonicalName());

    PrintWriter printWriter = context.tryCreate(logger, packageName, implementationName);

    if (printWriter == null) {
      // .println( "Introspector Generate skipped.");
      return packageName + "." + implementationName;
    }

    SourceWriter writer = cfcf.createSourceWriter(context, printWriter);
    this.writeIntrospectables(logger, introspectables, methods, writer);
    this.writeResolver(introspectables, writer);

    writer.println(
        "private HashMap<Class,BeanDescriptor> beanDescriptorLookup = new HashMap<Class,BeanDescriptor>();");
    writer.println();
    writer.println("public BeanDescriptor getDescriptor( Object object ){ ");
    writer.indent();
    writer.println(
        "if( object == null ) throw new NullPointerException(\"Attempt to introspect null object\");");
    writer.println(
        "if( object instanceof "
            + SelfDescribed.class.getCanonicalName()
            + " ) return ((SelfDescribed)object).__descriptor();");
    writer.println("BeanDescriptor descriptor = beanDescriptorLookup.get(object.getClass());");
    writer.println("if (descriptor!=null){");
    writer.indentln("return descriptor;");
    writer.outdent();
    writer.println("}");

    writer.println("descriptor=_getDescriptor(object);");
    writer.println("beanDescriptorLookup.put(object.getClass(),descriptor);");
    writer.println("return descriptor;");
    writer.outdent();
    writer.println("}");

    writer.println("private BeanDescriptor _getDescriptor( Object object ){ ");
    writer.indent();

    for (BeanResolver resolver : introspectables) {
      writer.println(
          "if( object instanceof " + resolver.getType().getQualifiedSourceName() + " ) {");
      writer.indent();

      String name = resolver.getType().getQualifiedSourceName().replaceAll("\\.", "_");
      logger.log(TreeLogger.DEBUG, "Writing : " + name, null);
      writer.print("return " + name + " == null ? " + name + " = ");
      this.writeBeanDescriptor(logger, resolver, methods, writer);
      writer.print(": " + name + ";");
      writer.outdent();
      writer.println("}");
    }

    writer.println(" throw new IllegalArgumentException(\"Unknown type\" + object.getClass() ); ");
    writer.outdent();
    writer.println("}");
    writer.println("public Object createInstance(Class clazz) {");
    writer.indent();
    for (BeanResolver resolver : introspectables) {
      boolean hasPNA = false;
      for (JConstructor constructor : resolver.getType().getConstructors()) {
        if (constructor.getParameters() == null
            || constructor.getParameters().length == 0 && constructor.isPublic()) {
          hasPNA = true;
          break;
        }
        if (hasPNA) {
          break;
        }
      }

      writer.println(
          "if(clazz.equals(" + resolver.getType().getQualifiedSourceName() + ".class)){");
      writer.indent();
      logger.log(
          TreeLogger.Type.TRACE,
          resolver.getType().getQualifiedSourceName()
              + " abstract "
              + resolver.getType().isAbstract()
              + " intf "
              + (resolver.getType().isInterface() != null)
              + " def "
              + resolver.getType().isDefaultInstantiable());
      if (resolver.getType().isAbstract() || resolver.getType().isInterface() != null) {
        writer.println("throw new IllegalArgumentException(clazz+\" is abstract\");");
      } else if (hasPNA) {
        writer.println("return new " + resolver.getType().getQualifiedSourceName() + "();");
      } else {
        writer.println(
            "throw new IllegalArgumentException(clazz+\" has no public no args constructor\");");
      }
      writer.outdent();
      writer.println("}");
    }
    writer.println(" throw new IllegalArgumentException(\"Unknown type\" +clazz ); ");
    writer.outdent();
    writer.println("}");

    writer.println("HashMap<String, Class> classes = new HashMap<String, Class>();");
    writer.println("public Class forName(String className){");
    writer.indent();
    writer.println("Class clazz = classes.get(className);");
    writer.println("if(clazz != null) return clazz;");
    for (BeanResolver resolver : introspectables) {
      writer.println(
          "if(className.equals(\"" + resolver.getType().getQualifiedSourceName() + "\")){");
      writer.indent();
      writer.println("clazz = " + resolver.getType().getQualifiedSourceName() + ".class;");
      writer.println("classes.put(className, clazz);");
      writer.println("return clazz;");
      writer.outdent();
      writer.println("}");
    }
    writer.println("throw new IllegalArgumentException(className+\" is not introspecable.\");");
    writer.outdent();
    writer.println("}");
    writer.outdent();
    writer.println("}");

    context.commit(logger, printWriter);

    // .println( "Introspector Generate completed.");
    return packageName + "." + implementationName;
  }
 public void commit() {
   for (PrintWriter writer : writers) {
     generatorContext.commit(logger, writer);
   }
 }