Package com.alibaba.citrus.service.form.impl

Source Code of com.alibaba.citrus.service.form.impl.FieldImpl$Attachment

/*
* Copyright 2010 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.service.requestcontext.util.RequestContextUtil.*;
import static com.alibaba.citrus.util.Assert.*;
import static com.alibaba.citrus.util.BasicConstant.*;
import static com.alibaba.citrus.util.ObjectUtil.*;
import static com.alibaba.citrus.util.StringUtil.*;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Map;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.citrus.service.form.CustomErrorNotFoundException;
import com.alibaba.citrus.service.form.Field;
import com.alibaba.citrus.service.form.Group;
import com.alibaba.citrus.service.form.MessageContext;
import com.alibaba.citrus.service.form.Validator;
import com.alibaba.citrus.service.form.Validator.Context;
import com.alibaba.citrus.service.form.configuration.FieldConfig;
import com.alibaba.citrus.service.requestcontext.parser.ParserRequestContext;
import com.alibaba.citrus.service.requestcontext.support.ValueListSupport;
import com.alibaba.citrus.util.ArrayUtil;
import com.alibaba.citrus.util.ObjectUtil;
import com.alibaba.citrus.util.StringEscapeUtil;
import com.alibaba.citrus.util.io.ByteArrayInputStream;
import com.alibaba.citrus.util.io.ByteArrayOutputStream;

/**
* �����û����ύ���е�һ��field��
* <p>
* ע�⣺field�������̰߳�ȫ�ģ����ܱ����̹߳���
* </p>
*
* @author Michael Zhou
*/
public class FieldImpl extends ValueListSupport implements Field {
    private final static Logger log = LoggerFactory.getLogger(Field.class);
    private final FieldConfig fieldConfig;
    private final Group group;
    private final String fieldKey;
    private final MessageContext messageContext;
    private boolean valid;
    private String message;
    private Attachment attachment;

    /**
     * ����һ����field��
     */
    public FieldImpl(FieldConfig fieldConfig, Group group) {
        super( //
                assertNotNull(group, "group").getForm().getTypeConverter(), // converter
                fieldConfig.getGroupConfig().getFormConfig().isConverterQuiet() // converter quiet
        );
        this.fieldConfig = assertNotNull(fieldConfig, "fieldConfig");
        this.group = group;
        this.fieldKey = group.getKey() + FIELD_KEY_SEPARATOR + fieldConfig.getKey();
        this.messageContext = MessageContextFactory.newInstance(this);
    }

    /**
     * ȡ��field��������Ϣ��
     */
    public FieldConfig getFieldConfig() {
        return fieldConfig;
    }

    /**
     * ȡ�ð�����field��group��
     */
    public Group getGroup() {
        return group;
    }

    /**
     * �ж�field�Ƿ�ͨ����֤��
     */
    public boolean isValid() {
        return valid;
    }

    /**
     * ȡ����form��Ψһ�����field��key��
     * <p>
     * �ɹ̶�ǰ׺<code>"_fm"</code>������group������д������group instance
     * fieldKey���ټ���field������д���ɡ����磺<code>_fm.m._0.n</code>��
     * </p>
     */
    public String getKey() {
        return fieldKey;
    }

    /**
     * ȡ����form��Ψһ�����field��key�����û��ύ�ı���δ������field����Ϣʱ��ȡ���key��ֵ��Ϊ��field��ֵ��
     * <p>
     * �����checkbox֮���HTML�ؼ��ر����á�
     * </p>
     * <p>
     * Key�ĸ�ʽΪ��<code>_fm.groupKey.instanceKey.fieldKey.absent</code>��
     * </p>
     */
    public String getAbsentKey() {
        return getKey() + FORM_FIELD_ABSENT_KEY;
    }

    /**
     * ȡ����form�к͵�ǰfield�󶨵ĸ�����key��
     * <p>
     * Key�ĸ�ʽΪ��<code>_fm.groupKey.instanceKey.fieldKey.attach</code>��
     * </p>
     */
    public String getAttachmentKey() {
        return getKey() + FORM_FIELD_ATTACHMENT_KEY;
    }

    /**
     * ȡ�ó�����Ϣ��
     */
    public String getMessage() {
        return message;
    }

    /**
     * ���ô�����Ϣ��ͬʱ��<code>isValid()</code>Ϊ<code>false</code>��
     * <p>
     * ����<code>isValid()</code>�Ѿ���<code>false</code>���ֶΣ��÷�����Ч�����������еĴ�����Ϣ��
     * </p>
     * <p>
     * id��ʾ������Ϣ��ID�����붨���form�����ļ��С�
     * </p>
     */
    public void setMessage(String id) {
        setMessage(id, null);
    }

    /**
     * ���ô�����Ϣ��ͬʱ��<code>isValid()</code>Ϊ<code>false</code>��
     * <p>
     * ����<code>isValid()</code>�Ѿ���<code>false</code>���ֶΣ��÷�����Ч�����������еĴ�����Ϣ��
     * </p>
     * <p>
     * id��ʾ������Ϣ��ID�����붨���form�����ļ��С�params��ʾ���ɴ�����Ϣ�IJ�����
     * </p>
     */
    public void setMessage(String id, Map<String, ?> params) {
        if (isValid()) {
            boolean found = false;

            for (Validator validator : getFieldConfig().getValidators()) {
                if (isEquals(validator.getId(), id)) {
                    MessageContext expressionContext = MessageContextFactory.newInstance(this, validator);
                    expressionContext.putAll(params);
                    valid = false;
                    found = true;
                    message = validator.getMessage(new ValidatorContextImpl(expressionContext, this));

                    if (message == null) {
                        throw new CustomErrorNotFoundException("No message specified for error ID \"" + id + "\" in "
                                + this);
                    }

                    break;
                }
            }

            if (found) {
                ((GroupImpl) getGroup()).setValid(valid);
            } else {
                throw new CustomErrorNotFoundException("Specified error ID \"" + id + "\" was not found in " + this);
            }
        }
    }

    /**
     * ��ʼ��fieldֵ��������֤���ֶΡ����У�<code>request</code>������<code>null</code>��
     */
    public void init(HttpServletRequest request) {
        valid = true;
        attachment = null;

        // requestΪnull����ʾ�ǿձ��������û��ύ�ģ�����ʱװ��Ĭ��ֵ
        if (request == null) {
            setValues(getFieldConfig().getDefaultValues());
        } else {
            ParserRequestContext prc = findRequestContext(request, ParserRequestContext.class);

            // ����������ParserRequestContext����ȡ��objects���Ա�֧��FileItem������ֻ֧���ַ���ֵ��
            if (prc != null) {
                setValues(prc.getParameters().getObjects(getKey()));
            } else {
                setValues(request.getParameterValues(getKey()));
            }

            // ���field�����ڣ�����absent fieldKey��
            if (size() == 0) {
                setValues(request.getParameterValues(getAbsentKey()));
            }

            // �������attachment����װ��֮
            String attachmentEncoded = trimToNull(request.getParameter(getAttachmentKey()));

            if (attachmentEncoded != null) {
                attachment = new Attachment(attachmentEncoded);
            }
        }
    }

    /**
     * ��֤����������֤���ֶΡ�
     */
    protected void validate() {
        valid = true;

        for (Validator validator : getFieldConfig().getValidators()) {
            MessageContext expressionContext = MessageContextFactory.newInstance(this, validator);
            Context context = new ValidatorContextImpl(expressionContext, this);
            boolean passed = validator.validate(context);

            if (!passed) {
                valid = false;
                message = validator.getMessage(context);
                break;
            }
        }

        ((GroupImpl) getGroup()).setValid(valid);
    }

    /**
     * ȡ��field����Ĵ�����Ϣ���ʽ��context��
     */
    protected MessageContext getMessageContext() {
        return messageContext;
    }

    /**
     * ȡ��field name���൱��<code>getFieldConfig().getName()</code>��
     */
    public String getName() {
        return getFieldConfig().getName();
    }

    /**
     * ȡ�ò���ֵ�����ָ�����ƵIJ��������ڣ��򷵻�<code>""</code>��
     */
    @Override
    public String getStringValue() {
        return getStringValue(EMPTY_STRING);
    }

    /**
     * ȡ��������ʾfield�����ƣ��൱��<code>getFieldConfig().getDisplayName()</code>��
     */
    public String getDisplayName() {
        return getFieldConfig().getDisplayName();
    }

    /**
     * ȡ��Ĭ��ֵ���൱��<code>getFieldConfig().getDefaultValue()</code>��
     */
    public String getDefaultValue() {
        return getFieldConfig().getDefaultValue();
    }

    /**
     * ȡ��Ĭ��ֵ���൱��<code>getFieldConfig().getDefaultValues()</code>��
     */
    public String[] getDefaultValues() {
        return getFieldConfig().getDefaultValues();
    }

    /**
     * ��Ӳ�����/����ֵ��
     */
    @Override
    public void addValue(Object value) {
        if (getFieldConfig().isTrimming() && value instanceof String) {
            value = trimToNull((String) value);
        }

        super.addValue(value);
    }

    /**
     * ���ø�����
     */
    public Object getAttachment() {
        return attachment == null ? null : attachment.getAttachment();
    }

    /**
     * ���ñ����ĸ�����
     */
    public String getAttachmentEncoded() {
        return attachment == null ? null : attachment.getAttachmentEncoded();
    }

    /**
     * �Ƿ����������
     */
    public boolean hasAttachment() {
        return attachment != null && attachment.getAttachment() != null;
    }

    /**
     * ���ø�����
     * <p>
     * ע�⣬��attachment�Ѿ�����ʱ���÷���������Ч����ǿ�����룬���ȵ���<code>clearAttachment()</code>��
     * </p>
     */
    public void setAttachment(Object attachment) {
        if (this.attachment == null) {
            this.attachment = new Attachment(attachment);
        }
    }

    /**
     * ���������
     */
    public void clearAttachment() {
        this.attachment = null;
    }

    /**
     * ת���������Ķ����ַ�����
     */
    @Override
    public String toString() {
        return "Field[group: " + getGroup().getGroupConfig().getName() + "." + getGroup().getInstanceKey() + ", name: "
                + getFieldConfig().getName() + ", values: " + ObjectUtil.toString(getValues()) + ", valid: "
                + isValid() + "]";
    }

    /**
     * ����һ��������
     */
    private static class Attachment {
        private Object attachment;
        private String attachmentEncoded;

        public Attachment(Object attachment) {
            setAttachment(attachment);
        }

        public Attachment(String attachmentEncoded) {
            setAttachment(decode(attachmentEncoded));
        }

        public Object getAttachment() {
            return attachment;
        }

        public void setAttachment(Object attachment) {
            this.attachment = attachment;
            this.attachmentEncoded = null;
        }

        public String getAttachmentEncoded() {
            if (attachment != null && attachmentEncoded == null) {
                attachmentEncoded = encode(attachment);
            }

            return attachmentEncoded;
        }

        private String encode(Object attachment) {
            if (attachment == null) {
                return null;
            }

            try {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();

                // 1. ���л�
                // 2. ѹ��
                Deflater def = new Deflater(Deflater.BEST_COMPRESSION, false);
                DeflaterOutputStream dos = new DeflaterOutputStream(baos, def);
                ObjectOutputStream oos = null;

                try {
                    oos = new ObjectOutputStream(dos);
                    oos.writeObject(attachment);
                } finally {
                    if (oos != null) {
                        try {
                            oos.close();
                        } catch (IOException e) {
                        }
                    }

                    def.end();
                }

                byte[] plaintext = baos.toByteArray().toByteArray();

                // 3. base64����
                return StringEscapeUtil.escapeURL(new String(Base64.encodeBase64(plaintext, false), "ISO-8859-1"));
            } catch (Exception e) {
                log.error("Failed to encode field attachment", e);
                return "!Failure: " + e;
            }
        }

        private Object decode(String attachmentEncoded) {
            if (attachmentEncoded == null || attachmentEncoded.startsWith("!Failure:")) {
                return null;
            }

            // 1. base64����
            byte[] plaintext = null;

            try {
                String encoded = StringEscapeUtil.unescapeURL(attachmentEncoded);
                plaintext = Base64.decodeBase64(encoded.getBytes("ISO-8859-1"));

                if (ArrayUtil.isEmptyArray(plaintext)) {
                    log.warn("Field attachment content is empty: " + encoded);
                    return null;
                }
            } catch (Exception e) {
                log.warn("Failed to decode field attachment: " + e);
                return null;
            }

            // 2. ��ѹ��
            ByteArrayInputStream bais = new ByteArrayInputStream(plaintext);
            Inflater inf = new Inflater(false);
            InflaterInputStream iis = new InflaterInputStream(bais, inf);

            // 3. �����л�
            ObjectInputStream ois = null;

            try {
                ois = new ObjectInputStream(iis);
                return ois.readObject();
            } catch (Exception e) {
                log.warn("Failed to parse field attachment", e);
            } finally {
                if (ois != null) {
                    try {
                        ois.close();
                    } catch (IOException e) {
                    }
                }

                inf.end();
            }

            return null;
        }
    }
}
TOP

Related Classes of com.alibaba.citrus.service.form.impl.FieldImpl$Attachment

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.