/* * Copyright 2011 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.web.bindery.autobean.gwt.rebind.model; import static com.google.web.bindery.autobean.vm.impl.BeanMethod.GET_PREFIX; import static com.google.web.bindery.autobean.vm.impl.BeanMethod.HAS_PREFIX; import static com.google.web.bindery.autobean.vm.impl.BeanMethod.IS_PREFIX; import static com.google.web.bindery.autobean.vm.impl.BeanMethod.SET_PREFIX; import com.google.gwt.core.ext.typeinfo.JClassType; import com.google.gwt.core.ext.typeinfo.JMethod; import com.google.gwt.core.ext.typeinfo.JPrimitiveType; import com.google.gwt.core.ext.typeinfo.JType; import java.beans.Introspector; /** * Common utility code for matching {@link JMethod} and against bean-style * accessor semantics. * * @see com.google.web.bindery.autobean.vm.impl.BeanMethod */ public enum JBeanMethod { GET { @Override public String inferName(JMethod method) { if (isBooleanProperty(method) && method.getName().startsWith(IS_PREFIX)) { return Introspector.decapitalize(method.getName().substring(2)); } return super.inferName(method); } @Override public boolean matches(JMethod method) { if (method.getParameters().length > 0) { return false; } if (isBooleanProperty(method)) { return true; } String name = method.getName(); if (name.startsWith(GET_PREFIX) && name.length() > 3) { return true; } return false; } /** * Returns {@code true} if the method matches {@code boolean isFoo()} or * {@code boolean hasFoo()} property accessors. */ private boolean isBooleanProperty(JMethod method) { JType returnType = method.getReturnType(); if (JPrimitiveType.BOOLEAN.equals(returnType) || method.getEnclosingType().getOracle().findType( Boolean.class.getCanonicalName()).equals(returnType)) { String name = method.getName(); if (name.startsWith(IS_PREFIX) && name.length() > 2) { return true; } if (name.startsWith(HAS_PREFIX) && name.length() > 3) { return true; } } return false; } }, SET { @Override public boolean matches(JMethod method) { if (!JPrimitiveType.VOID.equals(method.getReturnType())) { return false; } if (method.getParameters().length != 1) { return false; } String name = method.getName(); if (name.startsWith(SET_PREFIX) && name.length() > 3) { return true; } return false; } }, SET_BUILDER { @Override public boolean matches(JMethod method) { JClassType returnClass = method.getReturnType().isClassOrInterface(); if (returnClass == null || !returnClass.isAssignableFrom(method.getEnclosingType())) { return false; } if (method.getParameters().length != 1) { return false; } String name = method.getName(); if (name.startsWith(SET_PREFIX) && name.length() > 3) { return true; } return false; } }, CALL { /** * Matches all leftover methods. */ @Override public boolean matches(JMethod method) { return true; } }; /** * Determine which Action a method maps to. */ public static JBeanMethod which(JMethod method) { for (JBeanMethod action : JBeanMethod.values()) { if (action.matches(method)) { return action; } } throw new RuntimeException("CALL should have matched"); } /** * Infer the name of a property from the method. */ public String inferName(JMethod method) { if (this == CALL) { throw new UnsupportedOperationException( "Cannot infer a property name for a CALL-type method"); } return Introspector.decapitalize(method.getName().substring(3)); } /** * Returns {@code true} if the BeanLikeMethod matches the method. */ public abstract boolean matches(JMethod method); }