Author: michiel Date: 2009-08-10 15:36:09 +0200 (Mon, 10 Aug 2009) New Revision: 37644
Added: mmbase/trunk/core/src/main/java/org/mmbase/util/functions/Type.java Modified: mmbase/trunk/core/src/main/java/org/mmbase/util/functions/BeanFunction.java mmbase/trunk/core/src/main/java/org/mmbase/util/functions/FunctionFactory.java Log: support for a @Type annotation by which the datatype of a parameter can be completely defined Modified: mmbase/trunk/core/src/main/java/org/mmbase/util/functions/BeanFunction.java =================================================================== --- mmbase/trunk/core/src/main/java/org/mmbase/util/functions/BeanFunction.java 2009-08-10 13:32:16 UTC (rev 37643) +++ mmbase/trunk/core/src/main/java/org/mmbase/util/functions/BeanFunction.java 2009-08-10 13:36:09 UTC (rev 37644) @@ -10,7 +10,10 @@ package org.mmbase.util.functions; import org.mmbase.cache.Cache; - +import org.mmbase.util.xml.DocumentReader; +import org.mmbase.datatypes.util.xml.*; +import org.xml.sax.InputSource; +import java.util.regex.*; import java.lang.reflect.*; import java.util.*; import org.mmbase.util.logging.*; @@ -93,7 +96,7 @@ * <code>claz</code>. Defaults to a producer that simply calls {...@link Class#newInstance()}. * @since MMBase-1.8.5 */ - public static BeanFunction getFunction(final Class claz, String name, Producer producer) throws IllegalAccessException, InstantiationException, InvocationTargetException { + public static BeanFunction getFunction(final Class claz, String name, Producer producer) throws IllegalAccessException, InstantiationException, InvocationTargetException, DependencyException { String key = claz.getName() + '.' + name + '.' + producer; BeanFunction result = beanFunctionCache.get(key); if (result == null) { @@ -106,7 +109,7 @@ * This defaulting version of {...@link #getFunction(Class, String, Producer)} uses a producer that uses {...@link Class#newInstance()}. * Called from {...@link FunctionFactory} */ - public static BeanFunction getFunction(final Class claz, String name) throws IllegalAccessException, InstantiationException, InvocationTargetException { + public static BeanFunction getFunction(final Class claz, String name) throws IllegalAccessException, InstantiationException, InvocationTargetException, DependencyException { return getFunction(claz, name, new Producer() { public Object getInstance() { try { @@ -152,7 +155,7 @@ /** * @since MMBase-1.9.2 */ - public static Parameter<?>[] getParameterDefinition(Object sampleInstance, List<Method> setMethods) throws IllegalAccessException, InvocationTargetException { + public static Parameter<?>[] getParameterDefinition(Object sampleInstance, List<Method> setMethods) throws IllegalAccessException, InvocationTargetException, DependencyException { Class claz = sampleInstance.getClass(); List<Parameter> parameters = new ArrayList<Parameter>(); Method nodeParameter = null; @@ -161,18 +164,32 @@ Class[] parameterTypes = m.getParameterTypes(); if (parameterTypes.length == 1 && methodName.startsWith("set")) { String parameterName = methodName.substring(3); - boolean required = false; - Required requiredAnnotation = m.getAnnotation(Required.class); - required = requiredAnnotation != null; + final org.mmbase.datatypes.DataType dataType; + Type annotatedDataType = m.getAnnotation(Type.class); + if (annotatedDataType != null) { + dataType = getDataType(annotatedDataType.value(), org.mmbase.datatypes.DataTypes.createDataType(parameterName, parameterTypes[0])); + } else { + dataType = org.mmbase.datatypes.DataTypes.createDataType(parameterName, parameterTypes[0]); + } + { + boolean required = false; + Required requiredAnnotation = m.getAnnotation(Required.class); + if (requiredAnnotation != null) { + dataType.setRequired(true); + } + } + // find a corresponding getter method, which can be used for a default value; - Object defaultValue; try { + Object defaultValue; Method getter = claz.getMethod("get" + parameterName); defaultValue = getter.invoke(sampleInstance); + dataType.setDefaultValue(defaultValue); } catch (NoSuchMethodException nsme) { - defaultValue = null; + //defaultValue = null; } + if (Character.isUpperCase(parameterName.charAt(0))) { if (parameterName.length() > 1) { if (! Character.isUpperCase(parameterName.charAt(1))) { @@ -185,14 +202,7 @@ if (parameterName.equals("node") && org.mmbase.bridge.Node.class.isAssignableFrom(parameterTypes[0])) { nodeParameter = m; } else { - if(defaultValue != null) { - if (required) { - log.warn("Required annotation ignored, because a default value is present"); - } - parameters.add(new Parameter<Object>(parameterName, parameterTypes[0], defaultValue)); - } else { - parameters.add(new Parameter(parameterName, parameterTypes[0], required)); - } + parameters.add(new Parameter<Object>(parameterName, dataType)); if (setMethods != null) { setMethods.add(m); } @@ -242,6 +252,30 @@ } + /** + * @since MMBase-1.9.2 + */ + public static final Pattern NCName = Pattern.compile("[\\p{L}_][\\p{L}_\\-\\.0-9]*"); + + /** + * Given a string and a 'base' datatype, produces a new {...@link #DataType}. If the string matches + * {...@link #NCName} then the datatype is looked up in the MMBase DataType repository at {...@link + * org.mmbase.datatypes.DataTypes#getDataType}. Otherwise the String is interpreted as a piece + * of XML. + * + * @since MMBase-1.9.2 + */ + public static org.mmbase.datatypes.DataType getDataType(String value, org.mmbase.datatypes.BasicDataType base) throws org.mmbase.datatypes.util.xml.DependencyException { + if (NCName.matcher(value).matches()) { + return org.mmbase.datatypes.DataTypes.getDataType(value); + } else { + DocumentReader reader = new DocumentReader(new InputSource(new java.io.StringReader(value)), true, org.mmbase.datatypes.util.xml.DataTypeReader.class); + return org.mmbase.datatypes.util.xml.DataTypeReader.readDataType(reader.getDocument().getDocumentElement(), base, null).dataType; + + } + } + + /* ================================================================================ Instance methods ================================================================================ @@ -262,7 +296,7 @@ /** * The constructor! Performs reflection to fill 'method' and 'setMethods' members. */ - private BeanFunction(Class<?> claz, String name, Producer producer) throws IllegalAccessException, InstantiationException, InvocationTargetException { + private BeanFunction(Class<?> claz, String name, Producer producer) throws IllegalAccessException, InstantiationException, InvocationTargetException, DependencyException { super(name, null, null); this.producer = producer; @@ -298,7 +332,7 @@ /** * @since MMBase-1.8.5 */ - public BeanFunction(final Object bean, String name) throws IllegalAccessException, InstantiationException, InvocationTargetException { + public BeanFunction(final Object bean, String name) throws IllegalAccessException, InstantiationException, InvocationTargetException, DependencyException { this(bean.getClass(), name, new Producer() { public Object getInstance() { return bean; }}); } Modified: mmbase/trunk/core/src/main/java/org/mmbase/util/functions/FunctionFactory.java =================================================================== --- mmbase/trunk/core/src/main/java/org/mmbase/util/functions/FunctionFactory.java 2009-08-10 13:32:16 UTC (rev 37643) +++ mmbase/trunk/core/src/main/java/org/mmbase/util/functions/FunctionFactory.java 2009-08-10 13:36:09 UTC (rev 37644) @@ -76,7 +76,8 @@ /** * Gets a function object for a Bean */ - public static Function<Object> getFunction(Class<?> claz, String functionName) throws java.lang.IllegalAccessException, InstantiationException, InvocationTargetException { + public static Function<Object> getFunction(Class<?> claz, String functionName) throws java.lang.IllegalAccessException, InstantiationException, InvocationTargetException, + org.mmbase.datatypes.util.xml.DependencyException { return BeanFunction.getFunction(claz, functionName); } Added: mmbase/trunk/core/src/main/java/org/mmbase/util/functions/Type.java =================================================================== --- mmbase/trunk/core/src/main/java/org/mmbase/util/functions/Type.java (rev 0) +++ mmbase/trunk/core/src/main/java/org/mmbase/util/functions/Type.java 2009-08-10 13:36:09 UTC (rev 37644) @@ -0,0 +1,32 @@ +/* + +This software is OSI Certified Open Source Software. +OSI Certified is a certification mark of the Open Source Initiative. + +The license (Mozilla version 1.0) can be read at the MMBase site. +See http://www.MMBase.org/license + +*/ +package org.mmbase.util.functions; +import java.lang.annotation.*; + +/** + * This annotation can be used on methods, to attribute a {...@link org.mmbase.datatypes.Datatype}, e.g. to the parameter of + * the corresponding {...@link BeanFunction}. + * + * @author Michiel Meeuwissen + * @version $Id: Required.java 34900 2009-05-01 16:29:42Z michiel $ + * @since MMBase-1.9.2 + */ +...@retention(RetentionPolicy.RUNTIME) +...@target({ElementType.METHOD, ElementType.PARAMETER}) +public @interface Type { + + + /** + * An identifier, or an <datatype> xml-element + */ + String value(); + + +} _______________________________________________ Cvs mailing list Cvs@lists.mmbase.org http://lists.mmbase.org/mailman/listinfo/cvs