/* * Copyright © 2003-2009 Israfil Consulting Services Corporation * Copyright © 2003-2009 Christian Edward Gruber * All Rights Reserved * * This software is licensed under the Berkeley Standard Distribution license, * (BSD license), as defined below: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of Israfil Consulting Services nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * * $Id: DynamicallyAccessibleObject.java 76 2006-08-03 15:37:05Z cgruber $ */ package net.israfil.foundation.dynamic; import java.util.logging.Level; import java.util.logging.Logger; import net.israfil.foundation.core.Strings; /** * An implementation of the DynamicallyAccessible interface with the * appropriate infrastructure for retrieving field data, via accessors if * such are implemented, or directly from the field where not. * * @author Christian Edward Gruber * @author Latest: $Author: cgruber $ * @version $Revision: 76 $ */ public abstract class DynamicallyAccessibleObject extends DynamicObject implements DynamicallyAccessible { private static Logger logger = Logger.getLogger(DynamicallyAccessibleObject.class.getName()); @Override public Object get(String attributeName) { return get(this,attributeName); } public static Object get(Object receiver, String attributeName) { try { return _get(receiver, attributeName); } catch (NoSuchFieldException e) { logger.log(Level.FINE,"Object attempted to dynamically access a non-existant or unreadable field.",e); throw new RuntimeException(e); } catch (IllegalAccessException e) { logger.log(Level.FINE,"Object attempted to dynamically access a inaccessible field.",e); throw new RuntimeException(e); } } /** @deprecated This method is deprecated in favour of the static _get(receiver, attributeName) */ Object _get(String attributeName) throws NoSuchFieldException, IllegalAccessException { return _get(this,attributeName); } /** * Internal _get method that throws all the exceptions, to be wrapped by public methods * so that the various exceptions can be given meaning in different contexts (such * as fetching data, vs. testing for the existance of something. * * @param attributeName * @return * @throws NoSuchFieldException * @throws IllegalAccessException */ static Object _get(Object receiver, String attributeName) throws NoSuchFieldException, IllegalAccessException { if (hasAccessor(receiver,attributeName)) return DynamicUtil.performOn(receiver,_getAccessorSelector(receiver,attributeName), new Object[]{}); return receiver.getClass().getField(attributeName).get(receiver); } /** * Determines whether an attribute of the given name exists on this object's * definition, or if not, if there is a javabeans-style accessor named * appropriately for that attribute. Put another way, determines whether * a get() call would work against this attribute name. * * The existing implementation is inefficient, but simple to maintain. */ @Override public boolean hasAttribute(String attributeName) { return hasAttribute(this,attributeName); } public static boolean hasAttribute(Object receiver, String attributeName) { try { _get(receiver,attributeName); return true; } catch (NoSuchFieldException e) { logger.log(Level.FINEST,"Object attempted to dynamically access a non-existant or unreadable field.",e); return false; } catch (IllegalAccessException e) { logger.log(Level.FINEST,"Object attempted to dynamically access a inaccessible field.",e); return false; } } protected static final String[] accessPrefixes = new String[] { "get","is" }; /** @deprecated This method is deprecated in favour of the static _getAccessorSelector(receiver,attribute) */ protected String getAccessorSelector(String attributeName) { return _getAccessorSelector(this,attributeName); } protected static String _getAccessorSelector(Object receiver, String attributeName) { if (attributeName == null || attributeName.equals("")) return null; String camelAttr = camel(attributeName); for (String prefix : accessPrefixes) { String selector = prefix+camelAttr; if (DynamicUtil.respondsTo(receiver,selector)) return selector; } // No accessor, try a NeXTSTEP-style accessor, named the same as the property. if (DynamicUtil.respondsTo(receiver,attributeName)) return attributeName; return null; } @Override public boolean hasAccessor(String attributeName) { return hasAccessor(this,attributeName); } public static boolean hasAccessor(Object receiver, String attributeName) { return _getAccessorSelector(receiver,attributeName) != null; } /** @deprecated This method has been moved to net.israfil.foundation.core.Strings.camel(String) */ public static String camel(String string) { return Strings.camel(string); } }