org.metawidget.inspector.impl.propertystyle.BasePropertyStyle Maven / Gradle / Ivy
// Metawidget (licensed under LGPL)
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser 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 org.metawidget.inspector.impl.propertystyle;
import java.util.Map;
import java.util.Set;
import org.metawidget.inspector.impl.BaseTraitStyle;
import org.metawidget.inspector.impl.BaseTraitStyleConfig;
import org.metawidget.util.ArrayUtils;
import org.metawidget.util.ClassUtils;
import org.metawidget.util.CollectionUtils;
import org.metawidget.util.simple.StringUtils;
/**
* Convenience implementation for PropertyStyles.
*
* @author Richard Kennard
*/
public abstract class BasePropertyStyle
extends BaseTraitStyle
implements PropertyStyle {
//
// Constructor
//
protected BasePropertyStyle( BaseTraitStyleConfig config ) {
super( config );
}
//
// Public methods
//
public Map getProperties( String type ) {
return getTraits( type );
}
/**
* Traverses the given Object heirarchy using properties of the given names.
*
* Note: traversal involves calling Property.read, which invokes getter methods and can
* therefore have side effects. For example, a JSF controller 'ResourceController' may have a
* method 'getLoggedIn' which has to check the HttpSession, maybe even hit some EJBs or access
* the database.
*/
public ValueAndDeclaredType traverse( Object toTraverse, String type, boolean onlyToParent, String... names ) {
// Special support for direct class lookup
if ( toTraverse == null ) {
// If there are names, return null
if ( names != null && names.length > 0 ) {
return new ValueAndDeclaredType( null, null );
}
return new ValueAndDeclaredType( null, type );
}
// Sanity check that the given toTraverse is, in fact, of the given type.
//
// This is harder than it seems. We cannot do a simple 'equals', but to do a
// 'isAssignableFrom' we must instantiate the class. But instantiating the class may
// not be possible because of proxies, virtual classes, what tier we're on, etc. Basically,
// we can't be too strict about it.
//
// Use the toTraverse's ClassLoader, to support ClassLoader isolation (eg. classes from a
// WAR being inspected by an EJB lib) and dynamic classes (eg. Groovy)
Class> sanityCheck = ClassUtils.niceForName( type, toTraverse.getClass().getClassLoader() );
if ( sanityCheck != null && !sanityCheck.isAssignableFrom( toTraverse.getClass() ) ) {
return new ValueAndDeclaredType( null, null );
}
// Traverse through names (if any)
Object traverse = toTraverse;
String traverseDeclaredType = type;
if ( names == null || names.length == 0 ) {
// If no names, no parent
if ( onlyToParent ) {
return new ValueAndDeclaredType( null, null );
}
} else {
Set