1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.javadoc.internal.doclets.toolkit; 27 28 import java.util.regex.Pattern; 29 import javax.lang.model.element.ExecutableElement; 30 import javax.lang.model.type.TypeKind; 31 import javax.lang.model.type.TypeMirror; 32 import javax.lang.model.util.Types; 33 34 /** 35 * This class provides basic JavaFX property related utility methods. 36 * Refer to the JavaFX conventions in the VisibleMemberTable comments. 37 */ 38 public class PropertyUtils { 39 40 final TypeMirror jbObservableType; 41 42 final Pattern fxMethodPatterns; 43 44 final boolean javafx; 45 46 final Types typeUtils; 47 48 PropertyUtils(BaseConfiguration configuration) { 49 50 javafx = configuration.javafx; 51 52 typeUtils = configuration.docEnv.getTypeUtils(); 53 54 // Disable strict check for JDK's without FX. 55 TypeMirror jboType = configuration.disableJavaFxStrictChecks 56 ? null 57 : configuration.utils.getSymbol("javafx.beans.Observable"); 58 59 jbObservableType = jboType != null 60 ? configuration.docEnv.getTypeUtils().erasure(jboType) 61 : null; 62 63 fxMethodPatterns = javafx 64 ? Pattern.compile("[sg]et\\p{Upper}.*||is\\p{Upper}.*") 65 : null; 66 } 67 68 /** 69 * Returns a base name for a property method. Supposing we 70 * have {@code BooleanProperty acmeProperty()}, then "acme" 71 * will be returned. 72 * @param propertyMethod 73 * @return the base name of a property method. 74 */ 75 public String getBaseName(ExecutableElement propertyMethod) { 76 String name = propertyMethod.getSimpleName().toString(); 77 String baseName = name.substring(0, name.indexOf("Property")); 78 return baseName; 79 } 80 81 /** 82 * Returns a property getter's name. Supposing we have a property 83 * method {@code DoubleProperty acmeProperty()}, then "getAcme" 84 * will be returned. 85 * @param propertyMethod 86 * @return the property getter's name. 87 */ 88 public String getGetName(ExecutableElement propertyMethod) { 89 String baseName = getBaseName(propertyMethod); 90 String fnUppercased = "" + 91 Character.toUpperCase(baseName.charAt(0)) + baseName.substring(1); 92 return "get" + fnUppercased; 93 } 94 95 /** 96 * Returns an "is" method's name for a property method. Supposing 97 * we have a property method {@code BooleanProperty acmeProperty()}, 98 * then "isAcme" will be returned. 99 * @param propertyMethod 100 * @return the property is getter's name. 101 */ 102 public String getIsName(ExecutableElement propertyMethod) { 103 String baseName = getBaseName(propertyMethod); 104 String fnUppercased = "" + 105 Character.toUpperCase(baseName.charAt(0)) + baseName.substring(1); 106 return "is" + fnUppercased; 107 } 108 109 /** 110 * Returns true if a property method could have an "is" method, meaning 111 * {@code isAcme} could exist for a property method. 112 * @param propertyMethod 113 * @return true if the property could have an "is" method, false otherwise. 114 */ 115 public boolean hasIsMethod(ExecutableElement propertyMethod) { 116 String propertyTypeName = propertyMethod.getReturnType().toString(); 117 return "boolean".equals(propertyTypeName) || 118 propertyTypeName.endsWith("BooleanProperty"); 119 } 120 121 /** 122 * Returns a property setter's name. Supposing we have a property 123 * method {@code DoubleProperty acmeProperty()}, then "setAcme" 124 * will be returned. 125 * @param propertyMethod 126 * @return the property setter's method name. 127 */ 128 public String getSetName(ExecutableElement propertyMethod) { 129 String baseName = getBaseName(propertyMethod); 130 String fnUppercased = "" + 131 Character.toUpperCase(baseName.charAt(0)) + baseName.substring(1); 132 return "set" + fnUppercased; 133 } 134 135 /** 136 * Returns true if the given setter method is a valid property setter 137 * method. 138 * @param setterMethod 139 * @return true if setter method, false otherwise. 140 */ 141 public boolean isValidSetterMethod(ExecutableElement setterMethod) { 142 return setterMethod.getReturnType().getKind() == TypeKind.VOID; 143 } 144 145 /** 146 * Returns true if the method is a property method. 147 * @param propertyMethod 148 * @return true if the method is a property method, false otherwise. 149 */ 150 public boolean isPropertyMethod(ExecutableElement propertyMethod) { 151 if (!javafx || 152 !propertyMethod.getParameters().isEmpty() || 153 !propertyMethod.getTypeParameters().isEmpty()) { 154 return false; 155 } 156 String methodName = propertyMethod.getSimpleName().toString(); 157 if (!methodName.endsWith("Property") || 158 fxMethodPatterns.matcher(methodName).matches()) { 159 return false; 160 } 161 162 TypeMirror returnType = propertyMethod.getReturnType(); 163 if (jbObservableType == null) { 164 // JavaFX references missing, make a lazy backward compatible check. 165 return returnType.getKind() != TypeKind.VOID; 166 } else { 167 // Apply strict checks since JavaFX references are available 168 returnType = typeUtils.erasure(propertyMethod.getReturnType()); 169 return typeUtils.isAssignable(returnType, jbObservableType); 170 } 171 } 172 }