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 import jdk.javadoc.internal.doclets.formats.html.HtmlOptions; 35 36 /** 37 * This class provides basic JavaFX property related utility methods. 38 * Refer to the JavaFX conventions in the VisibleMemberTable comments. 39 */ 40 public class PropertyUtils { 41 42 final TypeMirror jbObservableType; 43 44 final Pattern fxMethodPatterns; 45 46 final boolean javafx; 47 48 final Types typeUtils; 49 50 PropertyUtils(BaseConfiguration configuration) { 51 BaseOptions options = configuration.getOptions(); 52 javafx = options.javafx; 53 54 typeUtils = configuration.docEnv.getTypeUtils(); 55 56 // Disable strict check for JDK's without FX. 57 TypeMirror jboType = options.disableJavaFxStrictChecks 58 ? null 59 : configuration.utils.getSymbol("javafx.beans.Observable"); 60 61 jbObservableType = jboType != null 62 ? configuration.docEnv.getTypeUtils().erasure(jboType) 63 : null; 64 65 fxMethodPatterns = javafx 66 ? Pattern.compile("[sg]et\\p{Upper}.*||is\\p{Upper}.*") 67 : null; 68 } 69 70 /** 71 * Returns a base name for a property method. Supposing we 72 * have {@code BooleanProperty acmeProperty()}, then "acme" 73 * will be returned. 74 * @param propertyMethod 75 * @return the base name of a property method. 76 */ 77 public String getBaseName(ExecutableElement propertyMethod) { 78 String name = propertyMethod.getSimpleName().toString(); 79 String baseName = name.substring(0, name.indexOf("Property")); 80 return baseName; 81 } 82 83 /** 84 * Returns a property getter's name. Supposing we have a property 85 * method {@code DoubleProperty acmeProperty()}, then "getAcme" 86 * will be returned. 87 * @param propertyMethod 88 * @return the property getter's name. 89 */ 90 public String getGetName(ExecutableElement propertyMethod) { 91 String baseName = getBaseName(propertyMethod); 92 String fnUppercased = "" + 93 Character.toUpperCase(baseName.charAt(0)) + baseName.substring(1); 94 return "get" + fnUppercased; 95 } 96 97 /** 98 * Returns an "is" method's name for a property method. Supposing 99 * we have a property method {@code BooleanProperty acmeProperty()}, 100 * then "isAcme" will be returned. 101 * @param propertyMethod 102 * @return the property is getter's name. 103 */ 104 public String getIsName(ExecutableElement propertyMethod) { 105 String baseName = getBaseName(propertyMethod); 106 String fnUppercased = "" + 107 Character.toUpperCase(baseName.charAt(0)) + baseName.substring(1); 108 return "is" + fnUppercased; 109 } 110 111 /** 112 * Returns true if a property method could have an "is" method, meaning 113 * {@code isAcme} could exist for a property method. 114 * @param propertyMethod 115 * @return true if the property could have an "is" method, false otherwise. 116 */ 117 public boolean hasIsMethod(ExecutableElement propertyMethod) { 118 String propertyTypeName = propertyMethod.getReturnType().toString(); 119 return "boolean".equals(propertyTypeName) || 120 propertyTypeName.endsWith("BooleanProperty"); 121 } 122 123 /** 124 * Returns a property setter's name. Supposing we have a property 125 * method {@code DoubleProperty acmeProperty()}, then "setAcme" 126 * will be returned. 127 * @param propertyMethod 128 * @return the property setter's method name. 129 */ 130 public String getSetName(ExecutableElement propertyMethod) { 131 String baseName = getBaseName(propertyMethod); 132 String fnUppercased = "" + 133 Character.toUpperCase(baseName.charAt(0)) + baseName.substring(1); 134 return "set" + fnUppercased; 135 } 136 137 /** 138 * Returns true if the given setter method is a valid property setter 139 * method. 140 * @param setterMethod 141 * @return true if setter method, false otherwise. 142 */ 143 public boolean isValidSetterMethod(ExecutableElement setterMethod) { 144 return setterMethod.getReturnType().getKind() == TypeKind.VOID; 145 } 146 147 /** 148 * Returns true if the method is a property method. 149 * @param propertyMethod 150 * @return true if the method is a property method, false otherwise. 151 */ 152 public boolean isPropertyMethod(ExecutableElement propertyMethod) { 153 if (!javafx || 154 !propertyMethod.getParameters().isEmpty() || 155 !propertyMethod.getTypeParameters().isEmpty()) { 156 return false; 157 } 158 String methodName = propertyMethod.getSimpleName().toString(); 159 if (!methodName.endsWith("Property") || 160 fxMethodPatterns.matcher(methodName).matches()) { 161 return false; 162 } 163 164 TypeMirror returnType = propertyMethod.getReturnType(); 165 if (jbObservableType == null) { 166 // JavaFX references missing, make a lazy backward compatible check. 167 return returnType.getKind() != TypeKind.VOID; 168 } else { 169 // Apply strict checks since JavaFX references are available 170 returnType = typeUtils.erasure(propertyMethod.getReturnType()); 171 return typeUtils.isAssignable(returnType, jbObservableType); 172 } 173 } 174 }