Package com.alibaba.tamper.core.config.parse

Source Code of com.alibaba.tamper.core.config.parse.BeanMappingParser

package com.alibaba.tamper.core.config.parse;

import java.beans.PropertyDescriptor;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.alibaba.tamper.core.BeanMappingException;
import com.alibaba.tamper.core.config.BeanMappingBehavior;
import com.alibaba.tamper.core.config.BeanMappingConfigHelper;
import com.alibaba.tamper.core.config.BeanMappingField;
import com.alibaba.tamper.core.config.BeanMappingFieldAttributes;
import com.alibaba.tamper.core.config.BeanMappingObject;
import com.alibaba.tamper.core.helper.ReflectionHelper;
import com.alibaba.tamper.core.helper.XmlHelper;

/**
* 解析对应的mapping配置
*
* @author jianghang 2011-5-26 下午07:13:45
*/
public class BeanMappingParser {

    private static final String MAPPING_SCHEMA = "META-INF/mapping.xsd";

    public static List<BeanMappingObject> parseMapping(InputStream in) throws BeanMappingException {
        List<BeanMappingObject> result = parseMappingObject(in);
        List<BeanMappingObject> reseverResult = new ArrayList<BeanMappingObject>(result.size());
        for (BeanMappingObject object : result) {
            if (object.isReversable()) {
                BeanMappingObject reverseObject = reverse(object);
                if (reverseObject != null) {
                    reseverResult.add(reverseObject);
                }
            }
        }
        result.addAll(reseverResult);
        return result;
    }

    // 自动解析下src/target匹配的属性
    public static List<BeanMappingObject> parseMapping(Class src, Class target) throws BeanMappingException {
        List<BeanMappingObject> result = new ArrayList<BeanMappingObject>(2);
        PropertyDescriptor[] targetPds = ReflectionHelper.getPropertyDescriptors(target);
        PropertyDescriptor[] srcPds = ReflectionHelper.getPropertyDescriptors(src);
        BeanMappingObject object = new BeanMappingObject();
        object.setSrcClass(src);
        object.setTargetClass(target);
        object.setBatch(true);
        BeanMappingBehavior globalBehavior = BeanMappingConfigHelper.getInstance().getGlobalBehavior();
        List<BeanMappingField> fields = new ArrayList<BeanMappingField>();
        for (PropertyDescriptor targetPd : targetPds) {
            String property = targetPd.getName();
            PropertyDescriptor srcPd = getMatchPropertyDescriptor(srcPds, property);
            if (srcPd == null) {// 没有匹配属性
                continue;
            }

            if (targetPd.getWriteMethod() != null && srcPd.getReadMethod() != null) {
                BeanMappingField field = new BeanMappingField();
                BeanMappingFieldAttributes srcFieldAttribute = new BeanMappingFieldAttributes();
                srcFieldAttribute.setName(property);
                srcFieldAttribute.setClazz(srcPd.getPropertyType());
                BeanMappingFieldAttributes targetFieldAttribute = new BeanMappingFieldAttributes();
                targetFieldAttribute.setName(property);
                targetFieldAttribute.setClazz(targetPd.getPropertyType());
                // 添加记录
                field.setSrcField(srcFieldAttribute);
                field.setTargetField(targetFieldAttribute);
                field.setBehavior(globalBehavior);
                fields.add(field);
            }

        }
        object.setBeanFields(fields);
        object.setBehavior(globalBehavior);// 设置为global
        result.add(object);
        if (object.isReversable()) {
            BeanMappingObject reverseObject = reverse(object);
            if (reverseObject != null) {
                result.add(reverseObject);
            }
        }
        return result;
    }

    // 解析class的属性为BeanMapping对象
    public static List<BeanMappingObject> parseMapMapping(Class src) throws BeanMappingException {
        List<BeanMappingObject> result = new ArrayList<BeanMappingObject>(2);
        PropertyDescriptor[] targetPds = ReflectionHelper.getPropertyDescriptors(src);
        BeanMappingObject object = new BeanMappingObject();
        object.setSrcClass(src);
        object.setTargetClass(Map.class); // 设置为map接口
        object.setBatch(true);
        List<BeanMappingField> fields = new ArrayList<BeanMappingField>();
        BeanMappingBehavior globalBehavior = BeanMappingConfigHelper.getInstance().getGlobalBehavior();
        for (PropertyDescriptor targetPd : targetPds) {
            if (targetPd.getWriteMethod() != null && targetPd.getReadMethod() != null) {
                BeanMappingField field = new BeanMappingField();
                BeanMappingFieldAttributes srcFieldAttribute = new BeanMappingFieldAttributes();
                srcFieldAttribute.setName(targetPd.getName());
                srcFieldAttribute.setClazz(targetPd.getPropertyType());
                BeanMappingFieldAttributes targetFieldAttribute = new BeanMappingFieldAttributes();
                targetFieldAttribute.setName(targetPd.getName());
                targetFieldAttribute.setClazz(targetPd.getPropertyType());
                field.setSrcField(srcFieldAttribute);
                field.setTargetField(targetFieldAttribute);
                field.setBehavior(globalBehavior);// 设置为global
                fields.add(field);
            }
        }
        object.setBeanFields(fields);
        object.setBehavior(globalBehavior);// 设置为global
        result.add(object);
        if (object.isReversable()) {
            BeanMappingObject reverseObject = reverse(object);
            if (reverseObject != null) {
                result.add(reverseObject);
            }
        }
        return result;
    }

    // 反转处理BeanMappingObject对象
    private static BeanMappingObject reverse(BeanMappingObject object) {
        BeanMappingObject newObject = new BeanMappingObject();
        // 反转一下属性,主要是一些srcName,srcClass等
        newObject.setSrcClass(object.getTargetClass());
        newObject.setTargetClass(object.getSrcClass());
        newObject.setReversable(object.isReversable());
        newObject.setBatch(object.isBatch());
        newObject.setSrcKey(object.getSrcKey());
        newObject.setTargetKey(object.getTargetKey());
        newObject.setBehavior(object.getBehavior());
        List<BeanMappingField> fields = newObject.getBeanFields();
        for (BeanMappingField field : object.getBeanFields()) {
            // 倒转一下
            BeanMappingField newField = new BeanMappingField();
            BeanMappingFieldAttributes srcFieldAttribute = new BeanMappingFieldAttributes();
            srcFieldAttribute.setName(field.getTargetField().getName());
            srcFieldAttribute.setClazz(field.getTargetField().getClazz());
            BeanMappingFieldAttributes targetFieldAttribute = new BeanMappingFieldAttributes();
            targetFieldAttribute.setName(field.getSrcField().getName());
            targetFieldAttribute.setClazz(field.getSrcField().getClazz());

            newField.setSrcField(srcFieldAttribute);
            newField.setTargetField(targetFieldAttribute);
            newField.setDefaultValue(field.getDefaultValue());
            newField.setMapping(field.isMapping());
            newField.setBehavior(field.getBehavior());
            if (StringUtils.isNotEmpty(field.getConvertor()) || StringUtils.isNotEmpty(field.getScript())) {
                object.setReversable(false);// 强制设置为false
                return null;
            }
            fields.add(newField);
        }
        return newObject;
    }

    // 根据属性名获取一下匹配的PropertyDescriptor
    private static PropertyDescriptor getMatchPropertyDescriptor(PropertyDescriptor[] srcPds, String property) {
        for (PropertyDescriptor srcPd : srcPds) {
            if (srcPd.getName().equals(property)) {
                return srcPd;
            }
        }

        return null;
    }

    // 解析一下bean-mapping
    private static List<BeanMappingObject> parseMappingObject(InputStream in) {
        Document doc = XmlHelper.createDocument(
                                                in,
                                                Thread.currentThread().getContextClassLoader().getResourceAsStream(
                                                                                                                   MAPPING_SCHEMA));
        Element root = doc.getDocumentElement();

        NodeList globalNodeList = root.getElementsByTagName("global-configurations");
        if (globalNodeList.getLength() > 1) {
            throw new BeanMappingException("global-configurations is exceed one node!");
        }

        BeanMappingBehavior globalBehavior = BeanMappingConfigHelper.getInstance().getGlobalBehavior();
        if (globalNodeList.getLength() == 1) {
            globalBehavior = BeanMappingBehaviorParse.parse(globalNodeList.item(0), globalBehavior);
            BeanMappingConfigHelper.getInstance().setGlobalBehavior(globalBehavior);
        }

        NodeList classAliasNodeList = root.getElementsByTagName("class-alias-configurations");
        for (int i = 0; i < classAliasNodeList.getLength(); i++) {
            ClassAliasParse.parseAndRegister(classAliasNodeList.item(i));
        }

        NodeList convertorNodeList = root.getElementsByTagName("convertors-configurations");
        for (int i = 0; i < convertorNodeList.getLength(); i++) {
            ConvertorParse.parseAndRegister(convertorNodeList.item(i));
        }

        NodeList functionClassNodeList = root.getElementsByTagName("function-class-configurations");
        for (int i = 0; i < functionClassNodeList.getLength(); i++) {
            FunctionClassParse.parseAndRegister(functionClassNodeList.item(i));
        }

        NodeList nodeList = root.getElementsByTagName("bean-mapping");
        List<BeanMappingObject> mappings = new ArrayList<BeanMappingObject>();
        // 解析BeanMappingObject属性
        for (int i = 0; i < nodeList.getLength(); i++) {
            BeanMappingObject config = BeanMappingParse.parse(nodeList.item(i), globalBehavior);
            // 添加到返回结果
            mappings.add(config);
        }

        return mappings;
    }

}
TOP

Related Classes of com.alibaba.tamper.core.config.parse.BeanMappingParser

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.