/* * Copyright (c) 2002-2012 Alibaba Group Holding Limited. * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.alibaba.citrus.turbine.dataresolver.impl; import static com.alibaba.citrus.generictype.TypeInfoUtil.*; import static com.alibaba.citrus.springext.util.SpringExtUtil.*; import static com.alibaba.citrus.turbine.dataresolver.impl.DataResolverUtil.*; import static com.alibaba.citrus.util.Assert.*; import static com.alibaba.citrus.util.StringUtil.*; import java.util.ArrayList; import java.util.Collection; import java.util.List; import com.alibaba.citrus.service.dataresolver.DataResolver; import com.alibaba.citrus.service.dataresolver.DataResolverContext; import com.alibaba.citrus.service.dataresolver.DataResolverFactory; import com.alibaba.citrus.service.form.Field; import com.alibaba.citrus.service.form.Form; import com.alibaba.citrus.service.form.FormService; import com.alibaba.citrus.service.form.Group; import com.alibaba.citrus.service.form.configuration.FieldConfig; import com.alibaba.citrus.service.form.configuration.GroupConfig; import com.alibaba.citrus.service.moduleloader.SkipModuleExecutionException; import com.alibaba.citrus.springext.support.parser.AbstractSingleBeanDefinitionParser; import com.alibaba.citrus.turbine.dataresolver.FormData; import com.alibaba.citrus.turbine.dataresolver.FormField; import com.alibaba.citrus.turbine.dataresolver.FormFields; import com.alibaba.citrus.turbine.dataresolver.FormGroup; import com.alibaba.citrus.turbine.dataresolver.FormGroups; import net.sf.cglib.reflect.FastConstructor; import org.springframework.beans.TypeMismatchException; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.core.MethodParameter; import org.w3c.dom.Element; public class FormResolverFactory implements DataResolverFactory { private final FormService formService; public FormResolverFactory(FormService formService) { this.formService = formService; } public DataResolver getDataResolver(DataResolverContext context) { // 当所需要的对象未定义时,resolver factory仍可以创建,但在取得resolver时报错。 // 这样使得同一套配置可用于所有环境,仅当你需要注入特定对象时,才报错。 assertNotNull(formService, "no FormService defined"); Class<?> paramType = context.getTypeInfo().getRawType(); // Form对象 FormData formAnnotation = context.getAnnotation(FormData.class); if (formAnnotation != null || paramType.isAssignableFrom(Form.class)) { return new FormResolver(context, paramType, formAnnotation); } // Group对象:annotation @FormGroup,参数类型可为Group或任意POJO FormGroup groupAnnotation = context.getAnnotation(FormGroup.class); if (groupAnnotation != null) { return new GroupResolver(context, paramType, groupAnnotation); } // Field对象:annotation @FormField,参数类型可为Field或任意类型 FormField fieldAnnotation = context.getAnnotation(FormField.class); if (fieldAnnotation != null) { return new FieldResolver(context, paramType, fieldAnnotation); } // Groups对象:annotation @FormGroups,参数类型可为Group[],List<Group>或任意可转换的类型 FormGroups groupsAnnotation = context.getAnnotation(FormGroups.class); if (groupsAnnotation != null) { return new GroupsResolver(context, paramType, groupsAnnotation); } // Fields对象:annotation @FormFields,参数类型可为Field[],List<Field>或任意可转换的类型 FormFields fieldsAnnotation = context.getAnnotation(FormFields.class); if (fieldsAnnotation != null) { return new FieldsResolver(context, paramType, fieldsAnnotation); } return null; } private boolean isConverterQuiet(Form form) { return form.getFormConfig().isConverterQuiet(); } /** 检验form中的所有groups均被检验,并通过所有验证。 */ private boolean isValidatedAndValid(Form form) { if (!form.isValid() || form.getGroups().isEmpty()) { return false; } for (Group group : form.getGroups()) { if (!group.isValidated()) { return false; } } return true; } private class FormResolver extends AbstractFormResolver { public FormResolver(DataResolverContext context, Class<?> paramType, FormData formAnnotation) { super("FormResolver", context); // 参数类型必须为Form assertTrue(paramType.isAssignableFrom(Form.class), "Parameter type annotated with @FormData should be Form"); this.skipIfInvalid = true; // @FormData可选 if (formAnnotation != null) { this.skipIfInvalid = formAnnotation.skipIfInvalid(); } } public Object resolve() { Form form = formService.getForm(); skipModuleExecutionIfNecessary(isValidatedAndValid(form), form); return form; } } private class GroupResolver extends AbstractFormResolver { private final String groupName; private final String groupInstanceKey; private final FastConstructor fc; public GroupResolver(DataResolverContext context, Class<?> paramType, FormGroup groupAnnotation) { super("GroupResolver", context); groupInstanceKey = trimToNull(groupAnnotation.instanceKey()); skipIfInvalid = groupAnnotation.skipIfInvalid(); // name()或value() - 确保group存在 groupName = getGroupConfig( getAnnotationNameOrValue(FormGroup.class, groupAnnotation, context, groupInstanceKey != null || skipIfInvalid == false)).getName(); // 假如是pojo,则取得constructor。 if (!paramType.isAssignableFrom(Group.class)) { fc = getFastConstructor(paramType); } else { fc = null; } } public Object resolve() { Form form = formService.getForm(); Group group = form.getGroup(groupName, groupInstanceKey); boolean valid = isValidatedAndValid(form); if (fc == null) { skipModuleExecutionIfNecessary(valid, group); return group; } else { skipModuleExecutionIfNecessary(valid, null); if (valid) { Object object = newInstance(fc); group.setProperties(object); return object; } else { return null; } } } } private class FieldResolver extends AbstractFormResolver { private final String groupName; private final String groupInstanceKey; private final String fieldName; public FieldResolver(DataResolverContext context, Class<?> paramType, FormField fieldAnnotation) { super("FieldResolver", context); // 确保group存在 groupName = getGroupConfig(fieldAnnotation.group()).getName(); // 确保field存在 fieldName = getFieldConfig(groupName, fieldAnnotation.name()).getName(); groupInstanceKey = trimToNull(fieldAnnotation.groupInstanceKey()); skipIfInvalid = fieldAnnotation.skipIfInvalid(); } public Object resolve() { Form form = formService.getForm(); Group group = form.getGroup(groupName, groupInstanceKey); Field field = group.getField(fieldName); boolean valid = isValidatedAndValid(form); if (context.getTypeInfo().getRawType().isAssignableFrom(Field.class)) { skipModuleExecutionIfNecessary(valid, field); return field; } else { skipModuleExecutionIfNecessary(valid, null); if (valid) { try { return field.getValueOfType(context.getTypeInfo().getRawType(), context.getExtraObject(MethodParameter.class), null); } catch (TypeMismatchException e) { if (!isConverterQuiet(form)) { throw e; } } } return null; } } } private class GroupsResolver extends AbstractFormResolver { private final String groupName; private final Class<?> componentType; private final FastConstructor fc; public GroupsResolver(DataResolverContext context, Class<?> paramType, FormGroups groupsAnnotation) { super("GroupResolver", context); skipIfInvalid = groupsAnnotation.skipIfInvalid(); // name()或value() - 确保group存在 groupName = getGroupConfig( getAnnotationNameOrValue(FormGroups.class, groupsAnnotation, context, skipIfInvalid == false)) .getName(); // param类型:数组、Collection if (paramType.isArray()) { componentType = paramType.getComponentType(); } else if (Collection.class.isAssignableFrom(paramType)) { componentType = resolveIterableElement(context.getTypeInfo()).getRawType(); } else { componentType = null; } // component类型可以是Group或任意类,但不能是Object。 assertTrue(componentType != null && !Object.class.equals(componentType), "Invalid paramType: %s", context.getTypeInfo()); if (!componentType.isAssignableFrom(Group.class)) { fc = getFastConstructor(componentType); } else { fc = null; } } public Object resolve() { Form form = formService.getForm(); Collection<Group> groups = form.getGroups(groupName); boolean valid = isValidatedAndValid(form); if (fc == null) { Object result = null; try { result = form.getTypeConverter().convertIfNecessary(groups, context.getTypeInfo().getRawType(), context.getExtraObject(MethodParameter.class)); } catch (TypeMismatchException e) { if (!isConverterQuiet(form)) { throw e; } return null; } skipModuleExecutionIfNecessary(valid, result); return result; } else { skipModuleExecutionIfNecessary(valid, null); if (!valid) { return null; } Object[] results = new Object[groups.size()]; int i = 0; for (Group group : groups) { Object object = newInstance(fc); group.setProperties(object); results[i++] = object; } try { return form.getTypeConverter().convertIfNecessary(results, context.getTypeInfo().getRawType(), context.getExtraObject(MethodParameter.class)); } catch (TypeMismatchException e) { if (!isConverterQuiet(form)) { throw e; } return null; } } } } private class FieldsResolver extends AbstractFormResolver { private final String groupName; private final String fieldName; private final Class<?> componentType; public FieldsResolver(DataResolverContext context, Class<?> paramType, FormFields fieldsAnnotation) { super("FieldsResolver", context); skipIfInvalid = fieldsAnnotation.skipIfInvalid(); // 确保group存在 groupName = getGroupConfig(fieldsAnnotation.group()).getName(); // 确保field存在 fieldName = getFieldConfig(groupName, fieldsAnnotation.name()).getName(); // param类型:数组、Collection if (paramType.isArray()) { componentType = paramType.getComponentType(); } else if (Collection.class.isAssignableFrom(paramType)) { componentType = resolveIterableElement(context.getTypeInfo()).getRawType(); } else { componentType = null; } // component类型可以是Field或任意类,但不能是Object。 assertTrue(componentType != null && !Object.class.equals(componentType), "Invalid paramType: %s", context.getTypeInfo()); } public Object resolve() { Form form = formService.getForm(); // 取得同名group instances中的指定field。 Collection<Group> groups = form.getGroups(groupName); List<Field> fields = new ArrayList<Field>(groups.size()); for (Group group : groups) { fields.add(group.getField(fieldName)); } boolean valid = isValidatedAndValid(form); if (componentType.isAssignableFrom(Field.class)) { Object result = null; try { result = form.getTypeConverter().convertIfNecessary(fields, context.getTypeInfo().getRawType(), context.getExtraObject(MethodParameter.class)); } catch (TypeMismatchException e) { if (!isConverterQuiet(form)) { throw e; } return null; } skipModuleExecutionIfNecessary(valid, result); return result; } else { skipModuleExecutionIfNecessary(valid, null); if (!valid) { return null; } Object[] results = new Object[fields.size()]; for (int i = 0; i < results.length; i++) { try { results[i] = fields.get(i).getValueOfType(componentType, context.getExtraObject(MethodParameter.class), null); } catch (TypeMismatchException e) { if (!isConverterQuiet(form)) { throw e; } results[i] = null; } } try { return form.getTypeConverter().convertIfNecessary(results, context.getTypeInfo().getRawType(), context.getExtraObject(MethodParameter.class)); } catch (TypeMismatchException e) { if (!isConverterQuiet(form)) { throw e; } return null; } } } } private abstract class AbstractFormResolver extends AbstractDataResolver { protected boolean skipIfInvalid; private AbstractFormResolver(String desc, DataResolverContext context) { super(desc, context); } protected final void skipModuleExecutionIfNecessary(boolean valid, Object valueForNonSkippable) throws SkipModuleExecutionException { if (skipIfInvalid && !valid) { throw new SkipModuleExecutionException("Form data is not valid", valueForNonSkippable); } } protected final GroupConfig getGroupConfig(String groupName) { groupName = assertNotNull(trimToNull(groupName), "group name is empty"); return assertNotNull(formService.getFormConfig().getGroupConfig(groupName), "group \"%s\" does not defined", groupName); } protected final FieldConfig getFieldConfig(String groupName, String fieldName) { GroupConfig groupConfig = getGroupConfig(groupName); fieldName = assertNotNull(trimToNull(fieldName), "field name is empty"); return assertNotNull(groupConfig.getFieldConfig(fieldName), "field \"%s.%s\" does not defined", groupConfig.getName(), fieldName); } } public static class DefinitionParser extends AbstractSingleBeanDefinitionParser<FormResolverFactory> { @Override protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { addConstructorArg(builder, false, FormService.class); } } }