Allow external server operation enum
Review at http://gwt-code-reviews.appspot.com/311801

Review by: amitmanjhi@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7879 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/bikeshed/src/com/google/gwt/bikeshed/list/client/IdentityColumn.java b/bikeshed/src/com/google/gwt/bikeshed/list/client/IdentityColumn.java
index 116368d..4cb93bb 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/list/client/IdentityColumn.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/list/client/IdentityColumn.java
@@ -28,7 +28,6 @@
 
   /**
    * @param cell
-   * @param hasKey
    */
   public IdentityColumn(Cell<T, Void> cell) {
     super(cell);
diff --git a/bikeshed/src/com/google/gwt/requestfactory/rebind/RequestFactoryGenerator.java b/bikeshed/src/com/google/gwt/requestfactory/rebind/RequestFactoryGenerator.java
index f2d0fcb..e8ad800 100644
--- a/bikeshed/src/com/google/gwt/requestfactory/rebind/RequestFactoryGenerator.java
+++ b/bikeshed/src/com/google/gwt/requestfactory/rebind/RequestFactoryGenerator.java
@@ -37,9 +37,7 @@
 import com.google.gwt.valuestore.client.ValueStoreJsonImpl;
 
 import java.io.PrintWriter;
-import java.util.ArrayList;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Set;
 
 /**
@@ -88,10 +86,78 @@
     return packageName + "." + implName;
   }
 
-  private void generateNestedInterfaceImplementation(TreeLogger logger,
+  private void generateOnce(TreeLogger logger,
+      GeneratorContext generatorContext, PrintWriterManager printWriters,
+      PrintWriter out, JClassType interfaceType, String packageName,
+      String implName) throws UnableToCompleteException {
+
+    logger = logger.branch(TreeLogger.INFO, String.format(
+        "Generating implementation of %s", interfaceType.getName()));
+
+    ClassSourceFileComposerFactory f = new ClassSourceFileComposerFactory(
+        packageName, implName);
+    f.addImport(RequestFactoryJsonImpl.class.getName());
+    f.addImport(ValueStoreJsonImpl.class.getName());
+    f.addImplementedInterface(interfaceType.getQualifiedSourceName());
+    f.setSuperclass(RequestFactoryJsonImpl.class.getName());
+
+    SourceWriter sw = f.createSourceWriter(generatorContext, out);
+    sw.println();
+
+    // the return types tell us what request selector interfaces
+    // to implement
+    Set<JClassType> requestSelectors = new HashSet<JClassType>();
+    for (JMethod methodType : interfaceType.getMethods()) {
+      JType returnType = methodType.getReturnType();
+      if (null == returnType) {
+        logger.log(TreeLogger.ERROR, String.format(
+            "Illegal return type for %s. Methods of %s must return interfaces",
+            methodType.getName(), interfaceType.getName()));
+        throw new UnableToCompleteException();
+      }
+      JClassType asInterface = returnType.isInterface();
+      if (null == asInterface) {
+        logger.log(TreeLogger.ERROR, String.format(
+            "Illegal return type for %s. Methods of %s must return interfaces",
+            methodType.getName(), interfaceType.getName()));
+        throw new UnableToCompleteException();
+      }
+      requestSelectors.add(asInterface);
+    }
+    // write a method for each sub-interface
+    for (JClassType requestSelector : requestSelectors) {
+      String simpleSourceName = requestSelector.getSimpleSourceName();
+      sw.println("public " + simpleSourceName + " "
+          + getMethodName(simpleSourceName) + "() {");
+      sw.indent();
+      sw.println("return new " + simpleSourceName + "Impl(this);");
+      sw.outdent();
+      sw.println("}");
+      sw.println();
+    }
+    sw.outdent();
+    sw.println("}");
+
+    // generate an implementation for each request selector
+
+    for (JClassType nestedInterface : requestSelectors) {
+      String nestedImplName = nestedInterface.getName() + "Impl";
+      PrintWriter pw = printWriters.makePrintWriterFor(nestedImplName);
+      if (pw != null) {
+        generateRequestSelectorImplementation(logger, generatorContext, pw,
+            nestedInterface, interfaceType, packageName, nestedImplName);
+      }
+    }
+    printWriters.commit();
+  }
+
+  private void generateRequestSelectorImplementation(TreeLogger logger,
       GeneratorContext generatorContext, PrintWriter out,
       JClassType interfaceType, JClassType mainType, String packageName,
       String implName) throws UnableToCompleteException {
+    logger = logger.branch(TreeLogger.INFO, String.format(
+        "Generating implementation of %s", interfaceType.getName()));
+    
     ClassSourceFileComposerFactory f = new ClassSourceFileComposerFactory(
         packageName, implName);
     f.addImport(ClientRequestObject.class.getName());
@@ -152,59 +218,6 @@
     sw.println("}");
   }
 
-  private void generateOnce(TreeLogger logger,
-      GeneratorContext generatorContext, PrintWriterManager printWriters,
-      PrintWriter out, JClassType interfaceType, String packageName,
-      String implName) throws UnableToCompleteException {
-    ClassSourceFileComposerFactory f = new ClassSourceFileComposerFactory(
-        packageName, implName);
-    f.addImport(RequestFactoryJsonImpl.class.getName());
-    f.addImport(ValueStoreJsonImpl.class.getName());
-    f.addImplementedInterface(interfaceType.getQualifiedSourceName());
-    f.setSuperclass(RequestFactoryJsonImpl.class.getName());
-
-    SourceWriter sw = f.createSourceWriter(generatorContext, out);
-    sw.println();
-
-    // get the sub-interfaces
-    List<JClassType> nestedInterfaces = new ArrayList<JClassType>();
-    for (JClassType nestedType : interfaceType.getNestedTypes()) {
-      if (nestedType.isInterface() != null) {
-        nestedInterfaces.add(nestedType);
-      }
-    }
-    // write a method for each sub-interface
-    for (JClassType nestedInterface : nestedInterfaces) {
-      String simpleSourceName = nestedInterface.getSimpleSourceName();
-      sw.println("public " + simpleSourceName + " "
-          + getMethodName(simpleSourceName) + "() {");
-      sw.indent();
-      sw.println("return new " + simpleSourceName + "Impl(this);");
-      sw.outdent();
-      sw.println("}");
-      sw.println();
-    }
-    sw.outdent();
-    sw.println("}");
-
-    // generate an implementation for each nested interface
-    String interfacePrefix = interfaceType.getName() + ".";
-    for (JClassType nestedInterface : nestedInterfaces) {
-      String nestedImplName = nestedInterface.getName();
-      if (nestedImplName.startsWith(interfacePrefix)) {
-        nestedImplName = nestedImplName.substring(interfacePrefix.length(),
-            nestedImplName.length())
-            + "Impl";
-      }
-      PrintWriter pw = printWriters.makePrintWriterFor(nestedImplName);
-      if (pw != null) {
-        generateNestedInterfaceImplementation(logger, generatorContext, pw,
-            nestedInterface, interfaceType, packageName, nestedImplName);
-      }
-    }
-    printWriters.commit();
-  }
-
   /**
    * This method is very similar to {@link
    * com.google.gwt.core.ext.typeinfo.JMethod.getReadableDeclaration()}. The
@@ -262,7 +275,7 @@
    * Inspect all the get methods that are returning a List of "domain type".
    * Return the domain type.
    * <p>
-   * TODO: Lift the restriction that there be just one return type. 
+   * TODO: Lift the restriction that there be just one return type.
    */
   private JClassType getReturnType(TreeLogger logger, JClassType interfaceType)
       throws UnableToCompleteException {
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/request/EmployeeRequest.java b/bikeshed/src/com/google/gwt/sample/expenses/gwt/request/EmployeeRequest.java
new file mode 100644
index 0000000..f84426c
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/sample/expenses/gwt/request/EmployeeRequest.java
@@ -0,0 +1,31 @@
+/*
+ * 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.sample.expenses.gwt.request;
+
+import com.google.gwt.requestfactory.shared.EntityListRequest;
+import com.google.gwt.requestfactory.shared.ServerOperation;
+
+/**
+ * Request selector.
+ */
+public interface EmployeeRequest {
+
+  /**
+   * @return a request object
+   */
+  @ServerOperation("FIND_ALL_EMPLOYEES")
+  EntityListRequest<EmployeeKey> findAllEmployees();
+}
\ No newline at end of file
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/request/ExpensesRequestFactory.java b/bikeshed/src/com/google/gwt/sample/expenses/gwt/request/ExpensesRequestFactory.java
index 2307d30..9bbed9b 100644
--- a/bikeshed/src/com/google/gwt/sample/expenses/gwt/request/ExpensesRequestFactory.java
+++ b/bikeshed/src/com/google/gwt/sample/expenses/gwt/request/ExpensesRequestFactory.java
@@ -15,12 +15,7 @@
  */
 package com.google.gwt.sample.expenses.gwt.request;
 
-import com.google.gwt.requestfactory.shared.EntityListRequest;
-import com.google.gwt.requestfactory.shared.LongString;
 import com.google.gwt.requestfactory.shared.RequestFactory;
-import com.google.gwt.requestfactory.shared.ServerOperation;
-import com.google.gwt.valuestore.shared.ValueRef;
-import com.google.gwt.valuestore.shared.ValuesKey;
 
 /**
  * "API generated" for the service methods of
@@ -32,100 +27,6 @@
 public interface ExpensesRequestFactory extends RequestFactory {
 
   /**
-   * Request selector.
-   */
-  interface EmployeeRequest {
-
-    /**
-     * @return a request object
-     */
-    @ServerOperation("FIND_ALL_EMPLOYEES")
-    EntityListRequest<EmployeeKey> findAllEmployees();
-  }
-
-  /**
-   * Request selector.
-   */
-  interface ReportRequest {
-
-    /**
-     * @return a request object
-     */
-    @ServerOperation("FIND_REPORTS_BY_EMPLOYEE")
-    EntityListRequest<ReportKey> findReportsByEmployee(
-        @LongString ValueRef<EmployeeKey, String> id);
-
-    /**
-     * @return a request object
-     */
-    @ServerOperation("FIND_ALL_REPORTS")
-    EntityListRequest<ReportKey> findAllReports();
-  }
-
-  /**
-   * Represents the server side operation to be carried out. This enum will be
-   * generated by the JPA-aware tool.
-   *
-   */
-  public enum ServerSideOperation implements RequestDefinition {
-    FIND_ALL_EMPLOYEES("com.google.gwt.sample.expenses.server.domain.Employee",
-        "findAllEmployees", null,
-        com.google.gwt.sample.expenses.gwt.request.EmployeeKey.class), //
-    FIND_ALL_REPORTS("com.google.gwt.sample.expenses.server.domain.Report",
-        "findAllReports", null,
-        com.google.gwt.sample.expenses.gwt.request.ReportKey.class), //
-    FIND_REPORTS_BY_EMPLOYEE(
-        "com.google.gwt.sample.expenses.server.domain.Report",
-        "findReportsByEmployee", new Class[] {java.lang.Long.class},
-        com.google.gwt.sample.expenses.gwt.request.ReportKey.class); //
-
-    /**
-     * the server side domain class.
-     */
-    private final String domainClassName;
-
-    /**
-     * the methodName of the domain class that is to be invoked.
-     */
-    private final String domainMethodName;
-
-    /**
-     * the parameterTypes of the parameters the domain method requires.
-     */
-    private final Class<?>[] parameterTypes;
-
-    /**
-     * for "READ" methods, the methods return a List. This class denotes the types
-     * of the elements of the list.
-     */
-    private final Class<? extends ValuesKey<?>> returnType;
-
-    private ServerSideOperation(String domainClassName, String domainMethodName,
-        Class<?> parameterTypes[], Class<? extends ValuesKey<?>> entryReturnType) {
-      this.domainClassName = domainClassName;
-      this.domainMethodName = domainMethodName;
-      this.parameterTypes = parameterTypes;
-      this.returnType = entryReturnType;
-    }
-
-    public String getDomainClassName() {
-      return domainClassName;
-    }
-
-    public String getDomainMethodName() {
-      return domainMethodName;
-    }
-
-    public Class<?>[] getParameterTypes() {
-      return parameterTypes;
-    }
-
-    public Class<? extends ValuesKey<?>> getReturnType() {
-      return returnType;
-    }
-  }
-
-  /**
    * @return a request selector
    */
   EmployeeRequest employeeRequest();
@@ -134,6 +35,7 @@
    * @return a request selector
    */
   ReportRequest reportRequest();
+  
   // todo: probably will also need something like this to support custom service methods
   // that do mutations, not just find:
 //  public ReportRequest reportRequest(DeltaValueStore deltas) {
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/request/ExpensesServerSideOperations.java b/bikeshed/src/com/google/gwt/sample/expenses/gwt/request/ExpensesServerSideOperations.java
new file mode 100644
index 0000000..7f10ff6
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/sample/expenses/gwt/request/ExpensesServerSideOperations.java
@@ -0,0 +1,81 @@
+/*
+ * 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.sample.expenses.gwt.request;
+
+import com.google.gwt.requestfactory.shared.RequestFactory.RequestDefinition;
+import com.google.gwt.valuestore.shared.ValuesKey;
+
+/**
+ * Represents the server side operation to be carried out. This enum will be
+ * generated by the JPA-aware tool.
+ */
+public enum ExpensesServerSideOperations implements RequestDefinition {
+  FIND_ALL_EMPLOYEES("com.google.gwt.sample.expenses.server.domain.Employee",
+      "findAllEmployees", null,
+      com.google.gwt.sample.expenses.gwt.request.EmployeeKey.class), //
+  FIND_ALL_REPORTS("com.google.gwt.sample.expenses.server.domain.Report",
+      "findAllReports", null,
+      com.google.gwt.sample.expenses.gwt.request.ReportKey.class), //
+  FIND_REPORTS_BY_EMPLOYEE(
+      "com.google.gwt.sample.expenses.server.domain.Report",
+      "findReportsByEmployee", new Class[] {java.lang.Long.class},
+      com.google.gwt.sample.expenses.gwt.request.ReportKey.class); //
+
+  /**
+   * the server side domain class.
+   */
+  private final String domainClassName;
+
+  /**
+   * the methodName of the domain class that is to be invoked.
+   */
+  private final String domainMethodName;
+
+  /**
+   * the parameterTypes of the parameters the domain method requires.
+   */
+  private final Class<?>[] parameterTypes;
+
+  /**
+   * for "READ" methods, the methods return a List. This class denotes the types
+   * of the elements of the list.
+   */
+  private final Class<? extends ValuesKey<?>> returnType;
+
+  private ExpensesServerSideOperations(String domainClassName, String domainMethodName,
+      Class<?> parameterTypes[], Class<? extends ValuesKey<?>> entryReturnType) {
+    this.domainClassName = domainClassName;
+    this.domainMethodName = domainMethodName;
+    this.parameterTypes = parameterTypes;
+    this.returnType = entryReturnType;
+  }
+
+  public String getDomainClassName() {
+    return domainClassName;
+  }
+
+  public String getDomainMethodName() {
+    return domainMethodName;
+  }
+
+  public Class<?>[] getParameterTypes() {
+    return parameterTypes;
+  }
+
+  public Class<? extends ValuesKey<?>> getReturnType() {
+    return returnType;
+  }
+}
\ No newline at end of file
diff --git a/bikeshed/src/com/google/gwt/sample/expenses/gwt/request/ReportRequest.java b/bikeshed/src/com/google/gwt/sample/expenses/gwt/request/ReportRequest.java
new file mode 100644
index 0000000..4be2dab
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/sample/expenses/gwt/request/ReportRequest.java
@@ -0,0 +1,40 @@
+/*
+ * 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.sample.expenses.gwt.request;
+
+import com.google.gwt.requestfactory.shared.EntityListRequest;
+import com.google.gwt.requestfactory.shared.LongString;
+import com.google.gwt.requestfactory.shared.ServerOperation;
+import com.google.gwt.valuestore.shared.ValueRef;
+
+/**
+ * Request selector.
+ */
+public interface ReportRequest {
+
+  /**
+   * @return a request object
+   */
+  @ServerOperation("FIND_REPORTS_BY_EMPLOYEE")
+  EntityListRequest<ReportKey> findReportsByEmployee(
+      @LongString ValueRef<EmployeeKey, String> id);
+
+  /**
+   * @return a request object
+   */
+  @ServerOperation("FIND_ALL_REPORTS")
+  EntityListRequest<ReportKey> findAllReports();
+}
\ No newline at end of file
diff --git a/bikeshed/war/WEB-INF/web.xml b/bikeshed/war/WEB-INF/web.xml
index a308f02..bb3088e 100644
--- a/bikeshed/war/WEB-INF/web.xml
+++ b/bikeshed/war/WEB-INF/web.xml
@@ -8,7 +8,7 @@
   <!--  Configures expensesData servlet -->
   <context-param>
     <param-name>servlet.serverOperation</param-name>
-    <param-value>com.google.gwt.sample.expenses.gwt.request.ExpensesRequestFactory$ServerSideOperation</param-value>
+    <param-value>com.google.gwt.sample.expenses.gwt.request.ExpensesRequests</param-value>
   </context-param>
 
   <!-- Servlets -->