/*
 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.xml.internal.bind.v2.runtime.unmarshaller;

import java.util.Collection;
import java.util.Collections;

import javax.xml.bind.Unmarshaller;
import javax.xml.bind.ValidationEvent;
import javax.xml.bind.helpers.ValidationEventImpl;
import javax.xml.namespace.QName;

import com.sun.xml.internal.bind.v2.runtime.JaxBeanInfo;

import org.xml.sax.SAXException;

/**
 * @author Kohsuke Kawaguchi
 */
public abstract class Loader {

    // allow derived classes to change it later
    protected boolean expectText;

    protected Loader(boolean expectText) {
        this.expectText = expectText;
    }

    protected Loader() {
    }

//
//
//
// Contract
//
//
//
    /**
     * Called when the loader is activated, which is when a new start tag is seen
     * and when the parent designated this loader as the child loader.
     *
     * <p>
     * The callee may change <tt>state.loader</tt> to designate another {@link Loader}
     * for the processing. It's the responsibility of the callee to forward the startElement
     * event in such a case.
     *
     * @param ea
     *      info about the start tag. never null.
     */
    public void startElement(UnmarshallingContext.State state,TagName ea) throws SAXException {
    }

    /**
     * Called when this loaderis an active loaderand we see a new child start tag.
     *
     * <p>
     * The callee is expected to designate another loaderas a loaderthat processes
     * this element, then it should also register a {@link Receiver}.
     * The designated loaderwill become an active loader.
     *
     * <p>
     * The default implementation reports an error saying an element is unexpected.
     */
    public void childElement(UnmarshallingContext.State state, TagName ea) throws SAXException {
        // notify the error, then recover by ignoring the whole element.
        reportUnexpectedChildElement(ea, true);
        state.setLoader(Discarder.INSTANCE);
        state.setReceiver(null);
    }

    @SuppressWarnings({"StringEquality"})
    protected final void reportUnexpectedChildElement(TagName ea, boolean canRecover) throws SAXException {
        if (canRecover) {
            // this error happens particurly often (when input documents contain a lot of unexpected elements to be ignored),
            // so don't bother computing all the messages and etc if we know that
            // there's no event handler to receive the error in the end. See #286
            UnmarshallingContext context = UnmarshallingContext.getInstance();
            if (!context.parent.hasEventHandler() // is somebody listening?
                    || !context.shouldErrorBeReported()) // should we report error?
                return;
        }
        if(ea.uri!=ea.uri.intern() || ea.local!=ea.local.intern())
            reportError(Messages.UNINTERNED_STRINGS.format(), canRecover );
        else
            reportError(Messages.UNEXPECTED_ELEMENT.format(ea.uri,ea.local,computeExpectedElements()), canRecover );
    }

    /**
     * Returns a set of tag names expected as possible child elements in this context.
     */
    public Collection<QName> getExpectedChildElements() {
        return Collections.emptyList();
    }

    /**
     * Returns a set of tag names expected as possible child elements in this context.
     */
    public Collection<QName> getExpectedAttributes() {
        return Collections.emptyList();
    }

    /**
     * Called when this loaderis an active loaderand we see a chunk of text.
     *
     * The runtime makes sure that adjacent characters (even those separated
     * by comments, PIs, etc) are reported as one event.
     * IOW, you won't see two text event calls in a row.
     */
    public void text(UnmarshallingContext.State state, CharSequence text) throws SAXException {
        // make str printable
        text = text.toString().replace('\r',' ').replace('\n',' ').replace('\t',' ').trim();
        reportError(Messages.UNEXPECTED_TEXT.format(text), true );
    }

    /**
     * True if this loader expects the {@link #text(UnmarshallingContext.State, CharSequence)} method
     * to be called. False otherwise.
     */
    public final boolean expectText() {
        return expectText;
    }


    /**
     * Called when this loaderis an active loaderand we see an end tag.
     */
    public void leaveElement(UnmarshallingContext.State state, TagName ea) throws SAXException {
    }










//
//
//
// utility methods
//
//
//
    /**
     * Computes the names of possible root elements for a better error diagnosis.
     */
    private String computeExpectedElements() {
        StringBuilder r = new StringBuilder();

        for( QName n : getExpectedChildElements() ) {
            if(r.length()!=0)   r.append(',');
            r.append("<{").append(n.getNamespaceURI()).append('}').append(n.getLocalPart()).append('>');
        }
        if(r.length()==0) {
            return "(none)";
        }

        return r.toString();
    }

    /**
     * Fires the beforeUnmarshal event if necessary.
     *
     * @param state
     *      state of the newly create child object.
     */
    protected final void fireBeforeUnmarshal(JaxBeanInfo beanInfo, Object child, UnmarshallingContext.State state) throws SAXException {
        if(beanInfo.lookForLifecycleMethods()) {
            UnmarshallingContext context = state.getContext();
            Unmarshaller.Listener listener = context.parent.getListener();
            if(beanInfo.hasBeforeUnmarshalMethod()) {
                beanInfo.invokeBeforeUnmarshalMethod(context.parent, child, state.getPrev().getTarget());
            }
            if(listener!=null) {
                listener.beforeUnmarshal(child, state.getPrev().getTarget());
            }
        }
    }

    /**
     * Fires the afterUnmarshal event if necessary.
     *
     * @param state
     *      state of the parent object
     */
    protected final void fireAfterUnmarshal(JaxBeanInfo beanInfo, Object child, UnmarshallingContext.State state) throws SAXException {
        // fire the event callback
        if(beanInfo.lookForLifecycleMethods()) {
            UnmarshallingContext context = state.getContext();
            Unmarshaller.Listener listener = context.parent.getListener();
            if(beanInfo.hasAfterUnmarshalMethod()) {
                beanInfo.invokeAfterUnmarshalMethod(context.parent, child, state.getTarget());
            }
            if(listener!=null)
                listener.afterUnmarshal(child, state.getTarget());
        }
    }


    /**
     * Last resort when something goes terribly wrong within the unmarshaller.
     */
    protected static void handleGenericException(Exception e) throws SAXException {
        handleGenericException(e,false);
    }

    public static void handleGenericException(Exception e, boolean canRecover) throws SAXException {
        reportError(e.getMessage(), e, canRecover );
    }

    public static void handleGenericError(Error e) throws SAXException {
        reportError(e.getMessage(), false);
    }

    protected static void reportError(String msg, boolean canRecover) throws SAXException {
        reportError(msg, null, canRecover );
    }

    public static void reportError(String msg, Exception nested, boolean canRecover) throws SAXException {
        UnmarshallingContext context = UnmarshallingContext.getInstance();
        context.handleEvent( new ValidationEventImpl(
            canRecover? ValidationEvent.ERROR : ValidationEvent.FATAL_ERROR,
            msg,
            context.getLocator().getLocation(),
            nested ), canRecover );
    }

    /**
     * This method is called by the generated derived class
     * when a datatype parse method throws an exception.
     */
    protected static void handleParseConversionException(UnmarshallingContext.State state, Exception e) throws SAXException {
        // wrap it into a ParseConversionEvent and report it
        state.getContext().handleError(e);
    }
}
