/*
 * Copyright 2015 the original author or authors.
 *
 * 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 org.gradle.model.internal.manage.schema.extract;

import org.apache.commons.lang.StringUtils;
import org.gradle.api.Nullable;

import java.lang.reflect.Method;

/**
 * Distinguish get getters, is getters and setters from non-property methods.
 */
public enum PropertyAccessorType {
    IS_GETTER, GET_GETTER, SETTER;

    public String propertyNameFor(Method method) {
        String methodName = method.getName();
        int prefixLength = this == PropertyAccessorType.IS_GETTER ? 2 : 3;
        String methodNamePrefixRemoved = methodName.substring(prefixLength);
        return StringUtils.uncapitalize(methodNamePrefixRemoved);
    }

    @Nullable
    public static PropertyAccessorType of(Method method) {
        String methodName = method.getName();
        if (!hasVoidReturnType(method) && takesNoParameter(method)) {
            if (isGetGetterName(methodName)) {
                return GET_GETTER;
            }
            if (isIsGetterName(methodName)) {
                return IS_GETTER;
            }
        }
        if (hasVoidReturnType(method) && takesSingleParameter(method) && isSetterName(methodName)) {
            return SETTER;
        }
        return null;
    }

    public static boolean hasVoidReturnType(Method method) {
        return void.class.equals(method.getReturnType());
    }

    public static boolean takesNoParameter(Method method) {
        return method.getParameterTypes().length == 0;
    }

    public static boolean takesSingleParameter(Method method) {
        return method.getParameterTypes().length == 1;
    }

    public static boolean isPropertyMethodName(String methodName) {
        return isGetGetterName(methodName) || isIsGetterName(methodName) || isSetterName(methodName);
    }

    public static boolean isGetterName(String methodName) {
        return isGetGetterName(methodName) || isIsGetterName(methodName);
    }

    public static boolean isGetGetterName(String methodName) {
        return methodName.startsWith("get") && !"get".equals(methodName) && isNthCharUpperCase(methodName, 4);
    }

    public static boolean isIsGetterName(String methodName) {
        return methodName.startsWith("is") && !"is".equals(methodName) && isNthCharUpperCase(methodName, 3);
    }

    public static boolean isSetterName(String methodName) {
        return methodName.startsWith("set") && !"set".equals(methodName) && isNthCharUpperCase(methodName, 4);
    }

    private static boolean isNthCharUpperCase(String methodName, int position) {
        return Character.isUpperCase(methodName.charAt(position - 1));
    }
}

@@ -734,19 +734,36 @@
 dle.
-api.Nullabl
+model.internal.type.ModelTyp
 e;%0A%0A
@@ -814,20 +814,24 @@
 tinguish
- 
+es %22
 get
+%22
  getters
@@ -832,18 +832,20 @@
 etters, 
+%22
 is
+%22
  getters
@@ -940,48 +940,225 @@
 TTER
-, GET_GETTER, SETTER;%0A%0A
+(2) %7B%0A        @Override%0A        public ModelType%3C?%3E propertyTypeFor(Method method) %7B%0A            return ModelType.returnType(method);%0A        %7D%0A    %7D,%0A%0A    GET_GETTER(3) %7B%0A        @Override%0A 
     
+   
 public 
-String
+ModelType%3C?%3E
  pro
@@ -1162,19 +1162,19 @@
 property
-Nam
+Typ
 eFor(Met
@@ -1199,53 +1199,248 @@
     
-String methodName = method.getName();%0A       
+    return ModelType.returnType(method);%0A        %7D%0A    %7D,%0A%0A    SETTER(3) %7B%0A        @Override%0A        public ModelType%3C?%3E propertyTypeFor(Method method) %7B%0A            return ModelType.paramType(method, 0);%0A        %7D%0A    %7D;%0A%0A    private final
  int
@@ -1456,18 +1456,14 @@
 ngth
- = this ==
+;%0A%0A   
  Pro
@@ -1483,27 +1483,128 @@
 Type
-.IS_GETTER ? 2 : 3;
+(int prefixLength) %7B%0A        this.prefixLength = prefixLength;%0A    %7D%0A%0A    public String propertyNameFor(Method method) %7B
 %0A   
@@ -1647,20 +1647,26 @@
 = method
+.get
 Name
+()
 .substri
@@ -1764,17 +1764,69 @@
     
-@Nullable
+abstract public ModelType%3C?%3E propertyTypeFor(Method method);%0A
 %0A   
@@ -3052,37 +3052,38 @@
 e);%0A    %7D%0A%0A    p
-ublic
+rivate
  static boolean 
@@ -3234,37 +3234,38 @@
 4);%0A    %7D%0A%0A    p
-ublic
+rivate
  static boolean 

Simplify PropertyAccessorType