/********************************************************************************* * TotalCross Software Development Kit * * Copyright (C) 2003-2004 Pierre G. Richard * * Copyright (C) 2003-2012 SuperWaba Ltda. * * All Rights Reserved * * * * This library and virtual machine is distributed in the hope that it will * * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * * * This file is covered by the GNU LESSER GENERAL PUBLIC LICENSE VERSION 3.0 * * A copy of this license is located in file license.txt at the root of this * * SDK or can be downloaded here: * * http://www.gnu.org/licenses/lgpl-3.0.txt * * * *********************************************************************************/ package totalcross.xml; import totalcross.sys.*; import totalcross.util.*; /** * This class describes the attributes attached to a start-tag. Tags are case-insensitive. * <P> * The <code>AttributeListIterator</code> class provides an iterator over the components of each attribute in this </code>AttributeList</code> * instance: * <UL> * <LI>the attribute name * <LI>the unquoted value * <LI>the quote, if one exists * </UL> */ public class AttributeList extends Hashtable { Filter filter; /** * Set to true if you want the get/set methods to be case insensitive. */ public boolean caseInsensitive; // guich@tc113_29 /** * Constructs an empty <code>attributeList</code> with 5 free positions. */ public AttributeList() { super(5); } /** * Clones the given <code>attributeList</code>. * * @param source The <code>attributeList</code> to be cloned. */ public AttributeList(AttributeList source) { super(source.size()); Vector keys = source.getKeys(); Vector values = source.getValues(); int max = keys.size(); for (int i=0; i < max; ++i) put(getKey((String)keys.items[i]), values.items[i]); } private String getKey(String k) // guich@tc113_29 { return caseInsensitive ? k.toLowerCase() : k; // guich@tc113_12: added toLowerCase } /** * Adds a new attribute to this AttributeList * * @param attrName The name of the attribute. * @param attrValue The unquoted value of the attribute. * @param dlm Delimiter that started the attribute value (<code>'</code> or <code>"</code>), or <code>'\0'</code> if none. */ public final void addAttribute(String attrName, String attrValue, byte dlm) { attrName = getKey(attrName); // guich@tc113_12: convert toLowerCase if ((filter == null) || filter.acceptAttribute(attrName, attrValue, dlm)) put(attrName, new AttributeValue(attrValue, dlm)); } /** * Gets the attribute value for a given name. * * @param name The attribute name. * @return The value, or <code>null</code> if it wasn't specified. */ public final String getAttributeValue(String name) { AttributeValue value = (AttributeValue)get(getKey(name)); // guich@tc113_12: convert toLowerCase if (value != null) return value.value; return null; } /** * Gets the attribute value for a given name as an integer. * * @param name The attribute name. * @param defaultValue The default value if there is no value for the attribute name. * @return The value, or the default value if it wasn't specified or there's a problem in the number conversion. */ public final int getAttributeValueAsInt(String name, int defaultValue) { AttributeValue value = (AttributeValue)get(getKey(name)); // guich@tc113_12: convert toLowerCase try { return Convert.toInt(value.value); } catch (Exception e) { return defaultValue; } } /** * Sets an <code>AttributeList.Filter</code> to filter the attribute entered in this <code>AttributeList</code>. * * @param filter The <code>AttributeList.Filter</code> to set, or <code>null</code> if the current <code>AttributeList</code> filter must be * removed. * @return The previous <code>AttributeList.Filter</code> or <code>null</code> if none was set. */ Filter setFilter(Filter filter) { Filter old = this.filter; this.filter = filter; return old; } /** * Interface to filter each attribute before entering it in the <code>AttributeList</code>. */ public interface Filter { /** * Call back to check if an attribute must be entered. * * @param attrName The name of the attribute. * @param attrValue The unquoted value of the attribute. * @param dlm Delimiter that started the attribute value (<code>'</code> or <code>"</code>), or <code>'\0'</code> if none. * @return <code>true</code> if the attribute can be entered; <code>false</code>, otherwise. */ boolean acceptAttribute(String attrName, String attrValue, byte dlm); } /** * Class to iterate over each attribute of an <code>AttributeList</code> */ public class Iterator { private int current; private String currentName; private AttributeValue currentValue; private Vector keys; private static final String singleQuote = "\'"; private static final String doubleQuote = "\""; private static final String noQuote = ""; /** * Constructs an <code>Iterator</code> over each attribute in the outer <code>AttributeList</code>. */ public Iterator() { this.keys = getKeys(); } /** * Makes current the next attribute in this <code>AttributeList</code>. * * @return <code>true</code> if the next attribute was activated, or <code>false</code> if there are no more attribute in this list. */ public final boolean next() { if (current < size()) { currentName = (String)keys.items[current++]; currentValue = (AttributeValue)get(currentName); return true; } else { currentName = null; currentValue = null; return false; } } /** * Gets the name of the current attribute. * * @return The name of the current attribute, or <code>null</code> if no attribute is actually current. */ public final String getAttributeName() { return currentName; } /** * Gets the unquoted value of the current attribute. * * @return The unquoted value of the current attribute, or <code>null</code> if no attribute is actually current. */ public final String getAttributeValue() { if (currentValue != null) return currentValue.value; return null; } /** * Gets the quote surrounding the value of the current attribute. * * @return <code>\'</code>, <code>\"</code>, or <code>\0</code> (the latter when no quote were surrounding the attribute value) or * <code>null</code> if no attribute is actually current. */ public final String getValueDelimiter() { if (currentValue != null) { switch (currentValue.dlm) { case (byte)'\'': return singleQuote; case (byte)'\"': return doubleQuote; default: return noQuote; } } return null; } /** * Gets the attribute as a string, the value being surrounded by single or double quotes if these were specified in the start-tag. * * @return The string a described above. */ public final String getAttributeAsString() { if (currentValue != null) { String dlm = getValueDelimiter(); return currentName + "=" + dlm + currentValue.value + dlm; } return null; } } /** Private class to store Attribute values with their delimiter */ private static class AttributeValue { private String value; private byte dlm; /** * Constructor * * @param value unquoted value for this AttributeValue * @param delemiter single quote, double quote or 0 */ AttributeValue(String value, byte dlm) { this.value = value; this.dlm = dlm; } } }