| /* 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.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.XmlErrorCodes; |
| 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 ""; |
| |
| StringBuilder sb = new StringBuilder(); |
| 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(XmlErrorCodes.DATATYPE_VALID$PATTERN_VALID, |
| new Object[] { "list", s, QNameHelper.readable(_schemaType) }); |
| |
| 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; |
| _jvalue = null; |
| } |
| |
| 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(XmlErrorCodes.LIST, new Object[] { "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 xgetListValue() |
| { |
| check_dated(); |
| return _value; |
| } |
| |
| public List getListValue() |
| { |
| 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; |
| _jvalue = null; |
| } |
| |
| 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(XmlErrorCodes.DATATYPE_ENUM_VALID, |
| new Object[] { "list", items, QNameHelper.readable(sType) }); |
| } |
| |
| XmlObject o; |
| int i; |
| |
| if ((o = sType.getFacet( SchemaType.FACET_LENGTH )) != null) |
| { |
| if ((i = ((SimpleValue)o).getIntValue()) != items.size()) |
| { |
| context.invalid(XmlErrorCodes.DATATYPE_LENGTH_VALID$LIST_LENGTH, |
| new Object[] { items, new Integer(items.size()), new Integer(i), QNameHelper.readable(sType) }); |
| } |
| } |
| |
| if ((o = sType.getFacet( SchemaType.FACET_MIN_LENGTH )) != null) |
| { |
| if ((i = ((SimpleValue)o).getIntValue()) > items.size()) |
| { |
| context.invalid(XmlErrorCodes.DATATYPE_MIN_LENGTH_VALID$LIST_LENGTH, |
| new Object[] { items, new Integer(items.size()), new Integer(i), QNameHelper.readable(sType) }); |
| } |
| } |
| |
| if ((o = sType.getFacet( SchemaType.FACET_MAX_LENGTH )) != null) |
| { |
| if ((i = ((SimpleValue)o).getIntValue()) < items.size()) |
| { |
| context.invalid(XmlErrorCodes.DATATYPE_MAX_LENGTH_VALID$LIST_LENGTH, |
| new Object[] { items, new Integer(items.size()), new Integer(i), 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); |
| } |
| |
| } |