Example usage for com.google.gwt.editor.rebind.model ModelUtils ensureBaseType

List of usage examples for com.google.gwt.editor.rebind.model ModelUtils ensureBaseType

Introduction

In this page you can find the example usage for com.google.gwt.editor.rebind.model ModelUtils ensureBaseType.

Prototype

@SuppressWarnings("unchecked")
    public static <T extends JType> T ensureBaseType(T maybeParameterized) 

Source Link

Usage

From source file:com.google.web.bindery.autobean.gwt.rebind.AutoBeanFactoryGenerator.java

License:Apache License

private void writeAutoBean(AutoBeanType type) throws UnableToCompleteException {
    PrintWriter pw = context.tryCreate(logger, type.getPackageNome(), type.getSimpleSourceName());
    if (pw == null) {
        // Previously-created
        return;/*  www.j  a  va  2 s.c o m*/
    }

    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());
    }

    // 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(wrapped, factory);");
    sw.println("}");

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

    // 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);
}

From source file:com.google.web.bindery.autobean.gwt.rebind.AutoBeanFactoryGenerator.java

License:Apache License

/**
 * Write an instance initializer block to populate the creators map.
 *//*from   ww  w  .j ava 2  s . co  m*/
private void writeDynamicMethods(SourceWriter sw) {
    List<JClassType> privatePeers = new ArrayList<JClassType>();
    sw.println("@Override protected void initializeCreatorMap(%s map) {",
            JsniCreatorMap.class.getCanonicalName());
    sw.indent();
    for (AutoBeanType type : model.getAllTypes()) {
        if (type.isNoWrap()) {
            continue;
        }
        String classLiteralAccessor;
        JClassType peer = type.getPeerType();
        String peerName = ModelUtils.ensureBaseType(peer).getQualifiedSourceName();
        if (peer.isPublic()) {
            classLiteralAccessor = peerName + ".class";
        } else {
            privatePeers.add(peer);
            classLiteralAccessor = "classLit_" + peerName.replace('.', '_') + "()";
        }
        // map.add(Foo.class, getConstructors_com_foo_Bar());
        sw.println("map.add(%s, getConstructors_%s());", classLiteralAccessor, peerName.replace('.', '_'));
    }
    sw.outdent();
    sw.println("}");

    /*
     * Create a native method for each peer type that isn't public since Java
     * class literal references are scoped.
     */
    for (JClassType peer : privatePeers) {
        String peerName = ModelUtils.ensureBaseType(peer).getQualifiedSourceName();
        sw.println("private native Class<?> classLit_%s() /*-{return @%s::class;}-*/;",
                peerName.replace('.', '_'), peerName);
    }

    /*
     * Create a method that returns an array containing references to the
     * constructors.
     */
    String factoryJNIName = context.getTypeOracle().findType(AutoBeanFactory.class.getCanonicalName())
            .getJNISignature();
    for (AutoBeanType type : model.getAllTypes()) {
        String peerName = ModelUtils.ensureBaseType(type.getPeerType()).getQualifiedSourceName();
        String peerJNIName = ModelUtils.ensureBaseType(type.getPeerType()).getJNISignature();
        /*-
         * private native JsArray<JSO> getConstructors_com_foo_Bar() {
         *   return [
         *     BarProxyImpl::new(ABFactory),
         *     BarProxyImpl::new(ABFactory, DelegateType)
         *   ];
         * }
         */
        sw.println("private native %s<%s> getConstructors_%s() /*-{", JsArray.class.getCanonicalName(),
                JavaScriptObject.class.getCanonicalName(), peerName.replace('.', '_'));
        sw.indent();
        sw.println("return [");
        if (type.isSimpleBean()) {
            sw.indentln("@%s::new(%s),", type.getQualifiedSourceName(), factoryJNIName);
        } else {
            sw.indentln(",");
        }
        sw.indentln("@%s::new(%s%s)", type.getQualifiedSourceName(), factoryJNIName, peerJNIName);
        sw.println("];");
        sw.outdent();
        sw.println("}-*/;");
    }
}

From source file:com.google.web.bindery.autobean.gwt.rebind.AutoBeanFactoryGenerator.java

License:Apache License

/**
 * 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./* w w  w. ja v a  2s. c  o m*/
 */
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();

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

            // Non-value types might need to be wrapped
            writeReturnWrapper(sw, type, method);
            sw.println("return toReturn;");
            break;
        case SET:
        case SET_BUILDER:
            // 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());
            if (JBeanMethod.SET_BUILDER.equals(method.getAction())) {
                sw.println("return this;");
            }
            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("};");
}

From source file:com.google.web.bindery.autobean.gwt.rebind.AutoBeanFactoryGenerator.java

License:Apache License

/**
 * Generate traversal logic./*from w ww. ja  v  a  2  s.  c o m*/
 */
private void writeTraversal(SourceWriter sw, AutoBeanType type) {
    List<AutoBeanMethod> referencedSetters = new ArrayList<AutoBeanMethod>();
    sw.println("@Override protected void traverseProperties(%s visitor, %s ctx) {",
            AutoBeanVisitor.class.getCanonicalName(), OneShotContext.class.getCanonicalName());
    sw.indent();
    sw.println("%s bean;", AbstractAutoBean.class.getCanonicalName());
    sw.println("Object value;");
    sw.println("%s propertyContext;", ClientPropertyContext.class.getCanonicalName());
    // Local variable ref cleans up emitted js
    sw.println("%1$s as = as();", type.getPeerType().getQualifiedSourceName());

    for (AutoBeanMethod method : type.getMethods()) {
        if (!method.getAction().equals(JBeanMethod.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()) {
                boolean isASetter = maybeSetter.getAction().equals(JBeanMethod.SET)
                        || maybeSetter.getAction().equals(JBeanMethod.SET_BUILDER);
                if (isASetter && maybeSetter.getPropertyName().equals(method.getPropertyName())) {
                    setter = maybeSetter;
                    break;
                }
            }
        }

        // The type of property influences the visitation
        String valueExpression = String.format("bean = (%1$s) %2$s.getAutoBean(as.%3$s());",
                AbstractAutoBean.class.getCanonicalName(), AutoBeanUtils.class.getCanonicalName(),
                method.getMethod().getName());
        String visitMethod;
        String visitVariable = "bean";
        if (method.isCollection()) {
            visitMethod = "Collection";
        } else if (method.isMap()) {
            visitMethod = "Map";
        } else if (method.isValueType()) {
            valueExpression = String.format("value = as.%s();", method.getMethod().getName());
            visitMethod = "Value";
            visitVariable = "value";
        } else {
            visitMethod = "Reference";
        }
        sw.println(valueExpression);

        // Map<List<Foo>, Bar> --> Map, List, Foo, Bar
        List<JType> typeList = new ArrayList<JType>();
        createTypeList(typeList, method.getMethod().getReturnType());
        assert typeList.size() > 0;

        /*
         * 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.
         */
        // propertyContext = new CPContext(.....);
        sw.println("propertyContext = new %s(", ClientPropertyContext.class.getCanonicalName());
        sw.indent();
        // The instance on which the context is nominally operating
        sw.println("as,");
        // Produce a JSNI reference to a setter function to call
        {
            if (setter != null) {
                // Call a method that returns a JSNI reference to the method to call
                // setFooMethodReference(),
                sw.println("%sMethodReference(as),", setter.getMethod().getName());
                referencedSetters.add(setter);
            } else {
                // Create a function that will update the values map
                // CPContext.beanSetter(FooBeanImpl.this, "foo");
                sw.println("%s.beanSetter(%s.this, \"%s\"),",
                        ClientPropertyContext.Setter.class.getCanonicalName(), type.getSimpleSourceName(),
                        method.getPropertyName());
            }
        }
        if (typeList.size() == 1) {
            sw.println("%s.class", ModelUtils.ensureBaseType(typeList.get(0)).getQualifiedSourceName());
        } else {
            // Produce the array of parameter types
            sw.print("new Class<?>[] {");
            boolean first = true;
            for (JType lit : typeList) {
                if (first) {
                    first = false;
                } else {
                    sw.print(", ");
                }
                sw.print("%s.class", ModelUtils.ensureBaseType(lit).getQualifiedSourceName());
            }
            sw.println("},");

            // Produce the array of parameter counts
            sw.print("new int[] {");
            first = true;
            for (JType lit : typeList) {
                if (first) {
                    first = false;
                } else {
                    sw.print(", ");
                }
                JParameterizedType hasParam = lit.isParameterized();
                if (hasParam == null) {
                    sw.print("0");
                } else {
                    sw.print(String.valueOf(hasParam.getTypeArgs().length));
                }
            }
            sw.println("}");
        }
        sw.outdent();
        sw.println(");");

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

    for (AutoBeanMethod method : referencedSetters) {
        JMethod jmethod = method.getMethod();
        assert jmethod.getParameters().length == 1;

        /*-
         * Setter setFooMethodReference(Object instance) {
         *   return instance.@com.example.Blah::setFoo(Lcom/example/Foo;);
         * }
         */
        sw.println("public static native %s %sMethodReference(Object instance) /*-{",
                ClientPropertyContext.Setter.class.getCanonicalName(), jmethod.getName());
        sw.indentln("return instance.@%s::%s(%s);", jmethod.getEnclosingType().getQualifiedSourceName(),
                jmethod.getName(), jmethod.getParameters()[0].getType().getJNISignature());
        sw.println("}-*/;");
    }
}

From source file:com.google.web.bindery.autobean.gwt.rebind.model.AutoBeanFactoryModel.java

License:Apache License

public AutoBeanType getPeer(JClassType beanType) {
    beanType = ModelUtils.ensureBaseType(beanType);
    return peers.get(beanType);
}

From source file:com.google.web.bindery.autobean.gwt.rebind.model.AutoBeanFactoryModel.java

License:Apache License

private AutoBeanType getAutoBeanType(JClassType beanType) {
    beanType = ModelUtils.ensureBaseType(beanType);
    AutoBeanType toReturn = peers.get(beanType);
    if (toReturn == null) {
        AutoBeanType.Builder builder = new AutoBeanType.Builder();
        builder.setOwnerFactory(this);
        builder.setPeerType(beanType);//from  ww w . j  a  v  a 2  s . c o m
        builder.setMethods(computeMethods(beanType));
        builder.setInterceptor(findInterceptor(beanType));
        if (noWrapTypes != null) {
            for (JClassType noWrap : noWrapTypes) {
                if (noWrap.isAssignableFrom(beanType)) {
                    builder.setNoWrap(true);
                    break;
                }
            }
        }
        toReturn = builder.build();
        peers.put(beanType, toReturn);
    }
    return toReturn;
}

From source file:com.google.web.bindery.autobean.gwt.rebind.model.AutoBeanFactoryModel.java

License:Apache License

private boolean methodAcceptsAutoBeanAsFirstParam(JClassType beanType, JMethod method) {
    JParameter[] params = method.getParameters();
    if (params.length == 0) {
        return false;
    }//from   w ww . j av  a 2 s . co  m
    JClassType paramAsClass = params[0].getType().isClassOrInterface();

    // First parameter is a primitive
    if (paramAsClass == null) {
        return false;
    }

    // Check using base types to account for erasure semantics
    JParameterizedType expectedFirst = oracle.getParameterizedType(autoBeanInterface,
            new JClassType[] { ModelUtils.ensureBaseType(beanType) });
    return expectedFirst.isAssignableTo(paramAsClass);
}

From source file:com.google.web.bindery.requestfactory.gwt.rebind.model.RequestFactoryModel.java

License:Apache License

private EntityProxyModel getEntityProxyType(JClassType entityProxyType) throws UnableToCompleteException {
    entityProxyType = ModelUtils.ensureBaseType(entityProxyType);
    EntityProxyModel toReturn = peers.get(entityProxyType);
    if (toReturn == null) {
        EntityProxyModel.Builder inProgress = peerBuilders.get(entityProxyType);
        if (inProgress != null) {
            toReturn = inProgress.peek();
        }//from  www .java 2  s  .co  m
    }
    if (toReturn == null) {
        EntityProxyModel.Builder builder = new EntityProxyModel.Builder();
        peerBuilders.put(entityProxyType, builder);

        // Validate possible super-proxy types first
        for (JClassType supertype : entityProxyType.getFlattenedSupertypeHierarchy()) {
            List<EntityProxyModel> superTypes = new ArrayList<EntityProxyModel>();
            if (supertype != entityProxyType && shouldAttemptProxyValidation(supertype)) {
                superTypes.add(getEntityProxyType(supertype));
            }
            builder.setSuperProxyTypes(superTypes);
        }

        builder.setQualifiedBinaryName(ModelUtils.getQualifiedBaseBinaryName(entityProxyType));
        builder.setQualifiedSourceName(ModelUtils.getQualifiedBaseSourceName(entityProxyType));
        if (entityProxyInterface.isAssignableFrom(entityProxyType)) {
            builder.setType(Type.ENTITY);
        } else if (valueProxyInterface.isAssignableFrom(entityProxyType)) {
            builder.setType(Type.VALUE);
        } else {
            poison("The type %s is not assignable to either %s or %s",
                    entityProxyInterface.getQualifiedSourceName(),
                    valueProxyInterface.getQualifiedSourceName());
            // Cannot continue, since knowing the behavior is crucial
            die(poisonedMessage());
        }

        // Get the server domain object type
        ProxyFor proxyFor = entityProxyType.getAnnotation(ProxyFor.class);
        ProxyForName proxyForName = entityProxyType.getAnnotation(ProxyForName.class);
        JsonRpcProxy jsonRpcProxy = entityProxyType.getAnnotation(JsonRpcProxy.class);
        if (proxyFor == null && proxyForName == null && jsonRpcProxy == null) {
            poison("The %s type does not have a @%s, @%s, or @%s annotation",
                    entityProxyType.getQualifiedSourceName(), ProxyFor.class.getSimpleName(),
                    ProxyForName.class.getSimpleName(), JsonRpcProxy.class.getSimpleName());
        }

        // Look at the methods declared on the EntityProxy
        List<RequestMethod> requestMethods = new ArrayList<RequestMethod>();
        Map<String, JMethod> duplicatePropertyGetters = new HashMap<String, JMethod>();
        for (JMethod method : entityProxyType.getInheritableMethods()) {
            if (method.getEnclosingType().equals(entityProxyInterface)) {
                // Ignore methods on EntityProxy
                continue;
            }
            RequestMethod.Builder methodBuilder = new RequestMethod.Builder();
            methodBuilder.setDeclarationMethod(entityProxyType, method);

            JType transportedType;
            String name = method.getName();
            if (JBeanMethod.GET.matches(method)) {
                transportedType = method.getReturnType();
                String propertyName = JBeanMethod.GET.inferName(method);
                JMethod previouslySeen = duplicatePropertyGetters.get(propertyName);
                if (previouslySeen == null) {
                    duplicatePropertyGetters.put(propertyName, method);
                } else {
                    poison("Duplicate accessors for property %s: %s() and %s()", propertyName,
                            previouslySeen.getName(), method.getName());
                }

            } else if (JBeanMethod.SET.matches(method) || JBeanMethod.SET_BUILDER.matches(method)) {
                transportedType = method.getParameters()[0].getType();

            } else if (name.equals("stableId") && method.getParameters().length == 0) {
                // Ignore any overload of stableId
                continue;
            } else {
                poison("The method %s is neither a getter nor a setter", method.getReadableDeclaration());
                continue;
            }
            validateTransportableType(methodBuilder, transportedType, false);
            RequestMethod requestMethod = methodBuilder.build();
            requestMethods.add(requestMethod);
        }
        builder.setExtraTypes(checkExtraTypes(entityProxyType, false)).setRequestMethods(requestMethods);

        toReturn = builder.build();
        peers.put(entityProxyType, toReturn);
        peerBuilders.remove(entityProxyType);
    }
    return toReturn;
}

From source file:com.google.web.bindery.requestfactory.gwt.rebind.RequestFactoryGenerator.java

License:Apache License

private void writeContextImplementations() {
    for (ContextMethod method : model.getMethods()) {
        PrintWriter pw = context.tryCreate(logger, method.getPackageName(), method.getSimpleSourceName());
        if (pw == null) {
            // Already generated
            continue;
        }//from w w w. j a  va 2s.  c o  m

        ClassSourceFileComposerFactory factory = new ClassSourceFileComposerFactory(method.getPackageName(),
                method.getSimpleSourceName());
        factory.setSuperclass(AbstractRequestContext.class.getCanonicalName());
        factory.addImplementedInterface(method.getImplementedInterfaceQualifiedSourceName());
        SourceWriter sw = factory.createSourceWriter(context, pw);

        // Constructor that accepts the parent RequestFactory
        sw.println("public %s(%s requestFactory) {super(requestFactory, %s.%s);}", method.getSimpleSourceName(),
                AbstractRequestFactory.class.getCanonicalName(), Dialect.class.getCanonicalName(),
                method.getDialect().name());

        Set<EntityProxyModel> models = findReferencedEntities(method);
        Set<JEnumType> extraEnumTypes = findExtraEnums(method);
        writeAutoBeanFactory(sw, models, extraEnumTypes);

        // Write each Request method
        for (RequestMethod request : method.getRequestMethods()) {
            JMethod jmethod = request.getDeclarationMethod();
            String operation = request.getOperation();

            // foo, bar, baz
            StringBuilder parameterArray = new StringBuilder();
            // final Foo foo, final Bar bar, final Baz baz
            StringBuilder parameterDeclaration = new StringBuilder();
            // <P extends Blah>
            StringBuilder typeParameterDeclaration = new StringBuilder();

            if (request.isInstance()) {
                // Leave a spot for the using() method to fill in later
                parameterArray.append(",null");
            }
            for (JTypeParameter param : jmethod.getTypeParameters()) {
                typeParameterDeclaration.append(",").append(param.getQualifiedSourceName());
            }
            for (JParameter param : jmethod.getParameters()) {
                parameterArray.append(",").append(param.getName());
                parameterDeclaration.append(",final ")
                        .append(param.getType().getParameterizedQualifiedSourceName()).append(" ")
                        .append(param.getName());
            }
            if (parameterArray.length() > 0) {
                parameterArray.deleteCharAt(0);
            }
            if (parameterDeclaration.length() > 0) {
                parameterDeclaration.deleteCharAt(0);
            }
            if (typeParameterDeclaration.length() > 0) {
                typeParameterDeclaration.deleteCharAt(0).insert(0, "<").append(">");
            }

            // public Request<Foo> doFoo(final Foo foo) {
            sw.println("public %s %s %s(%s) {", typeParameterDeclaration,
                    jmethod.getReturnType().getParameterizedQualifiedSourceName(), jmethod.getName(),
                    parameterDeclaration);
            sw.indent();
            // The implements clause covers InstanceRequest
            // class X extends AbstractRequest<Return> implements Request<Return> {
            sw.println("class X extends %s<%s> implements %s {", AbstractRequest.class.getCanonicalName(),
                    request.getDataType().getParameterizedQualifiedSourceName(),
                    jmethod.getReturnType().getParameterizedQualifiedSourceName());
            sw.indent();

            // public X() { super(FooRequestContext.this); }
            sw.println("public X() { super(%s.this);}", method.getSimpleSourceName());

            // This could also be gotten rid of by having only Request /
            // InstanceRequest
            sw.println("@Override public X with(String... paths) {super.with(paths); return this;}");

            // makeRequestData()
            sw.println("@Override protected %s makeRequestData() {", RequestData.class.getCanonicalName());
            String elementType = request.isCollectionType()
                    ? request.getCollectionElementType().getQualifiedSourceName() + ".class"
                    : "null";
            String returnTypeBaseQualifiedName = ModelUtils.ensureBaseType(request.getDataType())
                    .getQualifiedSourceName();
            // return new RequestData("ABC123", {parameters}, propertyRefs,
            // List.class, FooProxy.class);
            sw.indentln("return new %s(\"%s\", new Object[] {%s}, propertyRefs, %s.class, %s);",
                    RequestData.class.getCanonicalName(), operation, parameterArray,
                    returnTypeBaseQualifiedName, elementType);
            sw.println("}");

            /*
             * Only support extra properties in JSON-RPC payloads. Could add this to
             * standard requests to provide out-of-band data.
             */
            if (method.getDialect().equals(Dialect.JSON_RPC)) {
                for (JMethod setter : request.getExtraSetters()) {
                    PropertyName propertyNameAnnotation = setter.getAnnotation(PropertyName.class);
                    String propertyName = propertyNameAnnotation == null ? JBeanMethod.SET.inferName(setter)
                            : propertyNameAnnotation.value();
                    String maybeReturn = JBeanMethod.SET_BUILDER.matches(setter) ? "return this;" : "";
                    sw.println("%s { getRequestData().setNamedParameter(\"%s\", %s); %s}",
                            setter.getReadableDeclaration(false, false, false, false, true), propertyName,
                            setter.getParameters()[0].getName(), maybeReturn);
                }
            }

            // end class X{}
            sw.outdent();
            sw.println("}");

            // Instantiate, enqueue, and return
            sw.println("X x = new X();");

            if (request.getApiVersion() != null) {
                sw.println("x.getRequestData().setApiVersion(\"%s\");",
                        Generator.escape(request.getApiVersion()));
            }

            // JSON-RPC payloads send their parameters in a by-name fashion
            if (method.getDialect().equals(Dialect.JSON_RPC)) {
                for (JParameter param : jmethod.getParameters()) {
                    PropertyName annotation = param.getAnnotation(PropertyName.class);
                    String propertyName = annotation == null ? param.getName() : annotation.value();
                    boolean isContent = param.isAnnotationPresent(JsonRpcContent.class);
                    if (isContent) {
                        sw.println("x.getRequestData().setRequestContent(%s);", param.getName());
                    } else {
                        sw.println("x.getRequestData().setNamedParameter(\"%s\", %s);", propertyName,
                                param.getName());
                    }
                }
            }

            // See comment in AbstractRequest.using(EntityProxy)
            if (!request.isInstance()) {
                sw.println("addInvocation(x);");
            }
            sw.println("return x;");
            sw.outdent();
            sw.println("}");
        }

        sw.commit(logger);
    }
}