Package com.alibaba.citrus.springext.impl

Source Code of com.alibaba.citrus.springext.impl.SchemaBase

/*
* 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.springext.impl;

import static com.alibaba.citrus.springext.support.SchemaUtil.*;
import static com.alibaba.citrus.util.Assert.*;
import static com.alibaba.citrus.util.CollectionUtil.*;

import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;

import com.alibaba.citrus.springext.ConfigurationPointException;
import com.alibaba.citrus.springext.Schema;
import com.alibaba.citrus.util.io.ByteArrayInputStream;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.InputStreamSource;

/**
* 这是schema的基类,实现了schema生命周期中的几个步骤:
* <ol>
* <li>Parse - 将originalSource读出来,生成document文档。这一步可以被跳过,例如configuration point schema文档是直接在内存中创建的,所以不经过这一步。</li>
* <li>Transform - 将document文档进行转换、修改。这一步可进行多次,且真正的转换会被延迟到要用到时,才进行。</li>
* <li>Analyze - 分析document的内容,取得其中的信息。例如取得targetNamespace等。</li>
* <li>Serialize - 将document转换回二进制流,以供外部程序读取。例如,供给schema exporter生成schema文件,或者供给resolver来验证SpringExt配置文件。
* 每一次transform以后,需要重新进行serialize操作,以便反映最新的修改。</li>
* </ol>
*
* @author Michael Zhou
*/
public abstract class SchemaBase implements Schema {
    protected final static Logger log = LoggerFactory.getLogger(Schema.class);
    private final InputStreamSource originalSource;

    private Document document;
    private boolean  parsed;

    private final LinkedList<Transformer> transformersQueue = createLinkedList();
    private byte[]  transformedData;
    private boolean everTransformed;

    private boolean analyzed;

    public SchemaBase(InputStreamSource originalSource) {
        this(originalSource, null, true);
    }

    public SchemaBase(Document originalDocument) {
        this(null, originalDocument, false);
    }

    protected SchemaBase(InputStreamSource originalSource, Document originalDocument, boolean isInputStreamSource) {
        if (isInputStreamSource) {
            this.originalSource = assertNotNull(originalSource, "no InputStreamSource provided");
        } else {
            this.originalSource = null;
            this.document = assertNotNull(originalDocument, "no Document provided");
            this.parsed = true;
        }
    }

    public final void transform(Transformer transformer) {
        transform(transformer, false);
    }

    public final void transform(Transformer transformer, boolean doNow) {
        transformersQueue.addLast(assertNotNull(transformer, "no Transformer provided"));

        if (doNow) {
            transform();
        }
    }

    public final Document getDocument() {
        parse();
        transform();
        return document;
    }

    public final InputStream getInputStream() {
        serialize();

        if (transformedData != null) {
            return new ByteArrayInputStream(transformedData);
        }

        if (originalSource != null) {
            return getOriginalInputStream();
        } else {
            fail("Found a BUG: OriginalSource can't be null here");
            return null;
        }
    }

    private void serialize() {
        transform();

        if (transformedData == null && document != null && (everTransformed || originalSource == null)) {
            transformedData = getDocumentContent(document);
        }
    }

    private void transform() {
        if (!transformersQueue.isEmpty()) {
            parse();

            transformedData = null;
            everTransformed = true;

            while (!transformersQueue.isEmpty()) {
                Transformer transformer = transformersQueue.removeFirst();

                // 有可能因格式非法,不能生成document文件(document==null)。忽略这种情况。
                if (document != null) {
                    transformer.transform(document, getName());
                }
            }
        }
    }

    private void parse() {
        if (!parsed) {
            parsed = true;

            try {
                document = readDocument(getOriginalInputStream(), getName(), true);
            } catch (DocumentException e) {
                log.warn("Not a valid XML doc: {}, source={},\n{}", new Object[] { getName(), originalSource, e.getMessage() });
                document = null;
            }
        }
    }

    private InputStream getOriginalInputStream() {
        try {
            return originalSource.getInputStream();
        } catch (IOException e) {
            throw new ConfigurationPointException("Failed to read text of schema file: " + getName() + ", source=" + originalSource, e);
        }
    }

    protected final void analyze() {
        if (!analyzed) {
            analyzed = true;

            parse();
            transform();

            if (document != null) {
                doAnalyze();
            }
        }
    }

    protected abstract void doAnalyze();

    @Override
    public String toString() {
        if (originalSource != null) {
            return originalSource.toString();
        } else {
            return "generated-content";
        }
    }
}
TOP

Related Classes of com.alibaba.citrus.springext.impl.SchemaBase

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.