Package wwutil.model

Source Code of wwutil.model.BuiltinFunc

/******************************************************************************
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0.  If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* The Original Code is: Jsoda
* The Initial Developer of the Original Code is: William Wong (williamw520@gmail.com)
* Portions created by William Wong are Copyright (C) 2012 William Wong, All Rights Reserved.
*
******************************************************************************/


package wwutil.model;

import java.io.*;
import java.net.*;
import java.util.*;
import java.util.regex.*;
import java.text.MessageFormat;
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.concurrent.*;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.beanutils.ConvertUtils;

import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.auth.AWSCredentials;

import wwutil.sys.BaseXUtil;
import wwutil.sys.ReflectUtil;
import wwutil.model.AnnotationRegistry;
import wwutil.model.AnnotationClassHandler;
import wwutil.model.AnnotationFieldHandler;
import wwutil.model.ValidationException;
import wwutil.model.MaskMatcher;
import wwutil.model.annotation.*;


/**
* Built-in data generation and validation functions.
*/
public class BuiltinFunc
{
    private static Pattern  sEmailPattern = Pattern.compile(EmailMatch.regex);

    private static AnnotationRegistry   sPreStore1Registry = new AnnotationRegistry();
    private static AnnotationRegistry   sPreStore2Registry = new AnnotationRegistry();
    private static AnnotationRegistry   sValidationRegistry = new AnnotationRegistry();
    private static AnnotationRegistry   sPostLoadRegistry = new AnnotationRegistry();


    static {
        try {
            setupBuiltinPreStore1Handlers(sPreStore1Registry);
            setupBuiltinPreStore2Handlers(sPreStore2Registry);
            setupBuiltinValidationHandlers(sValidationRegistry);
            setupBuiltinPostLoadHandlers(sPostLoadRegistry);
        } catch(Throwable e) {
            e.printStackTrace();
        }
    }

    public static AnnotationRegistry clonePreStore1Registry() {
        return sPreStore1Registry.cloneRegistry();
    }

    public static AnnotationRegistry clonePreStore2Registry() {
        return sPreStore2Registry.cloneRegistry();
    }

    public static AnnotationRegistry cloneValidationRegistry() {
        return sValidationRegistry.cloneRegistry();
    }

    public static AnnotationRegistry clonePostLoadRegistry() {
        return sPostLoadRegistry.cloneRegistry();
    }
   

    ////////////////////////////////////////////////////////////////////////////
    // Stage 1 data handlers
    ////////////////////////////////////////////////////////////////////////////

    private static void setupBuiltinPreStore1Handlers(AnnotationRegistry registry) {

        registry.register( DefaultGUID.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != String.class)
                    throw new ValidationException("The @DefaultGUID field must be String type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                Object      value = field.get(object);
                if (value == null || value.toString().length() == 0) {
                    boolean isShort = ReflectUtil.getAnnoValue(fieldAnnotation, "isShort", false);
                    String  uuidStr = isShort ? BaseXUtil.uuid8() : BaseXUtil.uuid16();
                    field.set(object, uuidStr);
                }
            }
        });

        registry.register( ModifiedTime.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != java.util.Date.class)
                    throw new ValidationException("The @ModifiedTime field must be java.util.Date type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                field.set(object, new Date());
            }
        });

        registry.register( VersionLocking.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != Integer.class && field.getType() != int.class)
                    throw new ValidationException("The @VersionLocking field must be int type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                ReflectUtil.incrementField(object, field, 1);
            }
        });

        registry.register( ToUpper.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != String.class)
                    throw new ValidationException("The @ToUpper field must be String type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                String  value = (String)field.get(object);
                if (value != null) {
                    field.set(object, value.toUpperCase());
                }
            }
        });

        registry.register( ToLower.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != String.class)
                    throw new ValidationException("The @ToLower field must be String type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                String  value = (String)field.get(object);
                if (value != null) {
                    field.set(object, value.toLowerCase());
                }
            }
        });

        registry.register( Trim.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != String.class)
                    throw new ValidationException("The @Trim field must be String type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                String  value = (String)field.get(object);
                if (value != null) {
                    field.set(object, value.trim());
                }
            }
        });

        registry.register( RemoveChar.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != String.class)
                    throw new ValidationException("The @RemoveChar field must be String type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                char    charToRemove = ReflectUtil.getAnnoValue(fieldAnnotation, "charToRemove", ' ');
                String  value = (String)field.get(object);
                if (value != null) {
                    field.set(object, StringUtils.remove(value, charToRemove));
                }
            }
        });

        registry.register( RemoveAlphaDigits.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != String.class)
                    throw new ValidationException("The @RemoveAlphaDigits field must be String type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                boolean removeDigits = ReflectUtil.getAnnoValue(fieldAnnotation, "removeDigits", false);
                String  value = (String)field.get(object);
                if (value != null) {
                    if (removeDigits)
                        field.set(object, value.replaceAll("[\\d]", ""));   // remove all digits
                    else
                        field.set(object, value.replaceAll("[^\\d]", ""))// remove all alphas (non-digits)
                }
            }
        });

        registry.register( MaxValue.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != Integer.class && field.getType() != int.class &&
                    field.getType() != Long.class && field.getType() != long.class &&
                    field.getType() != Short.class && field.getType() != short.class &&
                    field.getType() != Float.class && field.getType() != float.class &&
                    field.getType() != Double.class && field.getType() != double.class)
                    throw new ValidationException("The @MaxValue field must be number type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                Object  maxValueObj = ReflectUtil.getAnnoValue(fieldAnnotation, "value", (Object)null);
                double  maxValue = ((Double)ConvertUtils.convert(maxValueObj, Double.class)).doubleValue();
                Object  valueObj = field.get(object);
                double  value = ((Double)ConvertUtils.convert(valueObj, Double.class)).doubleValue();
                value = (value > maxValue ? maxValue : value);
                field.set(object, ConvertUtils.convert(value, field.getType()));
            }
        });

        registry.register( MinValue.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != Integer.class && field.getType() != int.class &&
                    field.getType() != Long.class && field.getType() != long.class &&
                    field.getType() != Short.class && field.getType() != short.class &&
                    field.getType() != Float.class && field.getType() != float.class &&
                    field.getType() != Double.class && field.getType() != double.class)
                    throw new ValidationException("The @MinValue field must be number type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                Object  minValueObj = ReflectUtil.getAnnoValue(fieldAnnotation, "value", (Object)null);
                double  minValue = ((Double)ConvertUtils.convert(minValueObj, Double.class)).doubleValue();
                Object  valueObj = field.get(object);
                double  value = ((Double)ConvertUtils.convert(valueObj, Double.class)).doubleValue();
                value = (value < minValue ? minValue : value);
                field.set(object, ConvertUtils.convert(value, field.getType()));
            }
        });

        registry.register( AbsValue.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != Integer.class && field.getType() != int.class &&
                    field.getType() != Long.class && field.getType() != long.class &&
                    field.getType() != Short.class && field.getType() != short.class &&
                    field.getType() != Float.class && field.getType() != float.class &&
                    field.getType() != Double.class && field.getType() != double.class)
                    throw new ValidationException("The @AbsValue field must be number type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                Object  valueObj = field.get(object);
                double  value = ((Double)ConvertUtils.convert(valueObj, Double.class)).doubleValue();
                value = Math.abs(value);
                field.set(object, ConvertUtils.convert(value, field.getType()));
            }
        });

        registry.register( CeilValue.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != Integer.class && field.getType() != int.class &&
                    field.getType() != Long.class && field.getType() != long.class &&
                    field.getType() != Short.class && field.getType() != short.class &&
                    field.getType() != Float.class && field.getType() != float.class &&
                    field.getType() != Double.class && field.getType() != double.class)
                    throw new ValidationException("The @CeilValue field must be number type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                Object  valueObj = field.get(object);
                double  value = ((Double)ConvertUtils.convert(valueObj, Double.class)).doubleValue();
                value = Math.ceil(value);
                field.set(object, ConvertUtils.convert(value, field.getType()));
            }
        });

        registry.register( FloorValue.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != Integer.class && field.getType() != int.class &&
                    field.getType() != Long.class && field.getType() != long.class &&
                    field.getType() != Short.class && field.getType() != short.class &&
                    field.getType() != Float.class && field.getType() != float.class &&
                    field.getType() != Double.class && field.getType() != double.class)
                    throw new ValidationException("The @FloorValue field must be number type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                Object  valueObj = field.get(object);
                double  value = ((Double)ConvertUtils.convert(valueObj, Double.class)).doubleValue();
                value = Math.floor(value);
                field.set(object, ConvertUtils.convert(value, field.getType()));
            }
        });

    }


    ////////////////////////////////////////////////////////////////////////////
    // Stage 2 data handlers
    ////////////////////////////////////////////////////////////////////////////

    private static void setupBuiltinPreStore2Handlers(AnnotationRegistry registry) {

        registry.register( DefaultComposite.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != String.class)
                    throw new ValidationException("The @DefaultComposite field must be String type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                fillDefaultComposite(field, object, allFieldMap);
            }
        });

        registry.register( FormatMsg.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != String.class)
                    throw new ValidationException("The @FormatMsg field must be String type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                FormatMsg       formatMsg = (FormatMsg)fieldAnnotation;
                if (formatMsg.onSave()) {
                    fillFormatMsg(formatMsg, field, object, allFieldMap);
                }
            }
        });

    }


    ////////////////////////////////////////////////////////////////////////////
    // Validation handlers
    ////////////////////////////////////////////////////////////////////////////

    private static void setupBuiltinValidationHandlers(AnnotationRegistry registry) {

        registry.register( Required.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                if (field.get(object) == null)
                    throw new ValidationException("@Required field cannot be null.  Field: " + field.getName());
            }
        });

        registry.register( MaxSize.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != Integer.class && field.getType() != int.class &&
                    field.getType() != Long.class && field.getType() != long.class &&
                    field.getType() != Short.class && field.getType() != short.class &&
                    field.getType() != Float.class && field.getType() != float.class &&
                    field.getType() != Double.class && field.getType() != double.class &&
                    field.getType() != String.class)
                    throw new ValidationException("The @MaxSize field must be number type or String type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                Object  annValueObj = ReflectUtil.getAnnoValue(fieldAnnotation, "value", (Object)null);
                double  annValue = ((Double)ConvertUtils.convert(annValueObj, Double.class)).doubleValue();
                if (annValue != 0) {
                    Object  valueObj = field.get(object);
                    double  value;
                    if (valueObj instanceof String)
                        value = ((String)valueObj).length();
                    else
                        value = ((Double)ConvertUtils.convert(valueObj, Double.class)).doubleValue();
                    if (value > annValue)
                        throw new ValidationException("Field value " + valueObj + " exceeds MaxSize " + annValueObj + ".  Field: " + field.getName());
                }
            }
        });
       
        registry.register( MinSize.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != Integer.class && field.getType() != int.class &&
                    field.getType() != Long.class && field.getType() != long.class &&
                    field.getType() != Short.class && field.getType() != short.class &&
                    field.getType() != Float.class && field.getType() != float.class &&
                    field.getType() != Double.class && field.getType() != double.class &&
                    field.getType() != String.class)
                    throw new ValidationException("The @MinSize field must be number type or String type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                Object  annValueObj = ReflectUtil.getAnnoValue(fieldAnnotation, "value", (Object)null);
                double  annValue = ((Double)ConvertUtils.convert(annValueObj, Double.class)).doubleValue();
                if (annValue != 0) {
                    Object  valueObj = field.get(object);
                    double  value;
                    if (valueObj instanceof String)
                        value = ((String)valueObj).length();
                    else
                        value = ((Double)ConvertUtils.convert(valueObj, Double.class)).doubleValue();
                    if (value < annValue)
                        throw new ValidationException("Field value " + valueObj + " is less than MinSize " + annValueObj + ".  Field: " + field.getName());
                }
            }
        });

        registry.register( StartsWith.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != String.class)
                    throw new ValidationException("The @StartsWith field must be String type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                String  annValue = ReflectUtil.getAnnoValue(fieldAnnotation, "value", "");
                String  value = (String)field.get(object);
                if (value != null && !value.startsWith(annValue))
                    throw new ValidationException("Field value " + value + " does not start with " + annValue + ".  Field: " + field.getName());
            }
        });

        registry.register( EndsWith.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != String.class)
                    throw new ValidationException("The @EndsWith field must be String type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                String  annValue = ReflectUtil.getAnnoValue(fieldAnnotation, "value", "");
                String  value = (String)field.get(object);
                if (value != null && !value.endsWith(annValue))
                    throw new ValidationException("Field value " + value + " does not end with " + annValue + ".  Field: " + field.getName());
            }
        });

        registry.register( Contains.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != String.class)
                    throw new ValidationException("The @Contains field must be String type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                String  annValue = ReflectUtil.getAnnoValue(fieldAnnotation, "value", "");
                String  value = (String)field.get(object);
                if (value != null && !value.contains(annValue))
                    throw new ValidationException("Field value " + value + " does not contain " + annValue + ".  Field: " + field.getName());
            }
        });

        registry.register( NotContains.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != String.class)
                    throw new ValidationException("The @NotContains field must be String type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                String  annValue = ReflectUtil.getAnnoValue(fieldAnnotation, "value", "");
                String  value = (String)field.get(object);
                if (value != null && value.contains(annValue))
                    throw new ValidationException("Field value " + value + " contains " + annValue + ".  Field: " + field.getName());
            }
        });

        registry.register( RegexMatch.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != String.class)
                    throw new ValidationException("The @RegexMatch field must be String type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                String  annValue = ReflectUtil.getAnnoValue(fieldAnnotation, "value", "");
                String  value = (String)field.get(object);
                if (value != null && !Pattern.matches(annValue, value))
                    throw new ValidationException("Field value " + value + " does not match the regex " + annValue + ".  Field: " + field.getName());
            }
        });

        registry.register( EmailMatch.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != String.class)
                    throw new ValidationException("The @EmailMatch field must be String type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                String  value = (String)field.get(object);
                if (value != null) {
                    if (!sEmailPattern.matcher(value.toUpperCase()).matches())
                        throw new ValidationException("Field value " + value + " is not an email.  Field: " + field.getName());
                }
            }
        });



        registry.register( MaskMatch.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != String.class)
                    throw new ValidationException("The @MaskMatch field must be String type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                char    digitMask = ReflectUtil.getAnnoValue(fieldAnnotation, "digitMask", '#');
                char    letterMask = ReflectUtil.getAnnoValue(fieldAnnotation, "letterMask", '@');
                char    anyMask = ReflectUtil.getAnnoValue(fieldAnnotation, "anyMask", '*');
                String  pattern = ReflectUtil.getAnnoValue(fieldAnnotation, "pattern", "");
                String  value = (String)field.get(object);
                if (value != null) {
                    MaskMatcher matcher = new MaskMatcher(pattern, digitMask, letterMask, anyMask);
                    if (!matcher.matches(value))
                        throw new ValidationException("Field value " + value + " does not match the mask pattern " + pattern + ".  Field: " + field.getName());
                }
            }
        });

        registry.register( OneOf.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != String.class)
                    throw new ValidationException("The @OneOf field must be String type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                String[]    annValue = (String[])ReflectUtil.getAnnoValue(fieldAnnotation, "choices", new String[0]);
                String      value = (String)field.get(object);
                if (value != null) {
                    for (String choice : annValue) {
                        if (value.equals(choice))
                            return;
                    }
                    throw new ValidationException("Field value " + value + " is not one of the choices.  Field: " + field.getName());
                }
            }
        });

    }


    ////////////////////////////////////////////////////////////////////////////
    // Stage 2 data handlers
    ////////////////////////////////////////////////////////////////////////////

    private static void setupBuiltinPostLoadHandlers(AnnotationRegistry registry) {

        registry.register( FormatMsg.class, new AnnotationFieldHandler() {
            public void checkModel(Annotation fieldAnnotation, Field field, Map<String, Field> allFieldMap) throws ValidationException {
                if (field.getType() != String.class)
                    throw new ValidationException("The @FormatMsg field must be String type.  Field: " + field.getName());
            }

            public void handle(Annotation fieldAnnotation, Object object, Field field, Map<String, Field> allFieldMap) throws Exception {
                FormatMsg       formatMsg = (FormatMsg)fieldAnnotation;
                if (formatMsg.onLoad()) {
                    fillFormatMsg(formatMsg, field, object, allFieldMap);
                }
            }
        });

    }

   

    private static void fillDefaultComposite(Field field, Object dataObj, Map<String, Field> allFieldMap)
        throws Exception
    {
        String[]        fromFields = ReflectUtil.getAnnotationValue(field, DefaultComposite.class, "fromFields", String[].class, new String[0]);
        int[]           substrLen = ReflectUtil.getAnnotationValue(field, DefaultComposite.class, "substrLen", int[].class, new int[0]);
        String          separator = ReflectUtil.getAnnotationValue(field, DefaultComposite.class, "separator", "-");
        StringBuilder   sb = new StringBuilder();

        for (int i = 0; i < fromFields.length; i++) {
            Field       subpartField = allFieldMap.get(fromFields[i]);
            if (subpartField == null)
                throw new IllegalArgumentException(fromFields[i] + " specified in the fromFields parameter of the @DefaultComposite field " +
                                                   field.getName() + " doesn't exist.");
            Object      subpartValue = subpartField.get(dataObj);
            String      subpartStr = subpartValue == null ? "" : subpartValue.toString();

            subpartStr = getSubpartMax(subpartStr, i, substrLen);

            if (subpartStr.length() > 0) {
                if (sb.length() > 0)
                    sb.append(separator);
                sb.append(subpartStr);
            }
        }

        field.set(dataObj, sb.toString());
    }

    private static String getSubpartMax(String fieldStr, int fieldPos, int[] substrLen) {
        if (substrLen == null || fieldPos >= substrLen.length || substrLen[fieldPos] == 0)
            return fieldStr;
        int len = substrLen[fieldPos] > fieldStr.length() ? fieldStr.length() : substrLen[fieldPos];
        return fieldStr.substring(0, len);
    }

    private static void fillFormatMsg(FormatMsg formatMsg, Field field, Object dataObj, Map<String, Field> allFieldMap)
        throws Exception
    {
        Object[]    paramObjs = new Object[formatMsg.paramFields().length];
        for (int i = 0; i < formatMsg.paramFields().length; i++) {
            Field   paramField = allFieldMap.get(formatMsg.paramFields()[i]);
            if (paramField == null)
                throw new IllegalArgumentException(formatMsg.paramFields()[i] + " specified in the paramFields parameter of the @FormatMsg field " +
                                                   field.getName() + " doesn't exist.");
            paramObjs[i] = paramField.get(dataObj);
        }
        String      msg = MessageFormat.format(formatMsg.format(), paramObjs);
        field.set(dataObj, msg);
    }

}
TOP

Related Classes of wwutil.model.BuiltinFunc

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.