/*   Copyright 2004 The Apache Software Foundation
 *
 *   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 org.apache.xmlbeans.impl.common;

import org.apache.xmlbeans.impl.common.ValidatorListener.Event;
import javax.xml.namespace.QName;
import org.apache.xmlbeans.*;
import java.util.*;

/**
 * Identity constraint engine. Performs streaming validation of identity constraints.
 * This includes key, keyref, & unique, as well as ID & IDRef.
 */
public class IdentityConstraint {

    private ConstraintState _constraintStack;
    private ElementState _elementStack;
    private Collection _errorListener;
    private boolean _invalid;
    private boolean _trackIdrefs; // We only track idrefs if validating from the root element

    public IdentityConstraint(Collection  errorListener, boolean trackIdrefs) {
        _errorListener = errorListener;
        _trackIdrefs = trackIdrefs;
    }

    public void element(Event e, SchemaType st, SchemaIdentityConstraint[] ics) {

        // Construct a new state for the element
        newState();

        // First dispatch this element event
        for (ConstraintState cs = _constraintStack ; cs != null ; cs = cs._next)
            cs.element(e, st);

        // Create a new SelectorState for each new Identity Constraint

        for (int i = 0 ; ics != null && i < ics.length ; i++)
            newConstraintState(ics[i], e, st);
    }

    public void endElement(Event e) {
        // Pop the element state stack and any constraints at this depth
        if (_elementStack._hasConstraints)
        {
            for (ConstraintState cs = _constraintStack ; cs != null && cs != _elementStack._savePoint ; cs = cs._next)
                cs.remove( e );

            _constraintStack = _elementStack._savePoint;
        }

        _elementStack = _elementStack._next;

        // Dispatch the event
        for (ConstraintState cs = _constraintStack ; cs != null ; cs = cs._next)
            cs.endElement(e);

    }

    public void attr(Event e, QName name, SchemaType st, String value) {
        for (ConstraintState cs = _constraintStack ; cs != null ; cs = cs._next)
            cs.attr(e, name, st, value);
    }

    public void text(Event e, SchemaType st, String value, boolean emptyContent) {
        for (ConstraintState cs = _constraintStack ; cs != null ; cs = cs._next)
            cs.text(e, st, value, emptyContent);
    }

    public boolean isValid() {
        return !_invalid;
    }

    private void newConstraintState(SchemaIdentityConstraint ic, Event e, SchemaType st)
    {
        if (ic.getConstraintCategory() == SchemaIdentityConstraint.CC_KEYREF)
            new KeyrefState(ic, e, st);
        else
            new SelectorState(ic, e, st);
    }

    private void buildIdStates()
    {
        // Construct states to hold the values for IDs and IDRefs
        IdState ids = new IdState();
        if (_trackIdrefs)
            new IdRefState(ids);
    }

    private void newState() {
        boolean firstTime = _elementStack == null;

        ElementState st = new ElementState();
        st._next = _elementStack;
        _elementStack = st;

        if (firstTime)
            buildIdStates();
    }

    private void emitError ( Event event, String msg )
    {
        _invalid = true;

        if (_errorListener != null)
        {
            assert event != null;
            
            _errorListener.add(
                XmlError.forCursor( msg, event.getLocationAsCursor() ) );
        }
    }

    private void setSavePoint( ConstraintState cs )
    {
        if (! _elementStack._hasConstraints)
            _elementStack._savePoint = cs;

        _elementStack._hasConstraints = true;
    }

    private static XmlObject newValue(SchemaType st, String value)
    {
        try {
            return st.newValue(value);
        }
        catch (IllegalArgumentException e) {
            // This is a bit hacky. newValue throws XmlValueOutOfRangeException which is 
            // unchecked and declared in typeimpl. I can only catch its parent class, 
            // typeimpl is built after common.

            // Ignore these exceptions. Assume that validation will catch them.
            return null;
        }
    }

    /**
     * Return the simple type for schema type. If the schema type is already
     * simple, just return it. If it is a complex type with simple content,
     * return the simple type it extends.
     */
    static SchemaType getSimpleType(SchemaType st) 
    {
        assert st.isSimpleType() || st.getContentType() == SchemaType.SIMPLE_CONTENT : 
            st + " does not have simple content.";

        while (! st.isSimpleType() )
            st = st.getBaseType();

        return st;
    }

    static boolean hasSimpleContent(SchemaType st)
    {
        return st.isSimpleType() || st.getContentType() == SchemaType.SIMPLE_CONTENT;
    }

    public abstract class ConstraintState {
        ConstraintState _next;

        ConstraintState()
        {
            setSavePoint(_constraintStack);
            _next = _constraintStack;
            _constraintStack = this;
        }

        abstract void element(Event e, SchemaType st);
        abstract void endElement(Event e);
        abstract void attr(Event e, QName name, SchemaType st, String value);
        abstract void text(Event e, SchemaType st, String value, boolean emptyContent);
        abstract void remove(Event e);

    }

    public class SelectorState extends ConstraintState {
        SchemaIdentityConstraint _constraint;
        Set _values = new LinkedHashSet();
        XPath.ExecutionContext _context;

        SelectorState(SchemaIdentityConstraint constraint, Event e, SchemaType st) {
            _constraint = constraint;
            _context = new XPath.ExecutionContext();
            _context.init((XPath)_constraint.getSelectorPath());

            if ( ( _context.start() & XPath.ExecutionContext.HIT ) != 0 )
                createFieldState(e, st);
        }

        void addFields(XmlObjectList fields, Event e) 
        {
            if (_constraint.getConstraintCategory() == SchemaIdentityConstraint.CC_KEYREF)
                _values.add(fields);
            else if (_values.contains(fields)) 
                emitError(e, "Duplicate key '" + fields + "' for key or unique constraint " + QNameHelper.pretty(_constraint.getName()));
            else
                _values.add(fields);
        }

        void element(Event e, SchemaType st) 
        {
            if ( ( _context.element(e.getName()) & XPath.ExecutionContext.HIT) != 0 )
                createFieldState(e, st);
        }

        void endElement(Event e) 
        {
            _context.end();
        }

        void createFieldState(Event e, SchemaType st) {
            new FieldState(this, e, st);
        }

        void remove(Event e) {
            // Bubble up key, unique values to keyrefs
            for (ConstraintState cs = _next ; cs != null ; cs = cs._next )
            {
                if (cs instanceof KeyrefState)
                {
                    KeyrefState kr = (KeyrefState)cs;
                    if (kr._constraint.getReferencedKey() == this)
                        kr.addKeyValues(_values);
                }
            }
        }

        void attr(Event e, QName name, SchemaType st, String value) {}
        void text(Event e, SchemaType st, String value, boolean emptyContent) {}
    }

    public class KeyrefState extends SelectorState {
        Set _keyValues = new HashSet();

        KeyrefState(SchemaIdentityConstraint constraint, Event e, SchemaType st) {
            super(constraint, e, st);
        }

        void addKeyValues(final Set values)
        {
            // BUG: remove duplicates
            _keyValues.addAll(values);
        }

        void remove(Event e) {
            // First check if there are any keys at the same stack level as this
            // that may contribute key values to me
            for (ConstraintState cs = _next ; cs != null && cs != _elementStack._savePoint ; cs = cs._next)
            {
                if (cs instanceof SelectorState)
                {
                    SelectorState sel = (SelectorState)cs;
                    if (sel._constraint == _constraint.getReferencedKey())
                        addKeyValues(sel._values);
                }
            }


            // validate all values have been seen
            for (Iterator it = _values.iterator() ; it.hasNext() ; )
            {

                XmlObjectList fields = (XmlObjectList)it.next();
                if (fields.unfilled() < 0 && ! _keyValues.contains(fields))
                {
                    emitError(e, "Key '" + fields + "' not found (keyRef " + QNameHelper.pretty(_constraint.getName()) + ")");
                    return;
                }
            }
        }
    }

    public class FieldState extends ConstraintState {
        SelectorState _selector;
        XPath.ExecutionContext[] _contexts;
        boolean[] _needsValue;
        XmlObjectList _value;

        FieldState(SelectorState selector, Event e, SchemaType st) {

            // System.out.println("Creating new Field State for: " + e.getName());

            _selector = selector;
            SchemaIdentityConstraint ic = selector._constraint;

            int fieldCount = ic.getFields().length;
            _contexts = new XPath.ExecutionContext[fieldCount];
            _needsValue = new boolean[fieldCount];
            _value = new XmlObjectList(fieldCount);

            for (int i = 0 ; i < fieldCount ; i++)
            {
                _contexts[i] = new XPath.ExecutionContext();
                _contexts[i].init((XPath)ic.getFieldPath(i));
                if ( ( _contexts[i].start() & XPath.ExecutionContext.HIT ) != 0 )
                {
                    // System.out.println("hit for element: " + e.getName());

                    if (!hasSimpleContent(st))
                        emitError(e, "Identity constraint field must have simple content");
                    else
                        _needsValue[i] = true;
                }
            }

        }

        void element(Event e, SchemaType st)
        {
            for (int i = 0 ; i < _contexts.length ; i++) {
                if (_needsValue[i])
                {
                    emitError(e, "Identity constraint field must have simple content");
                    _needsValue[i] = false;
                }
            }

            for (int i = 0 ; i < _contexts.length ; i++) {
                if ( ( _contexts[i].element(e.getName()) & XPath.ExecutionContext.HIT) != 0 )
                {
                    if (! hasSimpleContent(st))
                        emitError(e, "Identity constraint field must have simple content");
                    else
                        _needsValue[i] = true;
                }
            }
        }

        void attr(Event e, QName name, SchemaType st, String value) {

            // Null value indicates previously reported validation problem
            if (value == null) return;

            for (int i = 0 ; i < _contexts.length ; i++) {
                if ( _contexts[i].attr(name) ) {
                    XmlObject o = newValue(st, value);

                    // Ignore invalid values. Assume that validation catches these
                    if (o == null) return;

                    boolean set = _value.set(o, i);

                    if (! set)
                        emitError(e, "Multiple instances of field with xpath: '" 
                            + _selector._constraint.getFields()[i] + "' for a selector");
                }

            }
        }


        void text(Event e, SchemaType st, String value, boolean emptyContent) {

            // Null value indicates previously reported validation problem
            if (value == null && !emptyContent) return;

            for (int i = 0 ; i < _contexts.length ; i++) {
                if ( _needsValue[i] ) {

                    if (emptyContent || !hasSimpleContent(st))
                    {
                        emitError(e, "Identity constraint field must have simple content");
                        return;
                    }

                    SchemaType simpleType = getSimpleType(st);
                    XmlObject o = newValue(simpleType, value);

                    // Ignore invalid values. Assume that validation catches these
                    if (o == null) return;

                    boolean set = _value.set(o, i);

                    if (! set)
                        emitError(e, "Multiple instances of field with xpath: '" 
                            + _selector._constraint.getFields()[i] + "' for a selector");
                }
            }
        }

        void endElement(Event e) {
            // reset any  _needsValue flags 
            // assume that if we didn't see the text, it was because of another validation
            // error, so don't emit another one.
            for (int i = 0 ; i < _needsValue.length ; i++)
            {
                _contexts[i].end();
                _needsValue[i] = false;
            }

        }

        void remove(Event e) 
        {

            if (_selector._constraint.getConstraintCategory() == SchemaIdentityConstraint.CC_KEY &&
                _value.unfilled() >= 0 )
            {
                // keys must have all values supplied
                emitError(e, "Key " + QNameHelper.pretty(_selector._constraint.getName()) + " is missing field with xpath: '" + _selector._constraint.getFields()[_value.unfilled()] + "'");
            }
            else
            {
                // Finished. Add these fields to the selector state
                _selector.addFields(_value, e);
            }
        }

    }

    public class IdState extends ConstraintState
    {
        Set _values = new LinkedHashSet();

        IdState() { }

        void attr(Event e, QName name, SchemaType st, String value)
        {
            handleValue(e, st, value);
        }

        void text(Event e, SchemaType st, String value, boolean emptyContent)
        {
            if (emptyContent)
                return;

            handleValue(e, st, value);
        }

        private void handleValue(Event e, SchemaType st, String value)
        {

            // Null value indicates previously reported validation problem
            if (value == null) return;

            if (st == null || st.isNoType())
            {
                // ignore invalid values. Assume that validation catches these
                return;
            }

            if (XmlID.type.isAssignableFrom(st))
            {
                XmlObjectList xmlValue = new XmlObjectList(1);
                XmlObject o = newValue(XmlID.type, value);

                // Ignore invalid values. Assume that validation catches these
                if (o == null) return;

                xmlValue.set(o, 0);

                if (_values.contains(xmlValue))
                    emitError(e, "Duplicate ID value '" + value + "'");
                else
                    _values.add(xmlValue);
            }
        }

        void element(Event e, SchemaType st) {}
        void endElement(Event e){}
        void remove(Event e){}

    }

    public class IdRefState extends ConstraintState
    {
        IdState _ids;
        List _values;

        IdRefState(IdState ids)
        {
            _ids = ids;
            _values = new ArrayList();
        }

        private void handleValue(Event e, SchemaType st, String value)
        {
            // Null value indicates previously reported validation problem
            if (value == null) return;

            if (st == null || st.isNoType())
            {
                // ignore invalid values. Assume that validation catches these
                return;
            }
            if (XmlIDREFS.type.isAssignableFrom(st))
            {
                XmlIDREFS lv = (XmlIDREFS)newValue(XmlIDREFS.type, value);

                // Ignore invalid values. Assume that validation catches these
                if (lv == null) return;

                List l = lv.xgetListValue();

                // Add one value for each idref in the list
                for (int i = 0 ; i < l.size() ; i++)
                {
                    XmlObjectList xmlValue = new XmlObjectList(1);
                    XmlIDREF idref = (XmlIDREF)l.get(i);
                    xmlValue.set(idref, 0);
                    _values.add(xmlValue);
                }
            }
            else if (XmlIDREF.type.isAssignableFrom(st))
            {
                XmlObjectList xmlValue = new XmlObjectList(1);
                XmlIDREF idref = (XmlIDREF)st.newValue(value);

                // Ignore invalid values. Assume that validation catches these
                if (idref == null) return;

                xmlValue.set(idref, 0);
                _values.add(xmlValue);
            }
        }

        void attr(Event e, QName name, SchemaType st, String value) 
        {
            handleValue(e, st, value);
        }
        void text(Event e, SchemaType st, String value, boolean emptyContent) 
        {
            if (emptyContent)
                return;

            handleValue(e, st, value);
        }
        void remove(Event e) 
        { 
            // Validate each ref has a corresponding ID
            for (Iterator it = _values.iterator() ; it.hasNext() ; )
            {
                Object o = it.next();
                if (! _ids._values.contains(o))
                {
                    emitError(e, "ID not found for IDRef value '" + o + "'");
                }
            }
        }
        void element(Event e, SchemaType st) { }
        void endElement(Event e) { }
    }

    private static class ElementState {
        ElementState _next;
        boolean _hasConstraints;
        ConstraintState _savePoint;
    }
}
