package org.codehaus.mojo.pomtools.wrapper.reflection; /* * Copyright 2005-2006 The Apache Software Foundation. * * Licensed 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. */ import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import org.apache.commons.beanutils.PropertyUtils; import org.apache.maven.plugin.logging.Log; import org.codehaus.mojo.pomtools.PomToolsPluginContext; import org.codehaus.mojo.pomtools.config.FieldConfiguration; import org.codehaus.mojo.pomtools.helpers.ModelHelper; import org.codehaus.plexus.util.StringUtils; /** * * @author <a href="mailto:dhawkins@codehaus.org">David Hawkins</a> * @version $Id$ */ public class BeanFields { private final List fields = new ArrayList(); private final Map fieldMap = new HashMap(); private final String fieldFullName; private static final Map LIST_ITEM_TYPE_CACHE = new HashMap(); public BeanFields( String fieldFullName, Object objectToInspect ) { this.fieldFullName = fieldFullName; PomToolsPluginContext context = PomToolsPluginContext.getInstance(); Log log = context.getLog(); PropertyDescriptor[] descriptors = PropertyUtils.getPropertyDescriptors( objectToInspect ); for ( int i = 0; i < descriptors.length; i++ ) { PropertyDescriptor pd = descriptors[i]; FieldConfiguration config = context.getFieldConfiguration( ModelHelper.buildFullName( fieldFullName, pd.getName() ) ); if ( pd.getWriteMethod() != null && ( config == null || !config.isIgnore() ) ) { if ( log.isDebugEnabled() ) { log.debug( "Property: " + ModelHelper.buildFullName( fieldFullName, pd.getName() ) + " => " + pd.getPropertyType().getName() ); } if ( pd.getPropertyType().equals( String.class ) ) { add( new StringField( fieldFullName, pd.getName() ) ); } else if ( pd.getPropertyType().equals( boolean.class ) ) { add( new BooleanField( fieldFullName, pd.getName() ) ); } else if ( pd.getPropertyType().equals( List.class ) ) { addListField( pd, objectToInspect ); } else if ( pd.getPropertyType().equals( Properties.class ) ) { add( new PropertiesBeanField( fieldFullName, pd.getName() ) ); } else { add( new CompositeField( fieldFullName, pd.getName(), pd.getPropertyType() ) ); } } } } /** Convert a plural string to its singular form */ protected String makeSingular( String name ) { if ( name == null ) { return null; } if ( name.endsWith( "ies" ) ) { return name.substring( 0, name.length() - "ies".length() ) + "y"; } else if ( name.endsWith( "es" ) && ( name.endsWith( "ches" ) || name.equalsIgnoreCase( "classes" ) ) ) { return name.substring( 0, name.length() - "es".length() ); } else if ( name.endsWith( "s" ) ) { return name.substring( 0, name.length() - "s".length() ); } return name; } private void addListField( PropertyDescriptor pd, Object objectToInspect ) { PomToolsPluginContext context = PomToolsPluginContext.getInstance(); String fieldName = ModelHelper.buildFullName( this.fieldFullName, pd.getName() ); FieldConfiguration fieldConfig = context.getFieldConfiguration( fieldName ); Class itemImplClass = null; String itemLabel = null; if ( fieldConfig != null ) { String itemClassName = fieldConfig.getItemClassName(); itemLabel = fieldConfig.getItemLabel(); if ( itemClassName != null ) { try { itemImplClass = Class.forName( itemClassName ); } catch ( ClassNotFoundException e ) { throw new ModelReflectionException( "Unable to locate the itemClassName class " + itemClassName ); } } } if ( itemLabel == null ) { itemLabel = makeSingular( pd.getName() ); } if ( itemImplClass == null ) { // Try get get the type by looking for an addXXX method // Currently field name is something like: project.dependencies String cacheKey = objectToInspect.getClass().getName() + ":" + pd.getName(); if ( LIST_ITEM_TYPE_CACHE.containsKey( cacheKey ) ) { itemImplClass = (Class) LIST_ITEM_TYPE_CACHE.get( cacheKey ); } else { String methodName = "add" + StringUtils.capitalizeFirstLetter( makeSingular( pd.getName() ) ); Method[] methods = objectToInspect.getClass().getMethods(); for ( int i = 0; i < methods.length; i++ ) { if ( methods[i].getName().equals( methodName ) ) { Class[] paramTypes = methods[i].getParameterTypes(); if ( paramTypes.length == 1 ) { itemImplClass = paramTypes[0]; LIST_ITEM_TYPE_CACHE.put( cacheKey, itemImplClass ); break; } } } } } if ( itemImplClass != null && itemLabel != null ) { add( new ListField( fieldFullName, pd.getName(), itemImplClass.getName(), itemLabel ) ); } else { context.getLog().warn( "Unable to find field configuration for List: " + fieldName ); } } private BeanField add( BeanField field ) { if ( fieldMap.containsKey( field.getFieldName() ) ) { throw new IllegalArgumentException( "Duplicate field name found for: " + field.getFieldName() ); } fields.add( field ); fieldMap.put( field.getFieldName(), field ); return field; } public Iterator iterator() { return fields.iterator(); } public int size() { return fields.size(); } public BeanField get( int id ) { return (BeanField) fields.get( id ); } public BeanField get( String fieldName ) { return (BeanField) fieldMap.get( fieldName ); } public String getFieldFullName() { return fieldFullName; } public boolean isEmpty() { return fields.isEmpty(); } }