blob: a38f3b8e9366e5f2d172eb8c7f8ee0b9b659926f [file] [log] [blame]
/*
* 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);
}
}