/*
 * Copyright 2010 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.autobean.rebind;

import com.google.gwt.autobean.client.impl.AbstractAutoBeanFactory;
import com.google.gwt.autobean.rebind.model.AutoBeanFactoryMethod;
import com.google.gwt.autobean.rebind.model.AutoBeanFactoryModel;
import com.google.gwt.autobean.rebind.model.AutoBeanMethod;
import com.google.gwt.autobean.rebind.model.AutoBeanMethod.Action;
import com.google.gwt.autobean.rebind.model.AutoBeanType;
import com.google.gwt.autobean.shared.AutoBean;
import com.google.gwt.autobean.shared.AutoBeanFactory;
import com.google.gwt.autobean.shared.AutoBeanUtils;
import com.google.gwt.autobean.shared.AutoBeanVisitor;
import com.google.gwt.autobean.shared.AutoBeanVisitor.CollectionPropertyContext;
import com.google.gwt.autobean.shared.AutoBeanVisitor.MapPropertyContext;
import com.google.gwt.autobean.shared.AutoBeanVisitor.PropertyContext;
import com.google.gwt.autobean.shared.impl.AbstractAutoBean;
import com.google.gwt.autobean.shared.impl.AbstractAutoBean.OneShotContext;
import com.google.gwt.core.client.impl.WeakMapping;
import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JEnumConstant;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JParameter;
import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.generator.NameFactory;
import com.google.gwt.editor.rebind.model.ModelUtils;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Generates implementations of AutoBeanFactory.
 */
public class AutoBeanFactoryGenerator extends Generator {

  private GeneratorContext context;
  private String simpleSourceName;
  private TreeLogger logger;
  private AutoBeanFactoryModel model;

  @Override
  public String generate(TreeLogger logger, GeneratorContext context,
      String typeName) throws UnableToCompleteException {
    this.context = context;
    this.logger = logger;

    TypeOracle oracle = context.getTypeOracle();
    JClassType toGenerate = oracle.findType(typeName).isInterface();
    if (toGenerate == null) {
      logger.log(TreeLogger.ERROR, typeName + " is not an interface type");
      throw new UnableToCompleteException();
    }

    String packageName = toGenerate.getPackage().getName();
    simpleSourceName = toGenerate.getName().replace('.', '_') + "Impl";
    PrintWriter pw = context.tryCreate(logger, packageName, simpleSourceName);
    if (pw == null) {
      return packageName + "." + simpleSourceName;
    }

    model = new AutoBeanFactoryModel(logger, toGenerate);

    ClassSourceFileComposerFactory factory = new ClassSourceFileComposerFactory(
        packageName, simpleSourceName);
    factory.setSuperclass(AbstractAutoBeanFactory.class.getCanonicalName());
    factory.addImplementedInterface(typeName);
    SourceWriter sw = factory.createSourceWriter(context, pw);
    for (AutoBeanType type : model.getAllTypes()) {
      writeAutoBean(type);
    }
    writeDynamicMethods(sw);
    writeEnumSetup(sw);
    writeMethods(sw);
    sw.commit(logger);

    return factory.getCreatedClassName();
  }

  private String getBaseMethodDeclaration(JMethod jmethod) {
    // Foo foo, Bar bar, Baz baz
    StringBuilder parameters = new StringBuilder();
    for (JParameter param : jmethod.getParameters()) {
      parameters.append(",").append(
          ModelUtils.getQualifiedBaseSourceName(param.getType())).append(" ").append(
          param.getName());
    }
    if (parameters.length() > 0) {
      parameters = parameters.deleteCharAt(0);
    }

    StringBuilder throwsDeclaration = new StringBuilder();
    if (jmethod.getThrows().length > 0) {
      for (JType thrown : jmethod.getThrows()) {
        throwsDeclaration.append(". ").append(
            ModelUtils.getQualifiedBaseSourceName(thrown));
      }
      throwsDeclaration.deleteCharAt(0);
      throwsDeclaration.insert(0, "throws ");
    }
    String returnName = ModelUtils.getQualifiedBaseSourceName(jmethod.getReturnType());
    assert !returnName.contains("extends");
    return String.format("%s %s(%s) %s", returnName, jmethod.getName(),
        parameters, throwsDeclaration);
  }

  /**
   * Used by {@link #writeShim} to avoid duplicate declarations of Object
   * methods.
   */
  private boolean isObjectMethodImplementedByShim(JMethod jmethod) {
    String methodName = jmethod.getName();
    JParameter[] parameters = jmethod.getParameters();
    switch (parameters.length) {
      case 0:
        return methodName.equals("hashCode") || methodName.equals("toString");
      case 1:
        return methodName.equals("equals")
            && parameters[0].getType().equals(
                context.getTypeOracle().getJavaLangObject());
    }
    return false;
  }

  private void writeAutoBean(AutoBeanType type)
      throws UnableToCompleteException {
    PrintWriter pw = context.tryCreate(logger, type.getPackageNome(),
        type.getSimpleSourceName());
    if (pw == null) {
      // Previously-created
      return;
    }

    ClassSourceFileComposerFactory factory = new ClassSourceFileComposerFactory(
        type.getPackageNome(), type.getSimpleSourceName());
    factory.setSuperclass(AbstractAutoBean.class.getCanonicalName() + "<"
        + type.getPeerType().getQualifiedSourceName() + ">");
    SourceWriter sw = factory.createSourceWriter(context, pw);

    writeShim(sw, type);

    // Instance initializer code to set the shim's association
    sw.println("{ %s.set(shim, %s.class.getName(), this); }",
        WeakMapping.class.getCanonicalName(), AutoBean.class.getCanonicalName());

    // Only simple wrappers have a default constructor
    if (type.isSimpleBean()) {
      // public FooIntfAutoBean(AutoBeanFactory factory) {}
      sw.println("public %s(%s factory) {super(factory);}",
          type.getSimpleSourceName(), AutoBeanFactory.class.getCanonicalName());
    }

    // Clone constructor
    // public FooIntfAutoBean(FooIntfoAutoBean toClone, boolean deepClone) {
    sw.println("public %1$s(%1$s toClone, boolean deep) {",
        type.getSimpleSourceName());
    sw.indentln("super(toClone, deep);");
    sw.println("}");

    // Wrapping constructor
    // public FooIntfAutoBean(AutoBeanFactory factory, FooIntfo wrapped) {
    sw.println("public %s(%s factory, %s wrapped) {",
        type.getSimpleSourceName(), AutoBeanFactory.class.getCanonicalName(),
        type.getPeerType().getQualifiedSourceName());
    sw.indentln("super(factory, wrapped);");
    sw.println("}");

    // public FooIntf as() {return shim;}
    sw.println("public %s as() {return shim;}",
        type.getPeerType().getQualifiedSourceName());

    // public FooIntfAutoBean clone(boolean deep) {
    sw.println("public %s clone(boolean deep) {", type.getQualifiedSourceName());
    // return new FooIntfAutoBean(this, deep);
    sw.indentln("return new %s(this, deep);", type.getSimpleSourceName());
    sw.println("}");

    // public Class<Intf> getType() {return Intf.class;}
    sw.println("public Class<%1$s> getType() {return %1$s.class;}",
        ModelUtils.ensureBaseType(type.getPeerType()).getQualifiedSourceName());

    if (type.isSimpleBean()) {
      writeCreateSimpleBean(sw, type);
    }
    writeTraversal(sw, type);
    sw.commit(logger);
  }

  /**
   * For interfaces that consist of nothing more than getters and setters,
   * create a map-based implementation that will allow the AutoBean's internal
   * state to be easily consumed.
   */
  private void writeCreateSimpleBean(SourceWriter sw, AutoBeanType type) {
    sw.println("@Override protected %s createSimplePeer() {",
        type.getPeerType().getQualifiedSourceName());
    sw.indent();
    // return new FooIntf() {
    sw.println("return new %s() {", type.getPeerType().getQualifiedSourceName());
    sw.indent();
    for (AutoBeanMethod method : type.getMethods()) {
      JMethod jmethod = method.getMethod();
      sw.println("public %s {", getBaseMethodDeclaration(jmethod));
      sw.indent();
      switch (method.getAction()) {
        case GET: {
          // Must handle de-boxing primitive types
          JPrimitiveType primitive = jmethod.getReturnType().isPrimitive();
          if (primitive != null) {
            // Object toReturn = values.get("foo");
            sw.println("Object toReturn = values.get(\"%s\");",
                method.getPropertyName());
            sw.println("if (toReturn == null) {");
            // return 0;
            sw.indentln("return %s;",
                primitive.getUninitializedFieldExpression());
            sw.println("} else {");
            // return (BoxedType) toReturn;
            sw.indentln("return (%s) toReturn;",
                primitive.getQualifiedBoxedSourceName());
            sw.println("}");
          } else {
            // return (ReturnType) values.get(\"foo\");
            sw.println("return (%s) values.get(\"%s\");",
                ModelUtils.getQualifiedBaseSourceName(jmethod.getReturnType()),
                method.getPropertyName());
          }
        }
          break;
        case SET:
          // values.put("foo", parameter);
          sw.println("values.put(\"%s\", %s);", method.getPropertyName(),
              jmethod.getParameters()[0].getName());
          break;
        case CALL:
          // return com.example.Owner.staticMethod(Outer.this, param,
          // param);
          JMethod staticImpl = method.getStaticImpl();
          if (!jmethod.getReturnType().equals(JPrimitiveType.VOID)) {
            sw.print("return ");
          }
          sw.print("%s.%s(%s.this",
              staticImpl.getEnclosingType().getQualifiedSourceName(),
              staticImpl.getName(), type.getSimpleSourceName());
          for (JParameter param : jmethod.getParameters()) {
            sw.print(", %s", param.getName());
          }
          sw.println(");");
          break;
        default:
          throw new RuntimeException();
      }
      sw.outdent();
      sw.println("}");
    }
    sw.outdent();
    sw.println("};");
    sw.outdent();
    sw.println("}");
  }

  /**
   * Write an instance initializer block to populate the creators map.
   */
  private void writeDynamicMethods(SourceWriter sw) {
    sw.println("{");
    sw.indent();
    for (AutoBeanType type : model.getAllTypes()) {
      if (type.isNoWrap()) {
        continue;
      }
      sw.println(
          "creators.put(%s.class, new Creator() {",
          ModelUtils.ensureBaseType(type.getPeerType()).getQualifiedSourceName());
      if (type.isSimpleBean()) {
        sw.indentln("public %1$s create() { return new %1$s(%2$s.this); }",
            type.getQualifiedSourceName(), simpleSourceName);
      } else {
        sw.indentln("public %1$s create() { return null; }",
            type.getQualifiedSourceName());
      }
      // public FooAutoBean create(Object delegate) {
      // return new FooAutoBean((Foo) delegate); }
      sw.indentln("public %1$s create(Object delegate) {"
          + " return new %1$s(%2$s.this, (%3$s) delegate); }",
          type.getQualifiedSourceName(), simpleSourceName,
          type.getPeerType().getQualifiedSourceName());
      sw.println("});");
    }
    sw.outdent();
    sw.println("}");
  }

  private void writeEnumSetup(SourceWriter sw) {
    // Make the deobfuscation model
    Map<String, List<JEnumConstant>> map = new HashMap<String, List<JEnumConstant>>();
    for (Map.Entry<JEnumConstant, String> entry : model.getEnumTokenMap().entrySet()) {
      List<JEnumConstant> list = map.get(entry.getValue());
      if (list == null) {
        list = new ArrayList<JEnumConstant>();
        map.put(entry.getValue(), list);
      }
      list.add(entry.getKey());
    }

    sw.println("@Override protected void initializeEnumMap() {");
    sw.indent();
    for (Map.Entry<JEnumConstant, String> entry : model.getEnumTokenMap().entrySet()) {
      // enumToStringMap.put(Enum.FOO, "FOO");
      sw.println("enumToStringMap.put(%s.%s, \"%s\");",
          entry.getKey().getEnclosingType().getQualifiedSourceName(),
          entry.getKey().getName(), entry.getValue());
    }
    for (Map.Entry<String, List<JEnumConstant>> entry : map.entrySet()) {
      String listExpr;
      if (entry.getValue().size() == 1) {
        JEnumConstant e = entry.getValue().get(0);
        // Collections.singletonList(Enum.FOO)
        listExpr = String.format("%s.<%s<?>> singletonList(%s.%s)",
            Collections.class.getCanonicalName(),
            Enum.class.getCanonicalName(),
            e.getEnclosingType().getQualifiedSourceName(), e.getName());
      } else {
        // Arrays.asList(Enum.FOO, OtherEnum.FOO, ThirdEnum,FOO)
        StringBuilder sb = new StringBuilder();
        boolean needsComma = false;
        sb.append(String.format("%s.<%s<?>> asList(",
            Arrays.class.getCanonicalName(), Enum.class.getCanonicalName()));
        for (JEnumConstant e : entry.getValue()) {
          if (needsComma) {
            sb.append(",");
          }
          needsComma = true;
          sb.append(e.getEnclosingType().getQualifiedSourceName()).append(".").append(
              e.getName());
        }
        sb.append(")");
        listExpr = sb.toString();
      }
      sw.println("stringsToEnumsMap.put(\"%s\", %s);", entry.getKey(), listExpr);
    }
    sw.outdent();
    sw.println("}");
  }

  private void writeMethods(SourceWriter sw) throws UnableToCompleteException {
    for (AutoBeanFactoryMethod method : model.getMethods()) {
      AutoBeanType autoBeanType = method.getAutoBeanType();
      // public AutoBean<Foo> foo(FooSubtype wrapped) {
      sw.println("public %s %s(%s) {",
          method.getReturnType().getQualifiedSourceName(), method.getName(),
          method.isWrapper()
              ? (method.getWrappedType().getQualifiedSourceName() + " wrapped")
              : "");
      if (method.isWrapper()) {
        sw.indent();
        // AutoBean<Foo> toReturn = AutoBeanUtils.getAutoBean(wrapped);
        sw.println("%s toReturn = %s.getAutoBean(wrapped);",
            method.getReturnType().getParameterizedQualifiedSourceName(),
            AutoBeanUtils.class.getCanonicalName());
        sw.println("if (toReturn != null) {return toReturn;}");
        // return new FooAutoBean(Factory.this, wrapped);
        sw.println("return new %s(%s.this, wrapped);",
            autoBeanType.getQualifiedSourceName(), simpleSourceName);
        sw.outdent();
      } else {
        // return new FooAutoBean(Factory.this);
        sw.indentln("return new %s(%s.this);",
            autoBeanType.getQualifiedSourceName(), simpleSourceName);
      }
      sw.println("}");
    }
  }

  private void writeReturnWrapper(SourceWriter sw, AutoBeanType type,
      AutoBeanMethod method) throws UnableToCompleteException {
    if (!method.isValueType() && !method.isNoWrap()) {
      JMethod jmethod = method.getMethod();
      JClassType returnClass = jmethod.getReturnType().isClassOrInterface();
      AutoBeanType peer = model.getPeer(returnClass);

      sw.println("if (toReturn != null) {");
      sw.indent();
      sw.println("if (%s.this.isWrapped(toReturn)) {",
          type.getSimpleSourceName());
      sw.indentln("toReturn = %s.this.getFromWrapper(toReturn);",
          type.getSimpleSourceName());
      sw.println("} else {");
      sw.indent();
      if (peer != null) {
        // toReturn = new FooAutoBean(getFactory(), toReturn).as();
        sw.println("toReturn = new %s(getFactory(), toReturn).as();",
            peer.getQualifiedSourceName());
      }
      sw.outdent();
      sw.println("}");

      sw.outdent();
      sw.println("}");
    }
    // Allow return values to be intercepted
    JMethod interceptor = type.getInterceptor();
    if (interceptor != null) {
      // toReturn = FooCategory.__intercept(FooAutoBean.this, toReturn);
      sw.println("toReturn = %s.%s(%s.this, toReturn);",
          interceptor.getEnclosingType().getQualifiedSourceName(),
          interceptor.getName(), type.getSimpleSourceName());
    }
  }

  /**
   * Create the shim instance of the AutoBean's peer type that lets us hijack
   * the method calls. Using a shim type, as opposed to making the AutoBean
   * implement the peer type directly, means that there can't be any conflicts
   * between methods in the peer type and methods declared in the AutoBean
   * implementation.
   */
  private void writeShim(SourceWriter sw, AutoBeanType type)
      throws UnableToCompleteException {
    // private final FooImpl shim = new FooImpl() {
    sw.println("private final %1$s shim = new %1$s() {",
        type.getPeerType().getQualifiedSourceName());
    sw.indent();
    for (AutoBeanMethod method : type.getMethods()) {
      JMethod jmethod = method.getMethod();
      String methodName = jmethod.getName();
      JParameter[] parameters = jmethod.getParameters();
      if (isObjectMethodImplementedByShim(jmethod)) {
        // Skip any methods declared on Object, since we have special handling
        continue;
      }

      // foo, bar, baz
      StringBuilder arguments = new StringBuilder();
      {
        for (JParameter param : parameters) {
          arguments.append(",").append(param.getName());
        }
        if (arguments.length() > 0) {
          arguments = arguments.deleteCharAt(0);
        }
      }

      sw.println("public %s {", getBaseMethodDeclaration(jmethod));
      sw.indent();

      // Use explicit enclosing this reference to avoid method conflicts
      sw.println("%s.this.checkWrapped();", type.getSimpleSourceName());

      switch (method.getAction()) {
        case GET:
          /*
           * The getter call will ensure that any non-value return type is
           * definitely wrapped by an AutoBean instance.
           */
          // Foo toReturn=FooAutoBean.this.get("getFoo", getWrapped().getFoo());
          sw.println(
              "%s toReturn = %3$s.this.get(\"%2$s\", getWrapped().%2$s());",
              ModelUtils.getQualifiedBaseSourceName(jmethod.getReturnType()),
              methodName, type.getSimpleSourceName());

          // Non-value types might need to be wrapped
          writeReturnWrapper(sw, type, method);
          sw.println("return toReturn;");
          break;
        case SET:
          sw.println("%s.this.checkFrozen();", type.getSimpleSourceName());
          // getWrapped().setFoo(foo);
          sw.println("%s.this.getWrapped().%s(%s);",
              type.getSimpleSourceName(), methodName, parameters[0].getName());
          // FooAutoBean.this.set("setFoo", foo);
          sw.println("%s.this.set(\"%s\", %s);", type.getSimpleSourceName(),
              methodName, parameters[0].getName());
          break;
        case CALL:
          // XXX How should freezing and calls work together?
          // sw.println("checkFrozen();");
          if (JPrimitiveType.VOID.equals(jmethod.getReturnType())) {
            // getWrapped().doFoo(params);
            sw.println("%s.this.getWrapped().%s(%s);",
                type.getSimpleSourceName(), methodName, arguments);
            // call("doFoo", null, params);
            sw.println("%s.this.call(\"%s\", null%s %s);",
                type.getSimpleSourceName(), methodName, arguments.length() > 0
                    ? "," : "", arguments);
          } else {
            // Type toReturn = getWrapped().doFoo(params);
            sw.println(
                "%s toReturn = %s.this.getWrapped().%s(%s);",
                ModelUtils.ensureBaseType(jmethod.getReturnType()).getQualifiedSourceName(),
                type.getSimpleSourceName(), methodName, arguments);
            // Non-value types might need to be wrapped
            writeReturnWrapper(sw, type, method);
            // call("doFoo", toReturn, params);
            sw.println("%s.this.call(\"%s\", toReturn%s %s);",
                type.getSimpleSourceName(), methodName, arguments.length() > 0
                    ? "," : "", arguments);
            sw.println("return toReturn;");
          }
          break;
        default:
          throw new RuntimeException();
      }
      sw.outdent();
      sw.println("}");
    }

    // Delegate equals(), hashCode(), and toString() to wrapped object
    sw.println("@Override public boolean equals(Object o) {");
    sw.indentln("return this == o || getWrapped().equals(o);");
    sw.println("}");
    sw.println("@Override public int hashCode() {");
    sw.indentln("return getWrapped().hashCode();");
    sw.println("}");
    sw.println("@Override public String toString() {");
    sw.indentln("return getWrapped().toString();");
    sw.println("}");

    // End of shim field declaration and assignment
    sw.outdent();
    sw.println("};");
  }

  /**
   * Generate traversal logic.
   */
  private void writeTraversal(SourceWriter sw, AutoBeanType type) {
    NameFactory names = new NameFactory();
    sw.println(
        "@Override protected void traverseProperties(%s visitor, %s ctx) {",
        AutoBeanVisitor.class.getCanonicalName(),
        OneShotContext.class.getCanonicalName());
    sw.indent();

    for (AutoBeanMethod method : type.getMethods()) {
      if (!method.getAction().equals(Action.GET)) {
        continue;
      }

      AutoBeanMethod setter = null;
      // If it's not a simple bean type, try to find a real setter method
      if (!type.isSimpleBean()) {
        for (AutoBeanMethod maybeSetter : type.getMethods()) {
          if (maybeSetter.getAction().equals(Action.SET)
              && maybeSetter.getPropertyName().equals(method.getPropertyName())) {
            setter = maybeSetter;
            break;
          }
        }
      }

      // The type of property influences the visitation
      String valueExpression = String.format(
          "%1$s value = (%1$s) %2$s.getAutoBean(as().%3$s());",
          AbstractAutoBean.class.getCanonicalName(),
          AutoBeanUtils.class.getCanonicalName(), method.getMethod().getName());
      String visitMethod;
      Class<?> propertyContextType;
      if (method.isCollection()) {
        propertyContextType = CollectionPropertyContext.class;
        visitMethod = "Collection";
      } else if (method.isMap()) {
        propertyContextType = MapPropertyContext.class;
        visitMethod = "Map";
      } else if (method.isValueType()) {
        propertyContextType = PropertyContext.class;
        valueExpression = String.format("Object value = as().%s();",
            method.getMethod().getName());
        visitMethod = "Value";
      } else {
        visitMethod = "Reference";
        propertyContextType = PropertyContext.class;
      }

      /*
       * Make the PropertyContext that lets us call the setter. We allow
       * multiple methods to be bound to the same property (e.g. to allow JSON
       * payloads to be interpreted as different types). The leading underscore
       * allows purely numeric property names, which are valid JSON map keys.
       */
      String propertyContextName = names.createName("_"
          + method.getPropertyName() + "PropertyContext");
      sw.println("class %s implements %s {", propertyContextName,
          propertyContextType.getCanonicalName());
      sw.indent();
      sw.println("public boolean canSet() { return %s; }", type.isSimpleBean()
          || setter != null);
      if (method.isCollection()) {
        // Will return the collection's element type or null if not a collection
        sw.println(
            "public Class<?> getElementType() { return %s.class; }",
            ModelUtils.ensureBaseType(method.getElementType()).getQualifiedSourceName());
      } else if (method.isMap()) {
        // Will return the map's value type
        sw.println(
            "public Class<?> getValueType() { return %s.class; }",
            ModelUtils.ensureBaseType(method.getValueType()).getQualifiedSourceName());
        // Will return the map's key type
        sw.println(
            "public Class<?> getKeyType() { return %s.class; }",
            ModelUtils.ensureBaseType(method.getKeyType()).getQualifiedSourceName());
      }
      // Return the property type
      sw.println(
          "public Class<?> getType() { return %s.class; }",
          ModelUtils.ensureBaseType(method.getMethod().getReturnType()).getQualifiedSourceName());
      sw.println("public void set(Object obj) { ");
      if (setter != null) {
        // Prefer the setter if one exists
        // as().setFoo((Foo) obj);
        sw.indentln(
            "as().%s((%s) obj);",
            setter.getMethod().getName(),
            ModelUtils.ensureBaseType(
                setter.getMethod().getParameters()[0].getType()).getQualifiedSourceName());
      } else if (type.isSimpleBean()) {
        // Otherwise, fall back to a map assignment
        sw.indentln("values.put(\"%s\", obj);", method.getPropertyName());
      } else {
        sw.indentln("throw new UnsupportedOperationException(\"No setter\");");
      }
      sw.println("}");
      sw.outdent();
      sw.println("}");

      sw.print("{");
      sw.indent();
      sw.println("%1$s %1$s = new %1$s();", propertyContextName);

      // Call the visit methods
      sw.println(valueExpression);
      // if (visitor.visitReferenceProperty("foo", value, ctx))
      sw.println("if (visitor.visit%sProperty(\"%s\", value, %s))",
          visitMethod, method.getPropertyName(), propertyContextName);
      if (!method.isValueType()) {
        // Cycle-detection in AbstractAutoBean.traverse
        sw.indentln("if (value != null) { value.traverse(visitor, ctx); }");
      }
      // visitor.endVisitorReferenceProperty("foo", value, ctx);
      sw.println("visitor.endVisit%sProperty(\"%s\", value, %s);", visitMethod,
          method.getPropertyName(), propertyContextName);
      sw.outdent();
      sw.print("}");
    }
    sw.outdent();
    sw.println("}");
  }
}
