/*   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 org.apache.xmlbeans.impl.common.SequencedHashSet;

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)
        {
            if (XmlBeans.ASSERTS)
                XmlBeans.assertTrue(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) 
    {
        if (XmlBeans.ASSERTS)
            XmlBeans.assertTrue(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 SequencedHashSet();
        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 SequencedHashSet();

        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;
    }
}
