0N/A/*
2362N/A * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage java.beans;
0N/A
0N/Aimport com.sun.beans.TypeResolver;
0N/A
0N/Aimport java.lang.ref.Reference;
0N/Aimport java.lang.ref.WeakReference;
0N/Aimport java.lang.ref.SoftReference;
0N/A
0N/Aimport java.lang.reflect.Method;
243N/A
243N/Aimport java.util.Enumeration;
243N/Aimport java.util.Hashtable;
2172N/Aimport java.util.Map.Entry;
0N/A
0N/A/**
0N/A * The FeatureDescriptor class is the common baseclass for PropertyDescriptor,
0N/A * EventSetDescriptor, and MethodDescriptor, etc.
0N/A * <p>
0N/A * It supports some common information that can be set and retrieved for
0N/A * any of the introspection descriptors.
0N/A * <p>
0N/A * In addition it provides an extension mechanism so that arbitrary
0N/A * attribute/value pairs can be associated with a design feature.
0N/A */
0N/A
0N/Apublic class FeatureDescriptor {
243N/A private static final String TRANSIENT = "transient";
0N/A
0N/A private Reference<Class> classRef;
0N/A
0N/A /**
0N/A * Constructs a <code>FeatureDescriptor</code>.
0N/A */
0N/A public FeatureDescriptor() {
0N/A }
0N/A
0N/A /**
0N/A * Gets the programmatic name of this feature.
0N/A *
0N/A * @return The programmatic name of the property/method/event
0N/A */
0N/A public String getName() {
0N/A return name;
0N/A }
0N/A
0N/A /**
0N/A * Sets the programmatic name of this feature.
0N/A *
0N/A * @param name The programmatic name of the property/method/event
0N/A */
0N/A public void setName(String name) {
0N/A this.name = name;
0N/A }
0N/A
0N/A /**
0N/A * Gets the localized display name of this feature.
0N/A *
0N/A * @return The localized display name for the property/method/event.
0N/A * This defaults to the same as its programmatic name from getName.
0N/A */
0N/A public String getDisplayName() {
0N/A if (displayName == null) {
0N/A return getName();
0N/A }
0N/A return displayName;
0N/A }
0N/A
0N/A /**
0N/A * Sets the localized display name of this feature.
0N/A *
0N/A * @param displayName The localized display name for the
0N/A * property/method/event.
0N/A */
0N/A public void setDisplayName(String displayName) {
0N/A this.displayName = displayName;
0N/A }
0N/A
0N/A /**
0N/A * The "expert" flag is used to distinguish between those features that are
0N/A * intended for expert users from those that are intended for normal users.
0N/A *
0N/A * @return True if this feature is intended for use by experts only.
0N/A */
0N/A public boolean isExpert() {
0N/A return expert;
0N/A }
0N/A
0N/A /**
0N/A * The "expert" flag is used to distinguish between features that are
0N/A * intended for expert users from those that are intended for normal users.
0N/A *
0N/A * @param expert True if this feature is intended for use by experts only.
0N/A */
0N/A public void setExpert(boolean expert) {
0N/A this.expert = expert;
0N/A }
0N/A
0N/A /**
0N/A * The "hidden" flag is used to identify features that are intended only
0N/A * for tool use, and which should not be exposed to humans.
0N/A *
0N/A * @return True if this feature should be hidden from human users.
0N/A */
0N/A public boolean isHidden() {
0N/A return hidden;
0N/A }
0N/A
0N/A /**
0N/A * The "hidden" flag is used to identify features that are intended only
0N/A * for tool use, and which should not be exposed to humans.
0N/A *
0N/A * @param hidden True if this feature should be hidden from human users.
0N/A */
0N/A public void setHidden(boolean hidden) {
0N/A this.hidden = hidden;
0N/A }
0N/A
0N/A /**
0N/A * The "preferred" flag is used to identify features that are particularly
0N/A * important for presenting to humans.
0N/A *
0N/A * @return True if this feature should be preferentially shown to human users.
0N/A */
0N/A public boolean isPreferred() {
0N/A return preferred;
0N/A }
0N/A
0N/A /**
0N/A * The "preferred" flag is used to identify features that are particularly
0N/A * important for presenting to humans.
0N/A *
0N/A * @param preferred True if this feature should be preferentially shown
0N/A * to human users.
0N/A */
0N/A public void setPreferred(boolean preferred) {
0N/A this.preferred = preferred;
0N/A }
0N/A
0N/A /**
0N/A * Gets the short description of this feature.
0N/A *
0N/A * @return A localized short description associated with this
0N/A * property/method/event. This defaults to be the display name.
0N/A */
0N/A public String getShortDescription() {
0N/A if (shortDescription == null) {
0N/A return getDisplayName();
0N/A }
0N/A return shortDescription;
0N/A }
0N/A
0N/A /**
0N/A * You can associate a short descriptive string with a feature. Normally
0N/A * these descriptive strings should be less than about 40 characters.
0N/A * @param text A (localized) short description to be associated with
0N/A * this property/method/event.
0N/A */
0N/A public void setShortDescription(String text) {
0N/A shortDescription = text;
0N/A }
0N/A
0N/A /**
0N/A * Associate a named attribute with this feature.
0N/A *
0N/A * @param attributeName The locale-independent name of the attribute
0N/A * @param value The value.
0N/A */
0N/A public void setValue(String attributeName, Object value) {
243N/A getTable().put(attributeName, value);
0N/A }
0N/A
0N/A /**
0N/A * Retrieve a named attribute with this feature.
0N/A *
0N/A * @param attributeName The locale-independent name of the attribute
0N/A * @return The value of the attribute. May be null if
0N/A * the attribute is unknown.
0N/A */
0N/A public Object getValue(String attributeName) {
243N/A return (this.table != null)
243N/A ? this.table.get(attributeName)
243N/A : null;
0N/A }
0N/A
0N/A /**
0N/A * Gets an enumeration of the locale-independent names of this
0N/A * feature.
0N/A *
0N/A * @return An enumeration of the locale-independent names of any
0N/A * attributes that have been registered with setValue.
0N/A */
243N/A public Enumeration<String> attributeNames() {
243N/A return getTable().keys();
0N/A }
0N/A
0N/A /**
0N/A * Package-private constructor,
0N/A * Merge information from two FeatureDescriptors.
0N/A * The merged hidden and expert flags are formed by or-ing the values.
0N/A * In the event of other conflicts, the second argument (y) is
0N/A * given priority over the first argument (x).
0N/A *
0N/A * @param x The first (lower priority) MethodDescriptor
0N/A * @param y The second (higher priority) MethodDescriptor
0N/A */
0N/A FeatureDescriptor(FeatureDescriptor x, FeatureDescriptor y) {
0N/A expert = x.expert | y.expert;
0N/A hidden = x.hidden | y.hidden;
0N/A preferred = x.preferred | y.preferred;
0N/A name = y.name;
0N/A shortDescription = x.shortDescription;
0N/A if (y.shortDescription != null) {
0N/A shortDescription = y.shortDescription;
0N/A }
0N/A displayName = x.displayName;
0N/A if (y.displayName != null) {
0N/A displayName = y.displayName;
0N/A }
0N/A classRef = x.classRef;
0N/A if (y.classRef != null) {
0N/A classRef = y.classRef;
0N/A }
0N/A addTable(x.table);
0N/A addTable(y.table);
0N/A }
0N/A
0N/A /*
0N/A * Package-private dup constructor
0N/A * This must isolate the new object from any changes to the old object.
0N/A */
0N/A FeatureDescriptor(FeatureDescriptor old) {
0N/A expert = old.expert;
0N/A hidden = old.hidden;
0N/A preferred = old.preferred;
0N/A name = old.name;
0N/A shortDescription = old.shortDescription;
0N/A displayName = old.displayName;
0N/A classRef = old.classRef;
0N/A
0N/A addTable(old.table);
0N/A }
0N/A
243N/A /**
243N/A * Copies all values from the specified attribute table.
243N/A * If some attribute is exist its value should be overridden.
243N/A *
243N/A * @param table the attribute table with new values
243N/A */
243N/A private void addTable(Hashtable<String, Object> table) {
243N/A if ((table != null) && !table.isEmpty()) {
243N/A getTable().putAll(table);
243N/A }
243N/A }
243N/A
243N/A /**
243N/A * Returns the initialized attribute table.
243N/A *
243N/A * @return the initialized attribute table
243N/A */
243N/A private Hashtable<String, Object> getTable() {
243N/A if (this.table == null) {
243N/A this.table = new Hashtable<String, Object>();
0N/A }
243N/A return this.table;
243N/A }
243N/A
243N/A /**
243N/A * Sets the "transient" attribute according to the annotation.
243N/A * If the "transient" attribute is already set
243N/A * it should not be changed.
243N/A *
243N/A * @param annotation the annotation of the element of the feature
243N/A */
243N/A void setTransient(Transient annotation) {
243N/A if ((annotation != null) && (null == getValue(TRANSIENT))) {
243N/A setValue(TRANSIENT, annotation.value());
0N/A }
0N/A }
0N/A
243N/A /**
243N/A * Indicates whether the feature is transient.
243N/A *
243N/A * @return {@code true} if the feature is transient,
243N/A * {@code false} otherwise
243N/A */
243N/A boolean isTransient() {
243N/A Object value = getValue(TRANSIENT);
243N/A return (value instanceof Boolean)
243N/A ? (Boolean) value
243N/A : false;
243N/A }
243N/A
0N/A // Package private methods for recreating the weak/soft referent
0N/A
0N/A void setClass0(Class cls) {
0N/A this.classRef = getWeakReference(cls);
0N/A }
0N/A
0N/A Class getClass0() {
0N/A return (this.classRef != null)
0N/A ? this.classRef.get()
0N/A : null;
0N/A }
0N/A
0N/A /**
0N/A * Creates a new soft reference that refers to the given object.
0N/A *
0N/A * @return a new soft reference or <code>null</code> if object is <code>null</code>
0N/A *
0N/A * @see SoftReference
0N/A */
0N/A static <T> Reference<T> getSoftReference(T object) {
0N/A return (object != null)
0N/A ? new SoftReference<T>(object)
0N/A : null;
0N/A }
0N/A
0N/A /**
0N/A * Creates a new weak reference that refers to the given object.
0N/A *
0N/A * @return a new weak reference or <code>null</code> if object is <code>null</code>
0N/A *
0N/A * @see WeakReference
0N/A */
0N/A static <T> Reference<T> getWeakReference(T object) {
0N/A return (object != null)
0N/A ? new WeakReference<T>(object)
0N/A : null;
0N/A }
0N/A
0N/A /**
0N/A * Resolves the return type of the method.
0N/A *
0N/A * @param base the class that contains the method in the hierarchy
0N/A * @param method the object that represents the method
0N/A * @return a class identifying the return type of the method
0N/A *
0N/A * @see Method#getGenericReturnType
0N/A * @see Method#getReturnType
0N/A */
0N/A static Class getReturnType(Class base, Method method) {
0N/A if (base == null) {
0N/A base = method.getDeclaringClass();
0N/A }
0N/A return TypeResolver.erase(TypeResolver.resolveInClass(base, method.getGenericReturnType()));
0N/A }
0N/A
0N/A /**
0N/A * Resolves the parameter types of the method.
0N/A *
0N/A * @param base the class that contains the method in the hierarchy
0N/A * @param method the object that represents the method
0N/A * @return an array of classes identifying the parameter types of the method
0N/A *
0N/A * @see Method#getGenericParameterTypes
0N/A * @see Method#getParameterTypes
0N/A */
0N/A static Class[] getParameterTypes(Class base, Method method) {
0N/A if (base == null) {
0N/A base = method.getDeclaringClass();
0N/A }
0N/A return TypeResolver.erase(TypeResolver.resolveInClass(base, method.getGenericParameterTypes()));
0N/A }
0N/A
0N/A private boolean expert;
0N/A private boolean hidden;
0N/A private boolean preferred;
0N/A private String shortDescription;
0N/A private String name;
0N/A private String displayName;
243N/A private Hashtable<String, Object> table;
2172N/A
2172N/A /**
2172N/A * Returns a string representation of the object.
2172N/A *
2172N/A * @return a string representation of the object
2172N/A *
2172N/A * @since 1.7
2172N/A */
2172N/A public String toString() {
2172N/A StringBuilder sb = new StringBuilder(getClass().getName());
2172N/A sb.append("[name=").append(this.name);
2172N/A appendTo(sb, "displayName", this.displayName);
2172N/A appendTo(sb, "shortDescription", this.shortDescription);
2172N/A appendTo(sb, "preferred", this.preferred);
2172N/A appendTo(sb, "hidden", this.hidden);
2172N/A appendTo(sb, "expert", this.expert);
2172N/A if ((this.table != null) && !this.table.isEmpty()) {
2172N/A sb.append("; values={");
2172N/A for (Entry<String, Object> entry : this.table.entrySet()) {
2172N/A sb.append(entry.getKey()).append("=").append(entry.getValue()).append("; ");
2172N/A }
2172N/A sb.setLength(sb.length() - 2);
2172N/A sb.append("}");
2172N/A }
2172N/A appendTo(sb);
2172N/A return sb.append("]").toString();
2172N/A }
2172N/A
2172N/A void appendTo(StringBuilder sb) {
2172N/A }
2172N/A
2172N/A static void appendTo(StringBuilder sb, String name, Reference reference) {
2172N/A if (reference != null) {
2172N/A appendTo(sb, name, reference.get());
2172N/A }
2172N/A }
2172N/A
2172N/A static void appendTo(StringBuilder sb, String name, Object value) {
2172N/A if (value != null) {
2172N/A sb.append("; ").append(name).append("=").append(value);
2172N/A }
2172N/A }
2172N/A
2172N/A static void appendTo(StringBuilder sb, String name, boolean value) {
2172N/A if (value) {
2172N/A sb.append("; ").append(name);
2172N/A }
2172N/A }
0N/A}