Author: oheger Date: Sun Dec 2 21:18:13 2012 New Revision: 1416264 URL: http://svn.apache.org/viewvc?rev=1416264&view=rev Log: Provided extended bean info for builder parameter classes.
Added: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/BasicBuilderParametersBeanInfo.java (with props) commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/BuilderParametersBeanInfo.java (with props) commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/FileBasedBuilderParametersBeanInfo.java (with props) Added: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/BasicBuilderParametersBeanInfo.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/BasicBuilderParametersBeanInfo.java?rev=1416264&view=auto ============================================================================== --- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/BasicBuilderParametersBeanInfo.java (added) +++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/BasicBuilderParametersBeanInfo.java Sun Dec 2 21:18:13 2012 @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.configuration.builder; + +/** + * An additional {@code BeanInfo} class for {@link BasicBuilderParameters}. + * + * @version $Id$ + * @since 2.0 + */ +public class BasicBuilderParametersBeanInfo extends BuilderParametersBeanInfo +{ + /** + * Creates a new instance of {@code BasicBuilderParametersBeanInfo}. + */ + public BasicBuilderParametersBeanInfo() + { + super(BasicBuilderParameters.class); + } +} Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/BasicBuilderParametersBeanInfo.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/BasicBuilderParametersBeanInfo.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/BasicBuilderParametersBeanInfo.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/BuilderParametersBeanInfo.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/BuilderParametersBeanInfo.java?rev=1416264&view=auto ============================================================================== --- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/BuilderParametersBeanInfo.java (added) +++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/BuilderParametersBeanInfo.java Sun Dec 2 21:18:13 2012 @@ -0,0 +1,219 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.configuration.builder; + +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.beans.SimpleBeanInfo; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Locale; +import java.util.Set; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * <p> + * A base class for providing additional {@code BeanInfo} information for + * parameter classes for {@link BasicConfigurationBuilder}. + * </p> + * <p> + * Because parameter classes typically use a fluent API their properties are not + * detected by standard introspection mechanisms. To make them available to + * <em>Commons BeanUtils</em> (which is used to process bean declarations), the + * properties have to be explicitly listed in custom property descriptors. This + * base class provides functionality to do this. + * </p> + * <p> + * An instance of this class is passed the class of the associated bean at + * construction time. It then obtains all properties of the bean class using + * standard introspection. In a second step, all methods starting with the + * prefix {@code set} are searched. Such methods are typically used to set + * properties in fluent API style. If a method is found whose name is not + * contained in the list of properties, it is added as an additional property. + * </p> + * + * @version $Id$ + * @since 2.0 + */ +public abstract class BuilderParametersBeanInfo extends SimpleBeanInfo +{ + /** Constant for the prefix for set methods. */ + private static final String PREFIX_SET_METHOD = "set"; + + /** The logger. */ + private static final Log LOG = LogFactory + .getLog(BuilderParametersBeanInfo.class); + + /** The property descriptors supported by the associated bean. */ + private final PropertyDescriptor[] propertyDescriptors; + + /** An array with additional BeanInfo objects. */ + private final BeanInfo[] additionalBeanInfo; + + /** + * Creates a new instance of {@code BuilderParametersBeanInfo} and + * initializes it from the specified bean class. + * + * @param beanClass the associated bean class + */ + protected BuilderParametersBeanInfo(Class<?> beanClass) + { + LOG.info("Initializing BeanInfo for " + beanClass); + BeanInfo stdInfo = obtainStandardBeanInfo(beanClass); + if (stdInfo != null) + { + additionalBeanInfo = new BeanInfo[1]; + additionalBeanInfo[0] = stdInfo; + } + else + { + additionalBeanInfo = null; + } + propertyDescriptors = extractPropertyDescriptors(beanClass, stdInfo); + } + + @Override + public BeanInfo[] getAdditionalBeanInfo() + { + return additionalBeanInfo; + } + + @Override + public PropertyDescriptor[] getPropertyDescriptors() + { + return propertyDescriptors; + } + + /** + * Performs standard introspection on the specified bean class. + * + * @param beanClass the bean class in question + * @return the {@code BeanInfo} for this bean class (<b>null</b> if an error + * occurs) + */ + private static BeanInfo obtainStandardBeanInfo(Class<?> beanClass) + { + try + { + return Introspector.getBeanInfo(beanClass, + Introspector.IGNORE_IMMEDIATE_BEANINFO); + } + catch (IntrospectionException e) + { + return null; + } + } + + /** + * Determines all property descriptors for fluent API properties which are + * not detected by standard bean introspection. + * + * @param beanClass the bean class to be processed + * @param stdBeanInfo the {@code BeanInfo} obtained by standard bean + * introspection + * @return an array with property descriptors for the properties discovered + */ + private static PropertyDescriptor[] extractPropertyDescriptors( + Class<?> beanClass, BeanInfo stdBeanInfo) + { + Set<String> propertyNames = fetchPropertyNames(stdBeanInfo); + Collection<PropertyDescriptor> descriptors = + new LinkedList<PropertyDescriptor>(); + + for (Method m : beanClass.getMethods()) + { + if (m.getName().startsWith(PREFIX_SET_METHOD)) + { + String propertyName = propertyName(m); + if (!propertyNames.contains(propertyName)) + { + try + { + descriptors.add(createFluentPropertyDescritor(m, + propertyName)); + } + catch (IntrospectionException e) + { + LOG.warn("Error when creating PropertyDescriptor for " + + m + "! Ignoring this property.", e); + } + } + } + } + + return descriptors.toArray(new PropertyDescriptor[descriptors.size()]); + } + + /** + * Obtains the names of all properties from the given {@code BeanInfo} + * object. + * + * @param info the {@code BeanInfo} (may be <b>null</b>) + * @return a set with all property names + */ + private static Set<String> fetchPropertyNames(BeanInfo info) + { + Set<String> propertyNames = new HashSet<String>(); + if (info != null) + { + PropertyDescriptor[] descs = info.getPropertyDescriptors(); + if (descs != null) + { + for (PropertyDescriptor pd : descs) + { + propertyNames.add(pd.getName()); + } + } + } + + return propertyNames; + } + + /** + * Creates a property descriptor for a fluent API property. + * + * @param m the set method for the fluent API property + * @param propertyName the name of the corresponding property + * @return the descriptor + * @throws IntrospectionException if an error occurs + */ + private static PropertyDescriptor createFluentPropertyDescritor(Method m, + String propertyName) throws IntrospectionException + { + return new PropertyDescriptor(propertyName(m), null, m); + } + + /** + * Derives the name of a property from the given set method. + * + * @param m the method + * @return the corresponding property name + */ + private static String propertyName(Method m) + { + String methodName = m.getName().substring(PREFIX_SET_METHOD.length()); + return (methodName.length() > 1) ? Character.toLowerCase(methodName + .charAt(0)) + methodName.substring(1) : methodName + .toLowerCase(Locale.ENGLISH); + } +} Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/BuilderParametersBeanInfo.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/BuilderParametersBeanInfo.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/BuilderParametersBeanInfo.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/FileBasedBuilderParametersBeanInfo.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/FileBasedBuilderParametersBeanInfo.java?rev=1416264&view=auto ============================================================================== --- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/FileBasedBuilderParametersBeanInfo.java (added) +++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/FileBasedBuilderParametersBeanInfo.java Sun Dec 2 21:18:13 2012 @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.configuration.builder; + +/** + * An additional {@code BeanInfo} class for {@link FileBasedBuilderParameters}. + * + * @version $Id$ + * @since 2.0 + */ +public class FileBasedBuilderParametersBeanInfo extends + BuilderParametersBeanInfo +{ + /** + * Creates a new instance of {@code FileBasedBuilderParametersBeanInfo}. + */ + public FileBasedBuilderParametersBeanInfo() + { + super(FileBasedBuilderParameters.class); + } +} Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/FileBasedBuilderParametersBeanInfo.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/FileBasedBuilderParametersBeanInfo.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/FileBasedBuilderParametersBeanInfo.java ------------------------------------------------------------------------------ svn:mime-type = text/plain