From 7c279747beb43c7e88633a6228a155a30e6834f7 Mon Sep 17 00:00:00 2001 From: Benjamin Culkin Date: Mon, 27 May 2024 11:38:33 -0400 Subject: Initial import --- .../dynamic/DynamicallyMutableObject.java | 197 +++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyMutableObject.java (limited to 'israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyMutableObject.java') diff --git a/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyMutableObject.java b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyMutableObject.java new file mode 100644 index 0000000..63b301d --- /dev/null +++ b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyMutableObject.java @@ -0,0 +1,197 @@ +/* + * 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: DynamicallyMutableObject.java 127 2006-11-09 18:04:43Z cgruber $ + */ +package net.israfil.foundation.dynamic; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.logging.Level; +import java.util.logging.Logger; + +import net.israfil.foundation.core.Strings; +import net.israfil.foundation.core.Types; + +/** + * 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 + * + */ +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; + for (Class c : DynamicUtil.getAllParentTypes(type)) { + 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()); + for (Class c : DynamicUtil.getAllParentTypes(type)) { + 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; + } +} -- cgit v1.2.3