diff options
author | John Keiser <shalom@gnu.org> | 1998-07-31 02:12:35 +0000 |
---|---|---|
committer | John Keiser <shalom@gnu.org> | 1998-07-31 02:12:35 +0000 |
commit | 5f3d9badb40dab548e3704bd93ea188814d18ed3 (patch) | |
tree | cb5368dc124e473073d70995bf8056315509079d /gnu | |
parent | c28591f25cf3c2fa7f039b95942e74e52fb0fb96 (diff) | |
download | classpath-5f3d9badb40dab548e3704bd93ea188814d18ed3.tar.gz |
Helpers for java.beans.
Diffstat (limited to 'gnu')
-rw-r--r-- | gnu/java/beans/BeanInfoEmbryo.java | 143 | ||||
-rw-r--r-- | gnu/java/beans/EmptyBeanInfo.java | 52 | ||||
-rw-r--r-- | gnu/java/beans/ExplicitBeanInfo.java | 126 | ||||
-rw-r--r-- | gnu/java/beans/IntrospectionIncubator.java | 357 |
4 files changed, 678 insertions, 0 deletions
diff --git a/gnu/java/beans/BeanInfoEmbryo.java b/gnu/java/beans/BeanInfoEmbryo.java new file mode 100644 index 000000000..b54a13d33 --- /dev/null +++ b/gnu/java/beans/BeanInfoEmbryo.java @@ -0,0 +1,143 @@ +/* + * gnu.java.beans.BeanInfoEmbryo: part of the Java Class Libraries project. + * Copyright (C) 1998 John Keiser + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +package gnu.java.beans; + +import java.beans.*; +import java.util.*; + +/** + ** A BeanInfoEmbryo accumulates information about a Bean + ** while it is in the process of being created, and then + ** when you are done accumulating the information, the + ** getBeanInfo() method may be called to create a BeanInfo + ** object based on the information.<P> + ** + ** This class is not well-synchronized. (It can be, it + ** just isn't yet.) + ** + ** @author John Keiser + ** @version 1.1.0, 30 Jul 1998 + ** @see java.beans.BeanInfo + **/ + +public class BeanInfoEmbryo { + BeanDescriptor beanDescriptor; + Vector additionalBeanInfo = new Vector(); + Hashtable properties = new Hashtable(); + Hashtable events = new Hashtable(); + Hashtable methods = new Hashtable(); + + BeanInfo[] AadditionalBeanInfo; + PropertyDescriptor[] Aproperties; + EventSetDescriptor[] Aevents; + MethodDescriptor[] Amethods; + + public BeanInfoEmbryo() { + } + + public BeanInfo getBeanInfo() { + if(additionalBeanInfo != null) { + AadditionalBeanInfo = new BeanInfo[additionalBeanInfo.size()]; + additionalBeanInfo.copyInto(AadditionalBeanInfo); + } + if(properties != null) { + Aproperties = new PropertyDescriptor[properties.size()]; + int i = 0; + Enumeration enum = properties.elements(); + while(enum.hasMoreElements()) { + Aproperties[i] = (PropertyDescriptor)enum.nextElement(); + i++; + } + } + if(events != null) { + Aevents = new EventSetDescriptor[events.size()]; + int i = 0; + Enumeration enum = events.elements(); + while(enum.hasMoreElements()) { + Aevents[i] = (EventSetDescriptor)enum.nextElement(); + i++; + } + } + if(methods != null) { + Amethods = new MethodDescriptor[methods.size()]; + int i = 0; + Enumeration enum = methods.elements(); + while(enum.hasMoreElements()) { + Amethods[i] = (MethodDescriptor)enum.nextElement(); + i++; + } + } + return new ExplicitBeanInfo(beanDescriptor,AadditionalBeanInfo,Aproperties,-1,Aevents,-1,Amethods,null); + } + + public void setBeanDescriptor(BeanDescriptor b) { + beanDescriptor = b; + } + + public void setAdditionalBeanInfo(BeanInfo[] b) { + additionalBeanInfo = null; + AadditionalBeanInfo = b; + } + public void addAdditionalBeanInfo(BeanInfo b) { + additionalBeanInfo.addElement(b); + } + public void setParentBeanInfo(BeanInfo b) { + BeanInfo[] ba = new BeanInfo[1]; + ba[0] = b; + setAdditionalBeanInfo(ba); + } + + public boolean hasProperty(String name) { + return properties.get(name) != null; + } + public void setProperties(PropertyDescriptor[] p) { + properties = null; + Aproperties = p; + } + public void addProperty(PropertyDescriptor p) { + properties.put(p.getName(),p); + } + public void addIndexedProperty(IndexedPropertyDescriptor p) { + properties.put(p.getName(),p); + } + + public boolean hasEvent(String name) { + return events.get(name) != null; + } + public void addEvent(EventSetDescriptor e) { + events.put(e.getName(),e); + } + public void setEvents(EventSetDescriptor[] e) { + events = null; + Aevents = e; + } + + public boolean hasMethod(String name) { + return methods.get(name) != null; + } + public void addMethod(MethodDescriptor m) { + methods.put(m.getName(),m); + } + public void setMethods(MethodDescriptor[] m) { + methods = null; + Amethods = m; + } +}
\ No newline at end of file diff --git a/gnu/java/beans/EmptyBeanInfo.java b/gnu/java/beans/EmptyBeanInfo.java new file mode 100644 index 000000000..07f938bf4 --- /dev/null +++ b/gnu/java/beans/EmptyBeanInfo.java @@ -0,0 +1,52 @@ +/* + * gnu.java.beans.EmptyBeanInfo: part of the Java Class Libraries project. + * Copyright (C) 1998 John Keiser + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +package gnu.java.beans; + +import java.beans.*; + +/** + ** EmptyBeanInfo is a BeanInfo that discloses no + ** information about the Bean and does not allow + ** Introspection. The Introspector uses instances of this + ** class to create empty BeanInfos, but it could also be + ** used as a base class for BeanInfos that do not allow + ** Introspection and provide only a little bit of + ** information.<P> + ** + ** @author John Keiser + ** @version 1.1.0, 30 Jul 1998 + ** @see gnu.java.beans.ExplicitBeanInfo + ** @see java.beans.BeanInfo + **/ + +public class EmptyBeanInfo extends ExplicitBeanInfo { + /** Create a new EmptyBeanInfo. **/ + public EmptyBeanInfo(Class beanClass) { + super(new BeanDescriptor(beanClass,null), + new BeanInfo[0], + new PropertyDescriptor[0], + -1, + new EventSetDescriptor[0], + -1, + new MethodDescriptor[0], + null); + } +}
\ No newline at end of file diff --git a/gnu/java/beans/ExplicitBeanInfo.java b/gnu/java/beans/ExplicitBeanInfo.java new file mode 100644 index 000000000..3b6c3f035 --- /dev/null +++ b/gnu/java/beans/ExplicitBeanInfo.java @@ -0,0 +1,126 @@ +/* + * gnu.java.beans.ExplicitBeanInfo: part of the Java Class Libraries project. + * Copyright (C) 1998 John Keiser + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +package gnu.java.beans; + +import java.beans.*; + +/** + ** ExplicitBeanInfo lets you specify in the constructor + ** all the various parts of the BeanInfo. + ** + ** @author John Keiser + ** @version 1.1.0, 30 Jul 1998 + ** @see java.beans.BeanInfo + **/ + +public class ExplicitBeanInfo implements BeanInfo { + /** The BeanDescriptor returned by getBeanDescriptor. **/ + protected BeanDescriptor beanDescriptor; + + /** The EventSetDescriptor array returned by + ** getEventSetDescriptors(). + **/ + protected EventSetDescriptor[] eventSetDescriptors = new EventSetDescriptor[0]; + + /** The PropertyDescriptor array returned by + ** getPropertyDescriptors(). + **/ + protected PropertyDescriptor[] propertyDescriptors = new PropertyDescriptor[0]; + + /** The MethodDescriptor array returned by + ** getMethodDescriptors(). + **/ + protected MethodDescriptor[] methodDescriptors; + + /** The default property index. **/ + protected int defaultPropertyIndex; + + /** The default event index. **/ + protected int defaultEventIndex; + + /** The BeanInfo array returned by + ** getAdditionalBeanInfo(). + **/ + protected BeanInfo[] additionalBeanInfo; + + /** The set of icons. **/ + protected java.awt.Image[] icons; + + public ExplicitBeanInfo(BeanDescriptor beanDescriptor, + BeanInfo[] additionalBeanInfo, + PropertyDescriptor[] propertyDescriptors, + int defaultPropertyIndex, + EventSetDescriptor[] eventSetDescriptors, + int defaultEventIndex, + MethodDescriptor[] methodDescriptors, + java.awt.Image[] icons) { + this.beanDescriptor = beanDescriptor; + this.additionalBeanInfo = additionalBeanInfo; + this.propertyDescriptors = propertyDescriptors; + this.defaultPropertyIndex = defaultPropertyIndex; + this.eventSetDescriptors = eventSetDescriptors; + this.defaultEventIndex = defaultEventIndex; + this.methodDescriptors = methodDescriptors; + this.icons = icons; + } + + /** Get Bean descriptor. **/ + public BeanDescriptor getBeanDescriptor() { + return beanDescriptor; + } + + /** Get Bean events. **/ + public EventSetDescriptor[] getEventSetDescriptors() { + return eventSetDescriptors; + } + + /** Get default event set. **/ + public int getDefaultEventIndex() { + return defaultEventIndex; + } + + /** Get Bean properties. **/ + public PropertyDescriptor[] getPropertyDescriptors() { + return propertyDescriptors; + } + + /** Get "default" property. **/ + public int getDefaultPropertyIndex() { + return defaultPropertyIndex; + } + + /** Get Bean methods. **/ + public MethodDescriptor[] getMethodDescriptors() { + return methodDescriptors; + } + + /** Get additional Bean info. **/ + public BeanInfo[] getAdditionalBeanInfo() { + return additionalBeanInfo; + } + + /** Get Bean icons. + ** @param iconType the type of icon + **/ + public java.awt.Image getIcon(int iconType) { + return icons != null ? icons[iconType] : null; + } +}
\ No newline at end of file diff --git a/gnu/java/beans/IntrospectionIncubator.java b/gnu/java/beans/IntrospectionIncubator.java new file mode 100644 index 000000000..aa08f81a8 --- /dev/null +++ b/gnu/java/beans/IntrospectionIncubator.java @@ -0,0 +1,357 @@ +/* + * gnu.java.beans.IntrospectionIncubator: part of the Java Class Libraries project. + * Copyright (C) 1998 John Keiser + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +package gnu.java.beans; + +import java.beans.*; +import java.util.*; +import java.lang.reflect.*; +import gnu.java.lang.*; + +/** + ** IntrospectionIncubator takes in a bunch of Methods, and + ** Introspects only those Methods you give it. + ** + ** @author John Keiser + ** @version 1.1.0, 30 Jul 1998 + ** @see gnu.java.beans.ExplicitBeanInfo + ** @see java.beans.BeanInfo + **/ + +public class IntrospectionIncubator { + Hashtable propertyMethods = new Hashtable(); + Hashtable listenerMethods = new Hashtable(); + Vector otherMethods = new Vector(); + + public IntrospectionIncubator(Class beanClass) { + addMethods(beanClass.getDeclaredMethods()); + } + + public IntrospectionIncubator() { + } + + /* Paving the way for automatic Introspection */ + public void addMethod(Method method) { + if(Modifier.isPublic(method.getModifiers()) && !Modifier.isStatic(method.getModifiers())) { + String name = gnu.java.lang.ClassHelper.getTruncatedName(method.getName()); + Class retType = method.getReturnType(); + Class[] params = method.getParameterTypes(); + boolean isVoid = retType.equals(java.lang.Void.TYPE); + if(name.startsWith("is") + && retType.equals(java.lang.Boolean.TYPE) + && params.length == 0) { + addToPropertyHash(name,method,IS); + } else if(name.startsWith("get") && !isVoid) { + if(params.length == 0) { + addToPropertyHash(name,method,GET); + } else if(params.length == 1 && params[0].equals(java.lang.Integer.TYPE)) { + addToPropertyHash(name,method,GET_I); + } else { + otherMethods.addElement(method); + } + } else if(name.startsWith("set") && isVoid) { + if(params.length == 1) { + addToPropertyHash(name,method,SET); + } else if(params.length == 2 && params[0].equals(java.lang.Integer.TYPE)) { + addToPropertyHash(name,method,SET_I); + } else { + otherMethods.addElement(method); + } + } else if(name.startsWith("add") + && isVoid + && params.length == 1 + && java.util.EventListener.class.isAssignableFrom(params[0]) + && name.substring(3).equals(ClassHelper.getTruncatedClassName(params[0]))) { + addToListenerHash(name,method,ADD); + } else if(name.startsWith("remove") + && isVoid + && params.length == 1 + && java.util.EventListener.class.isAssignableFrom(params[0]) + && name.substring(6).equals(ClassHelper.getTruncatedClassName(params[0]))) { + addToListenerHash(name,method,REMOVE); + } else { + otherMethods.addElement(method); + } + } + } + + public void addMethods(Method[] m) { + for(int i=0;i<m.length;i++) { + addMethod(m[i]); + } + } + + public BeanInfoEmbryo getBeanInfoEmbryo() { + BeanInfoEmbryo b = new BeanInfoEmbryo(); + findXXX(b,IS); + findXXXInt(b,GET_I); + findXXXInt(b,SET_I); + findXXX(b,GET); + findXXX(b,SET); + findAddRemovePairs(b); + findRemainingMethods(b,propertyMethods); + findRemainingMethods(b,listenerMethods); + for(int i=0;i<otherMethods.size();i++) { + b.addMethod(new MethodDescriptor((Method)otherMethods.elementAt(i))); + } + return b; + } + + public BeanInfo getBeanInfo() { + return getBeanInfoEmbryo().getBeanInfo(); + } + + + void findAddRemovePairs(BeanInfoEmbryo b) { + try { + Enumeration listenerEnum = listenerMethods.keys(); + Vector toRemove = new Vector(); + while(listenerEnum.hasMoreElements()) { + DoubleKey k = (DoubleKey)listenerEnum.nextElement(); + Method[] m = (Method[])listenerMethods.get(k); + if(m[ADD] != null && m[REMOVE] != null) { + EventSetDescriptor e = new EventSetDescriptor(Introspector.decapitalize(k.getName()), + k.getType(), k.getType().getMethods(), + m[ADD],m[REMOVE]); + e.setUnicast(ArrayHelper.contains(m[ADD].getExceptionTypes(),java.util.TooManyListenersException.class)); + b.addEvent(e); + toRemove.addElement(k); + } + } + + for(int i=0;i<toRemove.size();i++) { + listenerMethods.remove(toRemove.elementAt(i)); + } + + } catch(IntrospectionException e) { + System.err.println("Uhoh, Introspection failed in findAddRemovePairs()"); + } + } + + void findRemainingMethods(BeanInfoEmbryo b, Hashtable methodHash) { + Enumeration enum = methodHash.elements(); + while(enum.hasMoreElements()) { + Method[] m = (Method[])enum.nextElement(); + for(int i=0;i<m.length;i++) { + if(m[i] != null) { + b.addMethod(new MethodDescriptor(m[i])); + } + } + } + } + + void findXXX(BeanInfoEmbryo b, int funcType) { + try { + Enumeration keys = propertyMethods.keys(); + Vector toRemove = new Vector(); + while(keys.hasMoreElements()) { + DoubleKey k = (DoubleKey)keys.nextElement(); + Method[] m = (Method[])propertyMethods.get(k); + if(m[funcType] != null && !b.hasProperty(Introspector.decapitalize(k.getName()))) { + PropertyDescriptor p = new PropertyDescriptor(Introspector.decapitalize(k.getName()), + m[IS] != null ? m[IS] : m[GET], + m[SET]); + if(m[SET] != null) { + p.setConstrained(ArrayHelper.contains(m[SET].getExceptionTypes(),java.beans.PropertyVetoException.class)); + } + b.addProperty(p); + toRemove.addElement(k); + } + } + + for(int i=0;i<toRemove.size();i++) { + propertyMethods.remove(toRemove.elementAt(i)); + } + + } catch(IntrospectionException e) { + System.err.println("Uhoh, Introspection failed in findXXX()"); + } + } + + void findXXXInt(BeanInfoEmbryo b, int funcType) { + try { + Enumeration keys = propertyMethods.keys(); + Vector toRemove = new Vector(); + while(keys.hasMoreElements()) { + DoubleKey k = (DoubleKey)keys.nextElement(); + Method[] m = (Method[])propertyMethods.get(k); + if(m[funcType] != null && !b.hasProperty(Introspector.decapitalize(k.getName()))) { + boolean constrained; + if(m[SET_I] != null) { + constrained = ArrayHelper.contains(m[SET_I].getExceptionTypes(),java.beans.PropertyVetoException.class); + } else { + constrained = false; + } + + /** Find out if there is an array type get or set **/ + Class arrayType = Array.newInstance(k.getType(),0).getClass(); + DoubleKey findSetArray = new DoubleKey(arrayType,k.getName()); + Method[] m2 = (Method[])propertyMethods.get(findSetArray); + IndexedPropertyDescriptor p; + if(m2 == null) { + p = new IndexedPropertyDescriptor(Introspector.decapitalize(k.getName()), + null,null, + m[GET_I],m[SET_I]); + } else { + if(constrained && m2[SET] != null) { + constrained = ArrayHelper.contains(m2[SET].getExceptionTypes(),java.beans.PropertyVetoException.class); + } + p = new IndexedPropertyDescriptor(Introspector.decapitalize(k.getName()), + m[GET],m[SET], + m[GET_I],m[SET_I]); + toRemove.addElement(findSetArray); + } + p.setConstrained(constrained); + b.addProperty(p); + toRemove.addElement(k); + } + } + + for(int i=0;i<toRemove.size();i++) { + propertyMethods.remove(toRemove.elementAt(i)); + } + } catch(IntrospectionException e) { + System.err.println("Uhoh, reflection screwed up in findXXXInt"); + } + } + + static final int IS=0; + static final int GET_I=1; + static final int SET_I=2; + static final int GET=3; + static final int SET=4; + + static final int ADD=0; + static final int REMOVE=1; + + void addToPropertyHash(String name, Method method, int funcType) { + String newName; + Class type; + + switch(funcType) { + case IS: + type = java.lang.Boolean.TYPE; + newName = name.substring(2); + break; + case GET_I: + type = method.getReturnType(); + newName = name.substring(3); + break; + case SET_I: + type = method.getParameterTypes()[1]; + newName = name.substring(3); + break; + case GET: + type = method.getReturnType(); + newName = name.substring(3); + break; + case SET: + type = method.getParameterTypes()[0]; + newName = name.substring(3); + break; + default: + return; + } + newName = capitalize(newName); + + DoubleKey k = new DoubleKey(type,newName); + Method[] methods = (Method[])propertyMethods.get(k); + if(methods == null) { + methods = new Method[5]; + propertyMethods.put(k,methods); + } + methods[funcType] = method; + } + + + void addToListenerHash(String name, Method method, int funcType) { + String newName; + Class type; + + switch(funcType) { + case ADD: + type = method.getParameterTypes()[0]; + newName = name.substring(3); + break; + case REMOVE: + type = method.getParameterTypes()[0]; + newName = name.substring(6); + break; + default: + return; + } + newName = capitalize(newName); + + DoubleKey k = new DoubleKey(type,newName); + Method[] methods = (Method[])listenerMethods.get(k); + if(methods == null) { + methods = new Method[2]; + listenerMethods.put(k,methods); + } + methods[funcType] = method; + } + + static String capitalize(String name) { + try { + if(Character.isUpperCase(name.charAt(0))) { + return name; + } else { + char[] c = name.toCharArray(); + c[0] = Character.toLowerCase(c[0]); + return new String(c); + } + } catch(StringIndexOutOfBoundsException E) { + return name; + } catch(NullPointerException E) { + return null; + } + } +} + +class DoubleKey { + Class type; + String name; + + DoubleKey(Class type, String name) { + this.type = type; + this.name = name; + } + + Class getType() { + return type; + } + + String getName() { + return name; + } + + public boolean equals(Object o) { + if(o instanceof DoubleKey) { + DoubleKey d = (DoubleKey)o; + return d.type.equals(type) && d.name.equals(name); + } else { + return false; + } + } + + public int hashCode() { + return type.hashCode() ^ name.hashCode(); + } +} |