/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2003 The Apache Software Foundation.  All rights 
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer. 
*
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in
*    the documentation and/or other materials provided with the
*    distribution.
*
* 3. The end-user documentation included with the redistribution,
*    if any, must include the following acknowledgment:  
*       "This product includes software developed by the
*        Apache Software Foundation (http://www.apache.org/)."
*    Alternately, this acknowledgment may appear in the software itself,
*    if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must 
*    not be used to endorse or promote products derived from this
*    software without prior written permission. For written 
*    permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache 
*    XMLBeans", nor may "Apache" appear in their name, without prior 
*    written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 2000-2003 BEA Systems 
* Inc., <http://www.bea.com/>. For more information on the Apache Software
* Foundation, please see <http://www.apache.org/>.
*/

package org.apache.xmlbeans.impl.tool;

import org.apache.xmlbeans.SchemaTypeLoader;
import org.apache.xmlbeans.XmlBeans;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.SchemaTypeSystem;
import org.apache.xmlbeans.XmlException;

import java.util.Collection;
import java.util.ArrayList;
import java.util.Collections;
import java.io.PrintWriter;
import java.io.StringWriter;

public class XMLBeanXSTCHarness implements XSTCTester.Harness
{
    public void runTestCase(XSTCTester.TestCaseResult result)
    {
        XSTCTester.TestCase testCase = result.getTestCase();
        
        // System.out.println("Running case " + testCase.getDescription());
        
        try
        {
            Collection errors = new ArrayList();
            boolean schemaValid = true;
            boolean instanceValid = true;
            
            if (testCase.getSchemaFile() == null)
                return;
            
            // step 1, load schema file etc.
            SchemaTypeLoader loader = null;
            try
            {
                XmlObject schema = XmlObject.Factory.parse(testCase.getSchemaFile(), new XmlOptions().setErrorListener(errors).setLoadLineNumbers());
                XmlObject schema2 = null;
                if (testCase.getResourceFile() != null)
                    schema2 = XmlObject.Factory.parse(testCase.getResourceFile(), new XmlOptions().setErrorListener(errors).setLoadLineNumbers());
                XmlObject[] schemas = schema2 == null ? new XmlObject[] { schema } : new XmlObject[] { schema, schema2 };
                SchemaTypeSystem system = XmlBeans.compileXsd(schemas, XmlBeans.getBuiltinTypeSystem(), new XmlOptions().setErrorListener(errors));
                loader = XmlBeans.typeLoaderUnion(new SchemaTypeLoader[] { system, XmlBeans.getBuiltinTypeSystem() });
            }
            catch (Exception e)
            {
                schemaValid = false;
                if (!(e instanceof XmlException) || errors.isEmpty())
                {
                    result.setCrash(true);
                    StringWriter sw = new StringWriter();
                    e.printStackTrace(new PrintWriter(sw));
                    result.addSvMessages(Collections.singleton(sw.toString()));
                }
            }
            
            result.addSvMessages(errors);
            result.setSvActual(schemaValid);
            errors.clear();
            
            if (loader == null)
                return;
            
            if (testCase.getInstanceFile() == null)
                return;
            
            // step 2, load instance file and validate
            try
            {
                XmlObject instance = loader.parse(testCase.getInstanceFile(), null, new XmlOptions().setErrorListener(errors).setLoadLineNumbers());
                if (!instance.validate(new XmlOptions().setErrorListener(errors)))
                    instanceValid = false;
            }
            catch (Exception e)
            {
                instanceValid = false;
                if (!(e instanceof XmlException) || errors.isEmpty())
                {
                    result.setCrash(true);
                    StringWriter sw = new StringWriter();
                    e.printStackTrace(new PrintWriter(sw));
                    result.addIvMessages(Collections.singleton(sw.toString()));
                }
            }
            result.addIvMessages(errors);
            result.setIvActual(instanceValid);
                    
        }
        finally
        {
            // System.out.println(result.succeeded() ? "Success.": "Failure.");
        }
    }
}
