/* * 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.service.form.impl; import static com.alibaba.citrus.service.form.FormConstant.*; import static com.alibaba.citrus.util.CollectionUtil.*; import static com.alibaba.citrus.util.ObjectUtil.*; import static com.alibaba.citrus.util.StringUtil.*; import java.util.Collection; import java.util.Collections; import java.util.Enumeration; import java.util.List; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletRequest; import com.alibaba.citrus.service.form.Form; import com.alibaba.citrus.service.form.Group; import com.alibaba.citrus.service.form.MessageContext; import com.alibaba.citrus.service.form.configuration.FieldConfig; import com.alibaba.citrus.service.form.configuration.FormConfig; import com.alibaba.citrus.service.form.configuration.GroupConfig; import com.alibaba.citrus.service.form.impl.FormParameters.FormParameter; import com.alibaba.citrus.util.StringUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.SimpleTypeConverter; import org.springframework.beans.TypeConverter; /** * 代表一个用户提交的form信息。 * <p> * 注意:form对象不是线程安全的,不能被多线程共享。 * </p> * * @author Michael Zhou */ public class FormImpl implements Form { protected static final Logger log = LoggerFactory.getLogger(Form.class); private final FormConfig formConfig; private final String formKey; private final boolean forcePostOnly; private final Map<String, Group> groups = createLinkedHashMap(); private final Collection<Group> groupList = Collections.unmodifiableCollection(groups.values()); private final MessageContext messageContext; private boolean valid; private SimpleTypeConverter typeConverter; /** 创建一个新form。 */ public FormImpl(FormConfig formConfig, String formKey, boolean forcePostOnly) { this.formConfig = formConfig; this.formKey = formKey; this.messageContext = MessageContextFactory.newInstance(this); this.forcePostOnly = forcePostOnly; } /** 取得form的配置信息。 */ public FormConfig getFormConfig() { return formConfig; } /** 取得用于转换类型的converter。 */ public TypeConverter getTypeConverter() { if (typeConverter == null) { typeConverter = new SimpleTypeConverter(); getFormConfig().getPropertyEditorRegistrar().registerCustomEditors(typeConverter); } return typeConverter; } /** 是否强制为只接受post表单。 */ public boolean isForcePostOnly() { return forcePostOnly; } /** 判定form是否通过验证。 */ public boolean isValid() { return valid; } /** 设置form的合法性。该值将被叠加到当前的状态中:<code>this.valid &= valid</code> */ protected void setValid(boolean valid) { this.valid &= valid; } /** 初始化form,将form恢复成“未验证”状态。随后,调用者可以重新设置值并手工验证表单。 */ public void init() { init(null); } /** 用request初始化form。假如request为<code>null</code>,则将form设置成“未验证”状态,否则,验证表单。 */ public void init(HttpServletRequest request) { valid = true; // 清除所有group groups.clear(); if (request != null) { Set<String> ignoredGroups = createHashSet(); boolean logStarted = false; // 扫描用户submit过来的所有form参数,找到符合格式的key:formKey.groupKey.instanceKey.fieldKey @SuppressWarnings("unchecked") Enumeration<String> e = request.getParameterNames(); FormParameters params = new FormParameters(request); while (e.hasMoreElements()) { String key = e.nextElement(); FormParameter param = parseParameterKey(key); // param为null表示该参数不是从form service生成的,忽略之 if (param != null) { if (!logStarted) { logStarted = true; log.debug("Initializing user-submitted form for validating"); } params.addFormParameter(param); String groupKey = param.groupKey; String instanceKey = param.instanceKey; String groupInstanceKey = getGroupInstanceKey(groupKey, instanceKey); // 下面从request中初始化所有group instance, // 并确保不会重复初始化同一个group instance。 if (!groups.containsKey(groupInstanceKey) && !ignoredGroups.contains(groupInstanceKey)) { GroupConfig groupConfig = getFormConfig().getGroupConfigByKey(groupKey); if (groupConfig == null) { log.debug("No group associated with parameter: {}", key); continue; } else if ((forcePostOnly || groupConfig.isPostOnly()) && !"post".equalsIgnoreCase(request.getMethod())) { log.warn("Group {} can only read from POST request: {}", groupConfig.getName(), key); ignoredGroups.add(groupInstanceKey); setValid(false); continue; } else { groups.put(groupInstanceKey, new GroupImpl(groupConfig, this, instanceKey)); } } } } for (Group group : groups.values()) { if (log.isDebugEnabled()) { if (DEFAULT_GROUP_INSTANCE_KEY.equals(group.getInstanceKey())) { log.debug("Initializing form group: {}", group.getName()); } else { log.debug("Initializing form group: {}[{}]", group.getName(), group.getInstanceKey()); } } if (group instanceof GroupImpl) { ((GroupImpl) group).init(params); } } } } /** * 解析从URL中传过来的key,如果解析成功,则返回相应的groupKey,instanceKey和fieldKey,否则返回 * <code>null</code>。 */ private FormParameter parseParameterKey(String paramKey) { if (!paramKey.startsWith(FORM_KEY_PREFIX)) { return null; } String[] parts = StringUtil.split(paramKey, FIELD_KEY_SEPARATOR, 5); if (parts.length < 4 || !isEquals(parts[0], this.formKey)) { return null; } String groupKey = toLowerCase(parts[1]); String instanceKey = parts[2]; String fieldKey = toLowerCase(parts[3]); String additionalInfo = parts.length > 4 ? parts[4] : null; // 取得规格化的group/field key,即: // 如果fieldKeyFormat=compressed,则为压缩格式; // 如果fieldKeyFormat=uncompressed,则为非压缩格式; // 如果group或field不存在,则暂且保持key原值,后面会报警告。 GroupConfig groupConfig = getFormConfig().getGroupConfigByKey(groupKey); if (groupConfig != null) { groupKey = groupConfig.getKey(); FieldConfig fieldConfig = groupConfig.getFieldConfigByKey(fieldKey); if (fieldConfig != null) { fieldKey = fieldConfig.getKey(); } } String normalizedKey = FORM_KEY_PREFIX + FIELD_KEY_SEPARATOR + groupKey + FIELD_KEY_SEPARATOR + instanceKey + FIELD_KEY_SEPARATOR + fieldKey; if (additionalInfo != null) { normalizedKey += FIELD_KEY_SEPARATOR + additionalInfo; } return new FormParameter(groupKey, fieldKey, instanceKey, additionalInfo, paramKey, normalizedKey); } /** 取得group instance的key,用来索引所有group instance。 */ private String getGroupInstanceKey(String groupKey, String instanceKey) { return groupKey + FIELD_KEY_SEPARATOR + instanceKey; } /** 验证(或重新验证)当前的所有group instance。 */ public void validate() { valid = true; for (Group group : getGroups()) { group.validate(); } } /** 取得代表form的key。 */ public String getKey() { return formKey; } /** 取得所有group的列表。 */ public Collection<Group> getGroups() { return groupList; } /** 取得所有指定名称的group的列表。group名称大小写不敏感。 */ public Collection<Group> getGroups(String groupName) { List<Group> resultGroups = createArrayList(groups.size()); for (Group group : groups.values()) { if (group.getName().equalsIgnoreCase(groupName)) { resultGroups.add(group); } } return resultGroups; } /** 取得默认的group instance。如果该group instance不存在,则创建之。Group名称大小写不敏感。 */ public Group getGroup(String groupName) { return getGroup(groupName, null, true); } /** 取得group instance。如果该group instance不存在,则创建之。Group名称大小写不敏感。 */ public Group getGroup(String groupName, String instanceKey) { return getGroup(groupName, instanceKey, true); } /** * 取得group instance。如果该group instance不存在,并且<code>create == true</code> * ,则创建之。Group名称大小写不敏感。 */ public Group getGroup(String groupName, String instanceKey, boolean create) { GroupConfig groupConfig = getFormConfig().getGroupConfig(groupName); if (groupConfig == null) { return null; } instanceKey = defaultIfNull(trimToNull(instanceKey), DEFAULT_GROUP_INSTANCE_KEY); String groupInstanceKey = getGroupInstanceKey(groupConfig.getKey(), instanceKey); Group group = groups.get(groupInstanceKey); if (group == null && create) { group = new GroupImpl(groupConfig, this, instanceKey); groups.put(groupInstanceKey, group); group.init(); } return group; } /** 取得form级别的错误信息表达式的context,包含常用小工具和所有系统属性。 */ protected MessageContext getMessageContext() { return messageContext; } /** 转换成易于阅读的字符串。 */ @Override public String toString() { return "Form[groups: " + getFormConfig().getGroupConfigList().size() + ", group instances: " + getGroups().size() + ", valid: " + isValid() + "]"; } }