/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

/* $Id$ */

package org.apache.fop.fo;

import org.xml.sax.Locator;

import org.apache.xmlgraphics.util.QName;

import org.apache.fop.apps.FOPException;
import org.apache.fop.events.EventBroadcaster;
import org.apache.fop.events.EventProducer;
import org.apache.fop.fo.expr.PropertyException;

/**
 * Event producer interface for XSL-FO validation messages.
 */
public interface FOValidationEventProducer extends EventProducer {

    /**
     * Provider class for the event producer.
     */
    final class Provider {

        private Provider() { }

        /**
         * Returns an event producer.
         * @param broadcaster the event broadcaster to use
         * @return the event producer
         */
        public static FOValidationEventProducer get(EventBroadcaster broadcaster) {
            return broadcaster.getEventProducerFor(FOValidationEventProducer.class);
        }
    }

    /**
     * Too many child nodes.
     * @param source the event source
     * @param elementName the name of the context node
     * @param offendingNode the offending node
     * @param loc the location of the error or null
     * @throws ValidationException the validation error provoked by the method call
     * @event.severity FATAL
     */
    void tooManyNodes(Object source, String elementName, QName offendingNode,
            Locator loc) throws ValidationException;

    /**
     * The node order is wrong.
     * @param source the event source
     * @param elementName the name of the context node
     * @param tooLateNode string name of node that should be earlier in document
     * @param tooEarlyNode string name of node that should be later in document
     * @param canRecover indicates whether FOP can recover from this problem and continue working
     * @param loc the location of the error or null
     * @throws ValidationException the validation error provoked by the method call
     */
    void nodeOutOfOrder(Object source, String elementName,
            String tooLateNode, String tooEarlyNode, boolean canRecover,
            Locator loc) throws ValidationException;

    /**
     * An invalid child was encountered.
     * @param source the event source
     * @param elementName the name of the context node
     * @param offendingNode the offending node
     * @param ruleViolated the rule that was violated or null
     * @param loc the location of the error or null
     * @throws ValidationException the validation error provoked by the method call
     */
    void invalidChild(Object source, String elementName, QName offendingNode, String ruleViolated,
            Locator loc) throws ValidationException;

    /**
     * A valid but not yet supported child was encountered.
     *
     * @param source the event source
     * @param elementName the name of the context node
     * @param offendingNode the offending node
     * @param loc the location of the error or null
     * @throws ValidationException the validation error provoked by the method call
     */
    void notSupportedChild(Object source, String elementName, QName offendingNode, Locator loc)
            throws ValidationException;

    /**
     * A required child element is missing.
     * @param source the event source
     * @param elementName the name of the context node
     * @param contentModel the expected content model
     * @param canRecover indicates whether FOP can recover from this problem and continue working
     * @param loc the location of the error or null
     * @throws ValidationException the validation error provoked by the method call
     * @event.severity FATAL
     */
    void missingChildElement(Object source, String elementName,
            String contentModel, boolean canRecover,
            Locator loc) throws ValidationException;

    /**
     * An element is missing a required property.
     * @param source the event source
     * @param elementName the name of the context node
     * @param propertyName the name of the missing property
     * @param loc the location of the error or null
     * @throws ValidationException the validation error provoked by the method call
     * @event.severity FATAL
     */
    void missingProperty(Object source, String elementName, String propertyName,
            Locator loc) throws ValidationException;

    /**
     * An id was used twice in a document.
     * @param source the event source
     * @param elementName the name of the context node
     * @param id the id that was reused
     * @param canRecover indicates whether FOP can recover from this problem and continue working
     * @param loc the location of the error or null
     * @throws ValidationException the validation error provoked by the method call
     * @event.severity FATAL
     */
    void idNotUnique(Object source, String elementName, String id, boolean canRecover,
            Locator loc) throws ValidationException;

    /**
     * There are multiple color profiles defined with the same name.
     * @param source the event source
     * @param elementName the name of the context node
     * @param name the duplicate color profile name
     * @param loc the location of the error or null
     * @event.severity WARN
     */
    void colorProfileNameNotUnique(Object source, String elementName, String name,
            Locator loc);

    /**
     * There are multiple page masters defined with the same name.
     * @param source the event source
     * @param elementName the name of the context node
     * @param name the duplicate page master name
     * @param loc the location of the error or null
     * @throws ValidationException the validation error provoked by the method call
     * @event.severity FATAL
     */
    void masterNameNotUnique(Object source, String elementName, String name,
            Locator loc) throws ValidationException;

    /**
     * An fo:marker appears as initial descendant in an fo:block-container
     * that generates absolutely positioned areas
     * @param source    the event source
     * @param loc       the location of the error (possibly null)
     * @event.severity ERROR
     */
    void markerBlockContainerAbsolutePosition(Object source, Locator loc);

    /**
     * A marker is not an initial child on a node.
     * @param source the event source
     * @param elementName the name of the context node
     * @param mcname the marker class name
     * @param loc the location of the error or null
     * @event.severity ERROR
     */
    void markerNotInitialChild(Object source, String elementName, String mcname, Locator loc);

    /**
     * A marker class name is not unique within the same parent.
     * @param source the event source
     * @param elementName the name of the context node
     * @param mcname the marker class name
     * @param loc the location of the error or null
     * @event.severity ERROR
     */
    void markerNotUniqueForSameParent(Object source, String elementName,
            String mcname, Locator loc);

    /**
     * An invalid property was found.
     * @param source the event source
     * @param elementName the name of the context node
     * @param attr the invalid attribute
     * @param canRecover indicates whether FOP can recover from this problem and continue working
     * @param loc the location of the error or null
     * @throws ValidationException the validation error provoked by the method call
     * @event.severity FATAL
     */
    void invalidProperty(Object source, String elementName, QName attr, boolean canRecover,
            Locator loc) throws ValidationException;

    /**
     * An invalid property value was encountered.
     * @param source the event source
     * @param elementName the name of the context node
     * @param propName the property name
     * @param propValue the property value
     * @param e the property exception caused by the invalid value
     * @param loc the location of the error or null
     * @event.severity ERROR
     */
    void invalidPropertyValue(Object source, String elementName,
            String propName, String propValue, PropertyException e,
            Locator loc);

    /**
     * An invalid property value was encountered.
     * @param source the event source
     * @param elementName the name of the context node
     * @param propName the property name
     * @param propValue the property value
     * @param e the property exception caused by the invalid value
     * @param loc the location of the error or null
     * @event.severity WARN
     */
    void warnOnInvalidPropertyValue(Object source, String elementName,
            String propName, String propValue, PropertyException e,
            Locator loc);

    /**
     * A feature is not supported, yet.
     * @param source the event source
     * @param elementName the name of the context node
     * @param feature the unsupported feature
     * @param loc the location of the error or null
     * @event.severity WARN
     */
    void unimplementedFeature(Object source, String elementName, String feature,
            Locator loc);

    /**
     * Missing internal-/external-destination on basic-link or bookmark.
     * @param source the event source
     * @param elementName the name of the context node
     * @param loc the location of the error or null
     * @throws ValidationException the validation error provoked by the method call
     * @event.severity FATAL
     */
    void missingLinkDestination(Object source, String elementName, Locator loc)
                throws ValidationException;

    /**
     * Indicates a problem while cloning a marker (ex. due to invalid property values).
     * @param source the event source
     * @param markerClassName the "marker-class-name" of the marker
     * @param fe the FOP exception that cause this problem
     * @param loc the location of the error or null
     * @event.severity ERROR
     */
    void markerCloningFailed(Object source, String markerClassName, FOPException fe, Locator loc);

    /**
     * A region name is mapped to multiple region classes.
     * @param source the event source
     * @param regionName the region name
     * @param defaultRegionClass1 the first default region class
     * @param defaultRegionClass2 the second default region class
     * @param loc the location of the error or null
     * @throws ValidationException the validation error provoked by the method call
     * @event.severity FATAL
     */
    void regionNameMappedToMultipleRegionClasses(Object source, String regionName,
            String defaultRegionClass1, String defaultRegionClass2, Locator loc)
                throws ValidationException;

    /**
     * There are multiple flows with the same name.
     * @param source the event source
     * @param elementName the name of the context node
     * @param flowName the flow name
     * @param loc the location of the error or null
     * @throws ValidationException the validation error provoked by the method call
     * @event.severity FATAL
     */
    void duplicateFlowNameInPageSequence(Object source, String elementName, String flowName,
            Locator loc) throws ValidationException;

    /**
     * A flow name could not be mapped to a region.
     * @param source the event source
     * @param elementName the name of the context node
     * @param flowName the flow name
     * @param loc the location of the error or null
     * @throws ValidationException the validation error provoked by the method call
     * @event.severity FATAL
     */
    void flowNameNotMapped(Object source, String elementName, String flowName,
            Locator loc) throws ValidationException;

    /**
     * A page master could not be found.
     * @param source the event source
     * @param elementName the name of the context node
     * @param masterReference the page master reference
     * @param loc the location of the error or null
     * @throws ValidationException the validation error provoked by the method call
     * @event.severity FATAL
     */
    void masterNotFound(Object source, String elementName, String masterReference,
            Locator loc) throws ValidationException;

    /**
     * An illegal region name was used.
     * @param source the event source
     * @param elementName the name of the context node
     * @param regionName the region name
     * @param loc the location of the error or null
     * @throws ValidationException the validation error provoked by the method call
     * @event.severity FATAL
     */
    void illegalRegionName(Object source, String elementName, String regionName,
            Locator loc) throws ValidationException;

    /**
     * A non-zero border and/or padding has been encountered on a region.
     * @param source the event source
     * @param elementName the name of the context node
     * @param regionName the region name
     * @param canRecover indicates whether FOP can recover from this problem and continue working
     * @param loc the location of the error or null
     * @throws ValidationException the validation error provoked by the method call
     * @event.severity FATAL
     */
    void nonZeroBorderPaddingOnRegion(Object source, String elementName, String regionName,
            boolean canRecover, Locator loc) throws ValidationException;

    /**
     * If overflow property is set to "scroll", a column-count other than "1" may not be specified.
     * @param source the event source
     * @param elementName the name of the context node
     * @param loc the location of the error or null
     * @throws ValidationException the validation error provoked by the method call
     * @event.severity FATAL
     */
    void columnCountErrorOnRegionBodyOverflowScroll(Object source, String elementName,
            Locator loc) throws ValidationException;

    /**
     * fo:root must be root.
     * @param source the event source
     * @param elementName the name of the context node
     * @param loc the location of the error or null
     * @throws ValidationException the validation error provoked by the method call
     * @event.severity FATAL
     */
    void invalidFORoot(Object source, String elementName,
            Locator loc) throws ValidationException;

    /**
     * No FO document was found.
     * @param source the event source
     * @throws ValidationException the validation error provoked by the method call
     * @event.severity FATAL
     */
    void emptyDocument(Object source) throws ValidationException;

    /**
     * An unknown/unsupported formatting object has been encountered.
     * @param source the event source
     * @param elementName the name of the context node
     * @param offendingNode the offending node
     * @param loc the location of the error or null
     * @event.severity WARN
     */
    void unknownFormattingObject(Object source, String elementName,
            QName offendingNode, Locator loc);

    /**
     * A class for change bars is not unique.
     * @param source the event source
     * @param elementName the name of the context node
     * @param name the class name
     * @param loc the location of the error or null
     * @event.severity FATAL
     */
    void changeBarClassNotUnique(Object source, String elementName, String name,
            Locator loc);

    /**
     * Change bars were not stacked correctly
     * @param source the event source
     * @param elementName the name of the context node
     * @param beginName the class name of the beginning change bar
     * @param endName the class name of the ending change bar
     * @param loc the location of the error or null
     * @event.severity FATAL
     */
    void changeBarWrongStacking(Object source, String elementName, String beginName,
            String endName, Locator loc);

    /**
     * Change bar ended without a start of bar occurred
     * @param source the event source
     * @param elementName the name of the context node
     * @param loc the location of the error or null
     * @event.severity FATAL
     */
    void changeBarNoBegin(Object source, String elementName, Locator loc);

    /**
     * Change bar not descendant of fo:flow or fo:static-content
     * @param source the event source
     * @param elementName the name of the context node
     * @param loc the location of the error or null
     * @event.severity FATAL
     */
    void changeBarWrongAncestor(Object source, String elementName, Locator loc);

    /**
     * Alternate text is missing for a graphic element.
     *
     * @param source the event source
     * @param foElement name of the element (external-graphic or instream-foreign-object)
     * @param loc the location of the error or null
     * @event.severity WARN
     */
    void altTextMissing(Object source, String foElement, Locator loc);
}
