Path: blob/master/src/java.desktop/share/classes/java/beans/FeatureDescriptor.java
41152 views
/*1* Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.beans;2627import com.sun.beans.TypeResolver;2829import java.lang.ref.Reference;30import java.lang.ref.WeakReference;31import java.lang.ref.SoftReference;3233import java.lang.reflect.Method;3435import java.util.Enumeration;36import java.util.Hashtable;37import java.util.Map.Entry;3839/**40* The FeatureDescriptor class is the common baseclass for PropertyDescriptor,41* EventSetDescriptor, and MethodDescriptor, etc.42* <p>43* It supports some common information that can be set and retrieved for44* any of the introspection descriptors.45* <p>46* In addition it provides an extension mechanism so that arbitrary47* attribute/value pairs can be associated with a design feature.48*49* @since 1.150*/5152public class FeatureDescriptor {53private static final String TRANSIENT = "transient";5455private Reference<? extends Class<?>> classRef;5657/**58* Constructs a {@code FeatureDescriptor}.59*/60public FeatureDescriptor() {61}6263/**64* Gets the programmatic name of this feature.65*66* @return The programmatic name of the property/method/event67*/68public String getName() {69return name;70}7172/**73* Sets the programmatic name of this feature.74*75* @param name The programmatic name of the property/method/event76*/77public void setName(String name) {78this.name = name;79}8081/**82* Gets the localized display name of this feature.83*84* @return The localized display name for the property/method/event.85* This defaults to the same as its programmatic name from getName.86*/87public String getDisplayName() {88if (displayName == null) {89return getName();90}91return displayName;92}9394/**95* Sets the localized display name of this feature.96*97* @param displayName The localized display name for the98* property/method/event.99*/100public void setDisplayName(String displayName) {101this.displayName = displayName;102}103104/**105* The "expert" flag is used to distinguish between those features that are106* intended for expert users from those that are intended for normal users.107*108* @return True if this feature is intended for use by experts only.109*/110public boolean isExpert() {111return expert;112}113114/**115* The "expert" flag is used to distinguish between features that are116* intended for expert users from those that are intended for normal users.117*118* @param expert True if this feature is intended for use by experts only.119*/120public void setExpert(boolean expert) {121this.expert = expert;122}123124/**125* The "hidden" flag is used to identify features that are intended only126* for tool use, and which should not be exposed to humans.127*128* @return True if this feature should be hidden from human users.129*/130public boolean isHidden() {131return hidden;132}133134/**135* The "hidden" flag is used to identify features that are intended only136* for tool use, and which should not be exposed to humans.137*138* @param hidden True if this feature should be hidden from human users.139*/140public void setHidden(boolean hidden) {141this.hidden = hidden;142}143144/**145* The "preferred" flag is used to identify features that are particularly146* important for presenting to humans.147*148* @return True if this feature should be preferentially shown to human users.149* @since 1.2150*/151public boolean isPreferred() {152return preferred;153}154155/**156* The "preferred" flag is used to identify features that are particularly157* important for presenting to humans.158*159* @param preferred True if this feature should be preferentially shown160* to human users.161* @since 1.2162*/163public void setPreferred(boolean preferred) {164this.preferred = preferred;165}166167/**168* Gets the short description of this feature.169*170* @return A localized short description associated with this171* property/method/event. This defaults to be the display name.172*/173public String getShortDescription() {174if (shortDescription == null) {175return getDisplayName();176}177return shortDescription;178}179180/**181* You can associate a short descriptive string with a feature. Normally182* these descriptive strings should be less than about 40 characters.183* @param text A (localized) short description to be associated with184* this property/method/event.185*/186public void setShortDescription(String text) {187shortDescription = text;188}189190/**191* Associate a named attribute with this feature.192*193* @param attributeName The locale-independent name of the attribute194* @param value The value.195*/196public void setValue(String attributeName, Object value) {197getTable().put(attributeName, value);198}199200/**201* Retrieve a named attribute with this feature.202*203* @param attributeName The locale-independent name of the attribute204* @return The value of the attribute. May be null if205* the attribute is unknown.206*/207public Object getValue(String attributeName) {208return (this.table != null)209? this.table.get(attributeName)210: null;211}212213/**214* Gets an enumeration of the locale-independent names of this215* feature.216*217* @return An enumeration of the locale-independent names of any218* attributes that have been registered with setValue.219*/220public Enumeration<String> attributeNames() {221return getTable().keys();222}223224/**225* Package-private constructor,226* Merge information from two FeatureDescriptors.227* The merged hidden and expert flags are formed by or-ing the values.228* In the event of other conflicts, the second argument (y) is229* given priority over the first argument (x).230*231* @param x The first (lower priority) MethodDescriptor232* @param y The second (higher priority) MethodDescriptor233*/234FeatureDescriptor(FeatureDescriptor x, FeatureDescriptor y) {235expert = x.expert | y.expert;236hidden = x.hidden | y.hidden;237preferred = x.preferred | y.preferred;238name = y.name;239shortDescription = x.shortDescription;240if (y.shortDescription != null) {241shortDescription = y.shortDescription;242}243displayName = x.displayName;244if (y.displayName != null) {245displayName = y.displayName;246}247classRef = x.classRef;248if (y.classRef != null) {249classRef = y.classRef;250}251addTable(x.table);252addTable(y.table);253}254255/*256* Package-private dup constructor257* This must isolate the new object from any changes to the old object.258*/259FeatureDescriptor(FeatureDescriptor old) {260expert = old.expert;261hidden = old.hidden;262preferred = old.preferred;263name = old.name;264shortDescription = old.shortDescription;265displayName = old.displayName;266classRef = old.classRef;267268addTable(old.table);269}270271/**272* Copies all values from the specified attribute table.273* If some attribute is exist its value should be overridden.274*275* @param table the attribute table with new values276*/277private void addTable(Hashtable<String, Object> table) {278if ((table != null) && !table.isEmpty()) {279getTable().putAll(table);280}281}282283/**284* Returns the initialized attribute table.285*286* @return the initialized attribute table287*/288private Hashtable<String, Object> getTable() {289if (this.table == null) {290this.table = new Hashtable<>();291}292return this.table;293}294295/**296* Sets the "transient" attribute according to the annotation.297* If the "transient" attribute is already set298* it should not be changed.299*300* @param annotation the annotation of the element of the feature301*/302void setTransient(Transient annotation) {303if ((annotation != null) && (null == getValue(TRANSIENT))) {304setValue(TRANSIENT, annotation.value());305}306}307308/**309* Indicates whether the feature is transient.310*311* @return {@code true} if the feature is transient,312* {@code false} otherwise313*/314boolean isTransient() {315Object value = getValue(TRANSIENT);316return (value instanceof Boolean)317? (Boolean) value318: false;319}320321// Package private methods for recreating the weak/soft referent322323void setClass0(Class<?> cls) {324this.classRef = getWeakReference(cls);325}326327Class<?> getClass0() {328return (this.classRef != null)329? this.classRef.get()330: null;331}332333/**334* Creates a new soft reference that refers to the given object.335*336* @return a new soft reference or {@code null} if object is {@code null}337*338* @see SoftReference339*/340static <T> Reference<T> getSoftReference(T object) {341return (object != null)342? new SoftReference<>(object)343: null;344}345346/**347* Creates a new weak reference that refers to the given object.348*349* @return a new weak reference or {@code null} if object is {@code null}350*351* @see WeakReference352*/353static <T> Reference<T> getWeakReference(T object) {354return (object != null)355? new WeakReference<>(object)356: null;357}358359/**360* Resolves the return type of the method.361*362* @param base the class that contains the method in the hierarchy363* @param method the object that represents the method364* @return a class identifying the return type of the method365*366* @see Method#getGenericReturnType367* @see Method#getReturnType368*/369static Class<?> getReturnType(Class<?> base, Method method) {370if (base == null) {371base = method.getDeclaringClass();372}373return TypeResolver.erase(TypeResolver.resolveInClass(base, method.getGenericReturnType()));374}375376/**377* Resolves the parameter types of the method.378*379* @param base the class that contains the method in the hierarchy380* @param method the object that represents the method381* @return an array of classes identifying the parameter types of the method382*383* @see Method#getGenericParameterTypes384* @see Method#getParameterTypes385*/386static Class<?>[] getParameterTypes(Class<?> base, Method method) {387if (base == null) {388base = method.getDeclaringClass();389}390return TypeResolver.erase(TypeResolver.resolveInClass(base, method.getGenericParameterTypes()));391}392393private boolean expert;394private boolean hidden;395private boolean preferred;396private String shortDescription;397private String name;398private String displayName;399private Hashtable<String, Object> table;400401/**402* Returns a string representation of the object.403*404* @return a string representation of the object405*406* @since 1.7407*/408public String toString() {409StringBuilder sb = new StringBuilder(getClass().getName());410sb.append("[name=").append(this.name);411appendTo(sb, "displayName", this.displayName);412appendTo(sb, "shortDescription", this.shortDescription);413appendTo(sb, "preferred", this.preferred);414appendTo(sb, "hidden", this.hidden);415appendTo(sb, "expert", this.expert);416if ((this.table != null) && !this.table.isEmpty()) {417sb.append("; values={");418for (Entry<String, Object> entry : this.table.entrySet()) {419sb.append(entry.getKey()).append("=").append(entry.getValue()).append("; ");420}421sb.setLength(sb.length() - 2);422sb.append("}");423}424appendTo(sb);425return sb.append("]").toString();426}427428void appendTo(StringBuilder sb) {429}430431static void appendTo(StringBuilder sb, String name, Reference<?> reference) {432if (reference != null) {433appendTo(sb, name, reference.get());434}435}436437static void appendTo(StringBuilder sb, String name, Object value) {438if (value != null) {439sb.append("; ").append(name).append("=").append(value);440}441}442443static void appendTo(StringBuilder sb, String name, boolean value) {444if (value) {445sb.append("; ").append(name);446}447}448}449450451