/*
* 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.values;

import org.apache.xmlbeans.SchemaType;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlAnySimpleType;
import org.apache.xmlbeans.SimpleValue;
import org.apache.xmlbeans.XmlSimpleList;
import org.apache.xmlbeans.impl.common.ValidationContext;
import org.apache.xmlbeans.impl.common.QNameHelper;
import org.apache.xmlbeans.impl.common.PrefixResolver;
import org.apache.xmlbeans.impl.common.XMLChar;

import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;

public class XmlListImpl extends XmlObjectBase implements XmlAnySimpleType
{
    public XmlListImpl(SchemaType type, boolean complex)
        { _schemaType = type; initComplexType(complex, false); }

    public SchemaType schemaType()
        { return _schemaType; }

    private SchemaType _schemaType;
    private XmlSimpleList _value;
    private XmlSimpleList _jvalue;



    // SIMPLE VALUE ACCESSORS BELOW -------------------------------------------
    // gets raw text value

    private static String nullAsEmpty(String s)
    {
        if (s == null)
            return "";
        return s;
    }

    private static String compute_list_text(List xList)
    {
        if (xList.size() == 0)
            return "";

        StringBuffer sb = new StringBuffer();
        sb.append(nullAsEmpty(((SimpleValue)xList.get(0)).getStringValue()));

        for (int i = 1; i < xList.size(); i++)
        {
            sb.append(' ');
            sb.append(nullAsEmpty(((SimpleValue)xList.get(i)).getStringValue()));
        }

        return sb.toString();
    }

    protected String compute_text(NamespaceManager nsm)
    {
        return compute_list_text(_value);
    }

    protected boolean is_defaultable_ws(String v) {
        try {
            XmlSimpleList savedValue = _value;
            set_text(v);

            // restore the saved value
            _value = savedValue;

            return false;
        }
        catch (XmlValueOutOfRangeException e) {
            return true;
        }
    }

    protected void set_text(String s)
    {
        // first check against any patterns...
        if (_validateOnSet() && !_schemaType.matchPatternFacet(s))
            throw new XmlValueOutOfRangeException();

        SchemaType itemType = _schemaType.getListItemType();

        XmlSimpleList newval = lex(s, itemType, _voorVc, has_store() ? get_store() : null);

        // check enumeration
        if (_validateOnSet())
            validateValue(newval, _schemaType, _voorVc);

        // we made it all the way through; so we're OK.
        _value = newval;
    }
    
    private static final String[] EMPTY_STRINGARRAY = new String[0];
    
    public static String[] split_list(String s)
    {
        if (s.length() == 0)
            return EMPTY_STRINGARRAY;
                
        List result = new ArrayList();
        int i = 0;
        int start = 0;
        for (;;)
        {
            while (i < s.length() && XMLChar.isSpace(s.charAt(i)))
                i += 1;
            if (i >= s.length())
                return (String[])result.toArray(EMPTY_STRINGARRAY);
            start = i;
            while (i < s.length() && !XMLChar.isSpace(s.charAt(i)))
                i += 1;
            result.add(s.substring(start, i));
        }
    }
    
    public static XmlSimpleList lex(String s, SchemaType itemType, ValidationContext ctx, PrefixResolver resolver)
    {
        String[] parts = split_list(s);

        XmlAnySimpleType[] newArray = new XmlAnySimpleType[parts.length];
        boolean pushed = false;
        if (resolver != null)
        {
            NamespaceContext.push(new NamespaceContext(resolver));
            pushed = true;
        }
        int i = 0;
        try
        {
            for (i = 0; i < parts.length; i++)
            {
                try
                {
                    newArray[i] = itemType.newValue(parts[i]);
                }
                catch (XmlValueOutOfRangeException e)
                {
                    ctx.invalid("List item '" + parts[i] + "' is not a valid value of " + QNameHelper.readable(itemType));
                }
            }
        }
        finally
        {
            if (pushed)
                NamespaceContext.pop();
        }
        return new XmlSimpleList(Arrays.asList(newArray));
    }

    protected void set_nil()
    {
        _value = null;
    }

    public List xlistValue()
    {
        check_dated();
        return _value;
    }

    public List listValue()
    {
        check_dated();
        if (_value == null)
            return null;
        if (_jvalue != null)
            return _jvalue;
        List javaResult = new ArrayList();
        for (int i = 0; i < _value.size(); i++)
            javaResult.add(java_value((XmlObject)_value.get(i)));
        _jvalue = new XmlSimpleList(javaResult);
        return _jvalue;
    }

    private static boolean permits_inner_space(XmlObject obj)
    {
        switch (((SimpleValue)obj).instanceType().getPrimitiveType().getBuiltinTypeCode())
        {
            case SchemaType.BTC_STRING:
            case SchemaType.BTC_ANY_URI:
            case SchemaType.BTC_ANY_SIMPLE:
            case SchemaType.BTC_ANY_TYPE:
                return true;
            default:
                return false;
        }
    }

    private static boolean contains_white_space(String s)
    {
        return s.indexOf(' ') >= 0 ||
                s.indexOf('\t') >= 0 ||
                s.indexOf('\n') >= 0 ||
                s.indexOf('\r') >= 0;
    }

    public void set_list(List list)
    {
        SchemaType itemType = _schemaType.getListItemType();
        XmlSimpleList xList;

        boolean pushed = false;
        if (has_store())
        {
            NamespaceContext.push(new NamespaceContext(get_store()));
            pushed = true;
        }
        
        try
        {
            XmlAnySimpleType[] newval = new XmlAnySimpleType[list.size()];
            for (int i = 0; i < list.size(); i++)
            {
                Object entry = list.get(i);
                if ((entry instanceof XmlObject) && permits_inner_space((XmlObject)list.get(i)))
                {
                    String stringrep = list.get(i).toString();
                    if (contains_white_space(stringrep))
                        throw new XmlValueOutOfRangeException();
                }
                newval[i] = itemType.newValue(entry);
            }
            xList = new XmlSimpleList(Arrays.asList(newval));
        }
        finally
        {
            if (pushed)
                NamespaceContext.pop();
        }
        

        if (_validateOnSet())
        {
            // check enumeration + min/max/etc
            validateValue(xList, _schemaType, _voorVc);
        }

        _value = xList;
    }

    public static void validateValue(XmlSimpleList items, SchemaType sType, ValidationContext context)
    {
        XmlObject[] enumvals = sType.getEnumerationValues();
        checkEnum: if (enumvals != null)
        {
            for (int i = 0; i < enumvals.length; i++)
            {
                if (equal_xmlLists(items, ((XmlObjectBase)enumvals[i]).xlistValue()))
                    break checkEnum;
            }
            context.invalid("List (" + items + ") is not a valid enumerated value for " + QNameHelper.readable(sType));
        }

        XmlObject o;
        int i;

        if ((o = sType.getFacet( SchemaType.FACET_LENGTH )) != null)
        {
            if ((i = ((SimpleValue)o).getIntValue()) != items.size())
            {
                context.invalid(
                    "List (" + items + ") does not have " + i +
                        " items per length facet for " + QNameHelper.readable(sType));
            }
        }

        if ((o = sType.getFacet( SchemaType.FACET_MIN_LENGTH )) != null)
        {
            if ((i = ((SimpleValue)o).getIntValue()) > items.size())
            {
                context.invalid(
                    "List (" + items + ") has only " + items.size() +
                        " items, fewer than min length facet (" + i + ") for " + QNameHelper.readable(sType) );
            }
        }

        if ((o = sType.getFacet( SchemaType.FACET_MAX_LENGTH )) != null)
        {
            if ((i = ((SimpleValue)o).getIntValue()) < items.size())
            {
                context.invalid(
                    "List (" + items + ") has " + items.size() +
                        " items, more than max length facet (" + i + ") for " + QNameHelper.readable(sType) );
            }
        }
    }

    // comparators
    // protected int compare_to(XmlObject i) - no sorting order; inherit from base

    protected boolean equal_to(XmlObject obj)
    {
        return equal_xmlLists(_value, ((XmlObjectBase)obj).xlistValue());
    }


    private static boolean equal_xmlLists(List a, List b)
    {
        if (a.size() != b.size())
            return false;
        for (int i = 0; i < a.size(); i++)
        {
            if (!a.get(i).equals(b.get(i)))
                return false;
        }
        return true;
    }

    protected int value_hash_code()
    {
        if (_value == null)
            return 0;

        // hash code probes 9 distributed values, plus the last
        int hash = _value.size();
        int incr = _value.size() / 9;
        if (incr < 1)
            incr = 1;

        int i;
        for (i = 0; i < _value.size(); i += incr)
        {
            hash *= 19;
            hash += _value.get(i).hashCode();
        }

        if (i < _value.size())
        {
            hash *= 19;
            hash += _value.get(i).hashCode();
        }

        return hash;
    }

    protected void validate_simpleval(String lexical, ValidationContext ctx)
    {
        validateValue((XmlSimpleList)xlistValue(), schemaType(), ctx);
    }
    
}
