net.israfil.foundation.core.DynamicallyMutableObject Maven / Gradle / Ivy
/*
* Copyright (c) 2003, 2004, 2005 Israfil Consulting Services Corporation
* Copyright (c) 2003, 2004, 2005 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: DynamicallyMutableObject.java 127 2006-11-09 18:04:43Z cgruber $
*/
package net.israfil.foundation.core;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* An abstract class which implements the DynamicallyMutableObject
* infrastructure. It sets a field's value, by mutator method if such
* exists, or directly if none such exists.
*
* @author Christian Edward Gruber
*
*/
@Copyright(years={"2003","2004","2005","2006"},owner="Israfil Consulting Services Corporation",license="BSD")
public abstract class DynamicallyMutableObject extends DynamicallyAccessibleObject implements DynamicallyMutable {
private static Logger logger = Logger.getLogger(DynamicallyMutableObject.class.getName());
public void setNull(String attributeName, Class valueType) {
setNull(this,attributeName,valueType);
}
public void setNull(Object target, String attributeName, Class valueType) {
if (valueType == null)
throw new IllegalArgumentException("Cannot give a valueType of null for setNull(String,Class) method.");
set(target,attributeName, null, valueType);
}
public void set(String attributeName,Object value) {
set(this,attributeName,value);
}
public static void set(Object target, String attributeName,Object value) {
if (value == null) set(target,attributeName, value, null);
else set(target,attributeName, value, value.getClass());
}
public void set(String attributeName,Object value, Class valueType) {
set(this,attributeName,value,valueType);
}
public static void set(Object target,String attributeName,Object value, Class valueType) {
if (value == null) {
if (valueType != null && valueType.isPrimitive()) throw new IllegalArgumentException("Attempted to set null on a variable or accessor for attribute '"+attributeName+"' of primitive type: " + valueType);
String selector = getMutatorSelector(target,attributeName,valueType);
if (selector != null) {
Method m = DynamicUtil.getMethodForSelector(target,selector);
Class[] parmTypes = m.getParameterTypes();
if (parmTypes[0].isPrimitive())
throw new IllegalArgumentException("Attempted to set null using an accessor for attribute '"+attributeName+"' of primitive type: " + parmTypes[0]);
DynamicUtil.performOn(target,selector,new Object[]{value});
} else {
Field f = DynamicUtil.getField(target,attributeName);
if (f == null || f.getType().isPrimitive())
throw new IllegalArgumentException("Attempted to set null but could not find a set"+Strings.camel(attributeName)+" method with a single non-primitive type.");
else
_setField(target,attributeName,valueType);
}
} else /* value != null */ {
if (valueType == null) valueType = value.getClass();
if (hasMutator(target,attributeName,valueType)) {
DynamicUtil.performOn(target,getMutatorSelector(target,attributeName,valueType),new Object[]{value});
return;
} else if(hasMutator(target,attributeName,DynamicUtil.getPrimitiveTypeEquivalent(valueType))) {
DynamicUtil.performOn(target,getMutatorSelector(target,attributeName,DynamicUtil.getPrimitiveTypeEquivalent(valueType)),new Object[]{value});
return;
} else {
_setField(target,attributeName,value);
}
}
}
protected void _setField(String attributeName,Object value) {
_setField(this,attributeName,value);
}
protected static void _setField(Object target, String attributeName,Object value) {
Field f = DynamicUtil.getField(target,attributeName);
try {
if (f == null) {
RuntimeException rte = new RuntimeException("Could not find field named " + attributeName,
new NoSuchFieldException(target + " has no property " + attributeName));
logger.log(Level.FINEST,"Failed to set field.",rte);
throw rte;
}
f.set(target,Types.convert(value,f.getType()));
} catch (IllegalAccessException e) {
logger.log(Level.FINEST,"Object attempted to dynamically access a inaccessible field.",e);
throw new RuntimeException(e);
}
}
protected static final String mutatePrefix = "set";
protected String getMutatorSelector(String attributeName,Class type) {
return getMutatorSelector(this,attributeName,type);
}
protected static String getMutatorSelector(Object target, String attributeName,Class type) {
if (attributeName == null || attributeName.equals("")) return null;
String camelAttr = Strings.camel(attributeName);
String selector = null;
if (type == null) {
Method method = _tryToFindMutator(target,attributeName);
if (method == null) {
return null;
} else /* method != null */ {
if (method.getParameterTypes().length != 1) return null;
else return "set"+Strings.camel(attributeName)+":"+method.getParameterTypes()[0].getName();
}
} else /* type != null */ {
String tmp = mutatePrefix+camelAttr+":"+type.getName();
if (DynamicUtil.respondsTo(target,tmp)) selector = tmp;
Iterator i = DynamicUtil.getAllParentTypes(type).iterator();
while (selector == null && i.hasNext()) {
Class c = (Class)i.next();
tmp = mutatePrefix+camelAttr+":"+c.getName();
if (DynamicUtil.respondsTo(target,tmp)) selector = tmp;
}
}
return selector;
}
protected static Method _tryToFindMutator(Object target, String attributeName) {
Method method = null;
Method[] methods = target.getClass().getMethods();
for (int i = 0; i < methods.length; i++) {
if (methods[i].getName().equals("set"+Strings.camel(attributeName))) {
if (method == null) method = methods[i];
else throw new IllegalArgumentException("Attempted to find "+mutatePrefix+Strings.camel(attributeName) + " without a given type, but more than one such method exists. Should use set(String,Object,Class)");
}
}
return method;
}
protected static Method _tryToFindMutator(Object target, String attributeName, Class type) {
if (type == null) throw new IllegalArgumentException("Must set a type, or use _tryToFindMutator(Object,String).");
String methodName = mutatePrefix+Strings.camel(attributeName);
Method m = DynamicUtil.getMethodForSelector(target,methodName+":"+type.getName());
Iterator types = DynamicUtil.getAllParentTypes(type).iterator();
while (m == null && types.hasNext()) {
Class c = (Class)types.next();
m = DynamicUtil.getMethodForSelector(target,methodName+":"+c.getName());
}
return m;
}
public static Method getMutator(Object target, String attributeName, Class type) {
if (type == null) {
return _tryToFindMutator(target,attributeName);
} else {
return _tryToFindMutator(target,attributeName,type);
}
}
public boolean hasMutator(String attributeName,Class type) {
return hasMutator(this,attributeName,type);
}
public static boolean hasMutator(Object target, String attributeName,Class type) {
return getMutatorSelector(target,attributeName,type) != null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy