Package com.google.gwt.user.rebind.rpc

Source Code of com.google.gwt.user.rebind.rpc.RemoteServiceAsyncValidator

/*
* Copyright 2007 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.user.rebind.rpc;

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.JMethod;
import com.google.gwt.core.ext.typeinfo.JPackage;
import com.google.gwt.core.ext.typeinfo.JParameter;
import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.user.client.rpc.AsyncCallback;

import java.util.Map;
import java.util.TreeMap;

/**
* Validates the asynchronous version of
* {@link com.google.gwt.user.client.rpc.RemoteService RemoteService} interface.
*/
class RemoteServiceAsyncValidator {
  private static String synthesizeAsynchronousInterfaceDefinition(
      JClassType serviceIntf) {
    StringBuffer sb = new StringBuffer();
    JPackage pkg = serviceIntf.getPackage();
    if (pkg != null) {
      sb.append("\npackage ");
      sb.append(pkg.getName());
      sb.append(";\n");
    }

    sb.append("\npublic interface ");
    sb.append(serviceIntf.getSimpleSourceName());
    sb.append("Async {\n");

    JMethod[] methods = serviceIntf.getOverridableMethods();
    for (int index = 0; index < methods.length; ++index) {
      JMethod method = methods[index];
      assert (method != null);

      sb.append("\tvoid ");
      sb.append(method.getName());
      sb.append("(");

      JParameter[] params = method.getParameters();
      for (int paramIndex = 0; paramIndex < params.length; ++paramIndex) {
        JParameter param = params[paramIndex];

        if (paramIndex > 0) {
          sb.append(", ");
        }

        sb.append(param.toString());
      }

      if (params.length > 0) {
        sb.append(", ");
      }

      sb.append(AsyncCallback.class.getName());
      sb.append(" arg");
      sb.append(Integer.toString(params.length + 1));
      sb.append(");\n");
    }

    sb.append("}");

    return sb.toString();
  }

  private final JClassType asyncCallbackClass;
  private final TypeOracle typeOracle;

  RemoteServiceAsyncValidator(TypeOracle typeOracle) throws NotFoundException {
    this.typeOracle = typeOracle;
    asyncCallbackClass = typeOracle.getType(AsyncCallback.class.getName());
  }

  /**
   * Checks that for there is an asynchronous
   * {@link com.google.gwt.user.client.rpc.RemoteService RemoteService}
   * interface and that it has an asynchronous version of every synchronous
   * method.
   *
   * @throws UnableToCompleteException if the asynchronous
   *           {@link com.google.gwt.user.client.rpc.RemoteService RemoteService}
   *           was not found, or if it does not have an asynchronous method
   *           version of every synchronous one
   */
  public void validateRemoteServiceAsync(TreeLogger logger,
      JClassType remoteService) throws UnableToCompleteException {
    TreeLogger branch = logger.branch(TreeLogger.DEBUG,
        "Checking the synchronous interface '"
            + remoteService.getQualifiedSourceName()
            + "' against its asynchronous version '"
            + remoteService.getQualifiedSourceName() + "Async'", null);
    boolean failed = false;
    JClassType serviceAsync = typeOracle.findType(remoteService.getQualifiedSourceName()
        + "Async");
    if (serviceAsync == null) {
      failed = true;
      branch.branch(TreeLogger.ERROR,
          "Could not find an asynchronous version for the service interface "
              + remoteService.getQualifiedSourceName(), null);
    } else {
      JMethod[] asyncMethods = serviceAsync.getOverridableMethods();
      JMethod[] syncMethods = remoteService.getOverridableMethods();

      if (asyncMethods.length != syncMethods.length) {
        branch.branch(TreeLogger.ERROR, "The asynchronous version of "
            + remoteService.getQualifiedSourceName() + " has "
            + (asyncMethods.length > syncMethods.length ? "more" : "less")
            + " methods than the synchronous version", null);
        failed = true;
      } else {
        Map asyncMethodMap = initializeAsyncMethodMap(asyncMethods);
        for (int i = 0; i < syncMethods.length; ++i) {
          JMethod syncMethod = syncMethods[i];
          String asyncSig = computeAsyncMethodSignature(syncMethod);
          JMethod asyncMethod = (JMethod) asyncMethodMap.get(asyncSig);
          if (asyncMethod == null) {
            branch.branch(TreeLogger.ERROR,
                "Missing asynchronous version of the synchronous method '"
                    + syncMethod.getReadableDeclaration() + "'", null);
            failed = true;
          } else if (asyncMethod.getReturnType() != JPrimitiveType.VOID) {
            branch.branch(TreeLogger.ERROR,
                "The asynchronous version of the synchronous method '"
                    + syncMethod.getReadableDeclaration()
                    + "' must have a 'void' return type", null);
            failed = true;
          }
        }
      }
    }

    if (failed) {
      logValidAsyncInterfaceDeclaration(branch, remoteService);
      throw new UnableToCompleteException();
    }
  }

  private String computeAsyncMethodSignature(JMethod syncMethod) {
    return computeInternalSignature(syncMethod) + "/"
        + asyncCallbackClass.getQualifiedSourceName();
  }

  private String computeInternalSignature(JMethod method) {
    StringBuffer sb = new StringBuffer();
    sb.setLength(0);
    sb.append(method.getName());
    JParameter[] params = method.getParameters();
    for (int j = 0; j < params.length; j++) {
      JParameter param = params[j];
      sb.append("/");
      sb.append(param.getType().getQualifiedSourceName());
    }
    return sb.toString();
  }

  /**
   * Builds a map of asynchronous method internal signatures to the
   * corresponding asynchronous {@link JMethod}.
   */
  private Map initializeAsyncMethodMap(JMethod[] asyncMethods) {
    Map /* <String,JClassType> */sigs = new TreeMap();
    for (int i = 0; i < asyncMethods.length; ++i) {
      JMethod asyncMethod = asyncMethods[i];
      sigs.put(computeInternalSignature(asyncMethod), asyncMethod);
    }
    return sigs;
  }

  private void logValidAsyncInterfaceDeclaration(TreeLogger logger,
      JClassType remoteService) {
    TreeLogger branch = logger.branch(TreeLogger.INFO,
        "A valid definition for the asynchronous version of interface '"
            + remoteService.getQualifiedSourceName() + "' would be:\n", null);
    branch.log(TreeLogger.ERROR,
        synthesizeAsynchronousInterfaceDefinition(remoteService), null);
  }
}
TOP

Related Classes of com.google.gwt.user.rebind.rpc.RemoteServiceAsyncValidator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.