You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pivot.apache.org by gb...@apache.org on 2009/11/11 19:10:55 UTC
svn commit: r834994 - in /incubator/pivot/trunk:
core/src/org/apache/pivot/xml/Element.java
core/src/org/apache/pivot/xml/ElementListener.java
core/src/org/apache/pivot/xml/XMLSerializer.java
wtk/src/org/apache/pivot/wtk/content/TreeBranch.java
Author: gbrown
Date: Wed Nov 11 18:10:54 2009
New Revision: 834994
URL: http://svn.apache.org/viewvc?rev=834994&view=rev
Log:
Complete first pass implementation of org.apache.pivot.xml classes (code has not yet been tested, and writing of XML data is not yet supported).
Modified:
incubator/pivot/trunk/core/src/org/apache/pivot/xml/Element.java
incubator/pivot/trunk/core/src/org/apache/pivot/xml/ElementListener.java
incubator/pivot/trunk/core/src/org/apache/pivot/xml/XMLSerializer.java
incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/content/TreeBranch.java
Modified: incubator/pivot/trunk/core/src/org/apache/pivot/xml/Element.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/core/src/org/apache/pivot/xml/Element.java?rev=834994&r1=834993&r2=834994&view=diff
==============================================================================
--- incubator/pivot/trunk/core/src/org/apache/pivot/xml/Element.java (original)
+++ incubator/pivot/trunk/core/src/org/apache/pivot/xml/Element.java Wed Nov 11 18:10:54 2009
@@ -19,10 +19,13 @@
import java.util.Comparator;
import java.util.Iterator;
+import org.apache.pivot.collections.ArrayList;
import org.apache.pivot.collections.Dictionary;
+import org.apache.pivot.collections.HashMap;
import org.apache.pivot.collections.List;
import org.apache.pivot.collections.ListListener;
import org.apache.pivot.collections.Sequence;
+import org.apache.pivot.util.ImmutableIterator;
import org.apache.pivot.util.ListenerList;
/**
@@ -36,84 +39,160 @@
private NamespaceDictionary() {
}
+ /**
+ * Returns the URI of a namespace declared by this element.
+ *
+ * @param prefix
+ * The namespace prefix.
+ *
+ * @return
+ * The declared namespace, or <tt>null</tt> if no such namespace exists.
+ */
@Override
public String get(String prefix) {
- // TODO Auto-generated method stub
- return null;
+ return namespaces.get(prefix);
}
+ /**
+ * Sets the URI of a namespace declared by this element.
+ *
+ * @param prefix
+ * The namespace prefix.
+ *
+ * @param uri
+ * The namespace URI.
+ *
+ * @return
+ * The URI previously associated with the given prefix.
+ */
@Override
public String put(String prefix, String uri) {
- // TODO Auto-generated method stub
- return null;
+ if (uri == null) {
+ throw new IllegalArgumentException("uri is null.");
+ }
+
+ boolean update = containsKey(prefix);
+ String previousURI = namespaces.put(prefix, uri);
+
+ if (update) {
+ elementListeners.namespaceUpdated(Element.this, prefix, previousURI);
+ } else {
+ elementListeners.namespaceAdded(Element.this, prefix);
+ }
+
+ return previousURI;
}
+ /**
+ * Removes a namespace from this element's declared namespaces.
+ *
+ * @param prefix
+ * The namespace prefix.
+ *
+ * @return
+ * The URI previously associated with the given prefix.
+ */
@Override
public String remove(String prefix) {
- // TODO Auto-generated method stub
- return null;
+ String uri = null;
+
+ if (containsKey(prefix)) {
+ uri = namespaces.remove(prefix);
+ elementListeners.namespaceRemoved(Element.this, prefix, uri);
+ }
+
+ return uri;
}
+ /**
+ * Tests for the existence of a namespace declared by this element.
+ *
+ * @param prefix
+ *
+ * @return
+ * <tt>true</tt> if this element declares a namespace with the given prefix;
+ * <tt>false</tt>, otherwise.
+ */
@Override
public boolean containsKey(String prefix) {
- // TODO Auto-generated method stub
- return false;
+ return namespaces.containsKey(prefix);
}
+ /**
+ * Determines if this element declares any namespaces.
+ *
+ * @return
+ * <tt>true</tt> if this element does not declare any namespaces;
+ * <tt>false</tt> if the element declares at least one namespace.
+ */
@Override
public boolean isEmpty() {
- // TODO Auto-generated method stub
- return false;
+ return namespaces.isEmpty();
}
}
private static class ElementListenerList extends ListenerList<ElementListener>
implements ElementListener {
+ @Override
public void namespacePrefixChanged(Element element, String previousNamespacePrefix) {
for (ElementListener listener : this) {
listener.namespacePrefixChanged(element, previousNamespacePrefix);
}
}
+ @Override
public void localNameChanged(Element element, String previousLocalName) {
for (ElementListener listener : this) {
listener.localNameChanged(element, previousLocalName);
}
}
+ @Override
public void attributeAdded(Element element, String attribute) {
for (ElementListener listener : this) {
listener.attributeAdded(element, attribute);
}
}
+ @Override
public void attributeUpdated(Element element, String attribute, String previousValue) {
for (ElementListener listener : this) {
listener.attributeUpdated(element, attribute, previousValue);
}
}
- public void attributeRemoved(Element element, String attribute) {
+ @Override
+ public void attributeRemoved(Element element, String attribute, String value) {
+ for (ElementListener listener : this) {
+ listener.attributeRemoved(element, attribute, value);
+ }
+ }
+
+ @Override
+ public void defaultNamespaceURIChanged(Element element, String previousDefaultNamespaceURI) {
for (ElementListener listener : this) {
- listener.attributeRemoved(element, attribute);
+ listener.defaultNamespaceURIChanged(element, previousDefaultNamespaceURI);
}
}
+ @Override
public void namespaceAdded(Element element, String prefix) {
for (ElementListener listener : this) {
listener.namespaceAdded(element, prefix);
}
}
+ @Override
public void namespaceUpdated(Element element, String prefix, String previousURI) {
for (ElementListener listener : this) {
listener.namespaceUpdated(element, prefix, previousURI);
}
}
- public void namespaceRemoved(Element element, String prefix) {
+ @Override
+ public void namespaceRemoved(Element element, String prefix, String uri) {
for (ElementListener listener : this) {
- listener.namespaceRemoved(element, prefix);
+ listener.namespaceRemoved(element, prefix, uri);
}
}
}
@@ -121,6 +200,14 @@
private String namespacePrefix;
private String localName;
+ private HashMap<String, String> namespaces = new HashMap<String, String>();
+ private NamespaceDictionary namespaceDictionary = new NamespaceDictionary();
+ private String defaultNamespaceURI = null;
+
+ private HashMap<String, String> attributes = new HashMap<String, String>();
+ private ArrayList<Node> nodes = new ArrayList<Node>();
+
+ private ListListenerList<Node> listListeners = new ListListenerList<Node>();
private ElementListenerList elementListeners = new ElementListenerList();
public Element(String localName) {
@@ -133,29 +220,45 @@
}
/**
- * Returns the fully-qualified name of the element.
+ * Returns the element's namespace prefix.
+ *
+ * @return
+ * The element's namespace prefix, or <tt>null</tt> if the element belongs to the
+ * default namespace.
*/
- public String getName() {
- String name;
- if (namespacePrefix == null) {
- name = localName;
- } else {
- name = namespacePrefix + ":" + localName;
- }
-
- return name;
- }
-
public String getNamespacePrefix() {
return namespacePrefix;
}
+ /**
+ * Sets the element's namespace prefix.
+ * <p>
+ * Note that this method does not ensure that the namespace specified by the
+ * prefix actually exists. It only verifies that the prefix does not contain
+ * invalid characters.
+ *
+ * @param namespacePrefix
+ * The element's namespace prefix, or <tt>null</tt> to use the default namespace.
+ */
public void setNamespacePrefix(String namespacePrefix) {
if (namespacePrefix != null) {
- // TODO Validate name
+ if (namespacePrefix.length() == 0) {
+ throw new IllegalArgumentException("Namespace prefix is empty.");
+ }
+
+ char c = namespacePrefix.charAt(0);
+ if (!Character.isLetter(c)) {
+ throw new IllegalArgumentException("'" + c + "' is not a valid start"
+ + " character for a namespace prefix.");
+ }
- if (getNamespaceURI(namespacePrefix) == null) {
- throw new IllegalArgumentException("Namespace \"" + namespacePrefix + "\" does not exist.");
+ for (int i = 1, n = namespacePrefix.length(); i < n; i++) {
+ c = namespacePrefix.charAt(i);
+
+ if (!Character.isLetterOrDigit(c)) {
+ throw new IllegalArgumentException("'" + c + "' is not a valid character"
+ + " for a namespace prefix.");
+ }
}
}
@@ -167,25 +270,44 @@
}
}
- public String getNamespaceURI() {
- return (namespacePrefix == null) ? null : getNamespaceURI(namespacePrefix);
- }
-
- public String getNamespaceURI(String prefix) {
- // TODO Walk up parent tree looking for namespace prefix
- return null;
- }
-
+ /**
+ * Returns the element's local name.
+ */
public String getLocalName() {
return localName;
}
+ /**
+ * Sets the element's local name.
+ *
+ * @param localName
+ */
public void setLocalName(String localName) {
if (localName == null) {
throw new IllegalArgumentException();
}
- // TODO Validate name
+ if (localName.length() == 0) {
+ throw new IllegalArgumentException("Local name is empty.");
+ }
+
+ char c = localName.charAt(0);
+ if (!Character.isLetter(c)
+ && c != '_') {
+ throw new IllegalArgumentException("'" + c + "' is not a valid start"
+ + " character for a local name.");
+ }
+
+ for (int i = 1, n = localName.length(); i < n; i++) {
+ c = localName.charAt(i);
+
+ if (!Character.isLetterOrDigit(c)
+ && c != '-'
+ && c != '.') {
+ throw new IllegalArgumentException("'" + c + "' is not a valid character"
+ + " for a local name.");
+ }
+ }
String previousLocalName = this.localName;
@@ -195,110 +317,317 @@
}
}
+ /**
+ * Returns the fully-qualified name of the element.
+ */
+ public String getName() {
+ String name;
+ if (namespacePrefix == null) {
+ name = localName;
+ } else {
+ name = namespacePrefix + ":" + localName;
+ }
+
+ return name;
+ }
+
+ /**
+ * Returns the element's namespace dictionary.
+ */
+ public NamespaceDictionary getNamespaces() {
+ return namespaceDictionary;
+ }
+
+ /**
+ * Returns the element's default namespace URI.
+ *
+ * @return
+ * The default namespace URI declared by this element, or <tt>null</tt> if
+ * this element does not declare a default namespace.
+ */
+ public String getDefaultNamespaceURI() {
+ return defaultNamespaceURI;
+ }
+
+ /**
+ * Sets the element's default namespace URI.
+ *
+ * @return
+ * The default namespace URI declared by this element, or <tt>null</tt> if
+ * this element does not declare a default namespace.
+ */
+ public void setDefaultNamespaceURI(String defaultNamespaceURI) {
+ String previousDefaultNamespaceURI = this.defaultNamespaceURI;
+
+ if (previousDefaultNamespaceURI != defaultNamespaceURI) {
+ this.defaultNamespaceURI = defaultNamespaceURI;
+ elementListeners.defaultNamespaceURIChanged(this, previousDefaultNamespaceURI);
+ }
+ }
+
+ /**
+ * Determines the namespace URI corresponding to the given prefix by traversing
+ * the element's ancestry.
+ *
+ * @param prefix
+ * The namespace prefix to look up, or <tt>null</tt> to determine the default
+ * namespace for this element.
+ *
+ * @return
+ * The namespace URI corresponding to the given prefix, or <tt>null</tt> if a
+ * URI could not be found.
+ */
+ public String getNamespaceURI(String prefix) {
+ String namespaceURI;
+
+ Element parent = getParent();
+ if (prefix == null) {
+ if (defaultNamespaceURI == null) {
+ namespaceURI = parent.getDefaultNamespaceURI();
+ } else {
+ namespaceURI = defaultNamespaceURI;
+ }
+ } else {
+ if (namespaces.containsKey(prefix)) {
+ namespaceURI = namespaces.get(prefix);
+ } else {
+ namespaceURI = parent.getNamespaceURI(prefix);
+ }
+ }
+
+ return namespaceURI;
+ }
+
+ /**
+ * Returns an attribute value.
+ */
@Override
public String get(String attribute) {
- // TODO Auto-generated method stub
- return null;
+ return attributes.get(attribute);
}
+ /**
+ * Sets an attribute value.
+ *
+ * @param attribute
+ * @param value
+ *
+ * @return
+ * The value previously associated with the given attribute.
+ */
@Override
public String put(String attribute, String value) {
- // TODO Auto-generated method stub
- return null;
+ if (value == null) {
+ throw new IllegalArgumentException("value is null.");
+ }
+
+ boolean update = containsKey(attribute);
+ String previousValue = attributes.put(attribute, value);
+
+ if (update) {
+ elementListeners.attributeUpdated(Element.this, attribute, previousValue);
+ } else {
+ elementListeners.attributeAdded(Element.this, attribute);
+ }
+
+ return previousValue;
}
+ /**
+ * Removes an attribute value.
+ *
+ * @param attribute
+ *
+ * @return
+ * The value previously associated with the given attribute.
+ */
@Override
public String remove(String attribute) {
- // TODO Auto-generated method stub
- return null;
+ String value = null;
+
+ if (containsKey(attribute)) {
+ value = attributes.remove(attribute);
+ elementListeners.namespaceRemoved(Element.this, attribute, value);
+ }
+
+ return value;
}
+ /**
+ * Tests for the existence of an attribute.
+ *
+ * @param attribute
+ *
+ * @return
+ * <tt>true</tt> if this element defines the given attribute; <tt>false<tt>,
+ * otherwise.
+ */
@Override
public boolean containsKey(String attribute) {
- // TODO Auto-generated method stub
- return false;
+ return attributes.containsKey(attribute);
}
+ /**
+ * Determines if this element defines any attributes.
+ *
+ * @return
+ * <tt>true</tt> if this element does not define any attributes;
+ * <tt>false</tt>, otherwise.
+ */
@Override
public boolean isEmpty() {
- // TODO Auto-generated method stub
- return false;
+ return attributes.isEmpty();
}
+ /**
+ * Adds a node to this element.
+ *
+ * @param node
+ *
+ * @return
+ * The index at which the node was added.
+ */
@Override
- public int add(Node item) {
- // TODO Auto-generated method stub
- return 0;
+ public int add(Node node) {
+ int index = nodes.add(node);
+ listListeners.itemInserted(this, index);
+
+ return index;
}
+ /**
+ * Inserts a node at a specific location within this element.
+ *
+ * @param node
+ * @param index
+ */
@Override
- public void insert(Node item, int index) {
- // TODO Auto-generated method stub
-
+ public void insert(Node node, int index) {
+ nodes.insert(node, index);
+ listListeners.itemInserted(this, index);
}
+ /**
+ * Updates the node at the given location.
+ *
+ * @param index
+ * @param node
+ */
@Override
- public Node update(int index, Node item) {
- // TODO Auto-generated method stub
- return null;
+ public Node update(int index, Node node) {
+ Node previousNode = nodes.update(index, node);
+ listListeners.itemUpdated(this, index, previousNode);
+
+ return previousNode;
}
+ /**
+ * Removes a node from this element.
+ *
+ * @param
+ */
@Override
- public int remove(Node item) {
- // TODO Auto-generated method stub
- return 0;
+ public int remove(Node node) {
+ int index = nodes.indexOf(node);
+ if (index != -1) {
+ remove(index, 1);
+ }
+
+ return index;
}
+ /**
+ * Removes a range of nodes from this element.
+ *
+ * @param index
+ * @param count
+ *
+ * @return
+ * The removed nodes.
+ */
@Override
public Sequence<Node> remove(int index, int count) {
- // TODO Auto-generated method stub
- return null;
+ Sequence<Node> removed = nodes.remove(index, count);
+ if (count > 0) {
+ listListeners.itemsRemoved(this, index, removed);
+ }
+
+ return removed;
}
+ /**
+ * Removes all nodes from this element.
+ */
@Override
public void clear() {
- // TODO Auto-generated method stub
-
+ if (getLength() > 0) {
+ nodes.clear();
+ listListeners.listCleared(this);
+ }
}
+ /**
+ * Returns the node at the given index.
+ *
+ * @param index
+ */
@Override
public Node get(int index) {
- // TODO Auto-generated method stub
- return null;
+ return nodes.get(index);
}
+ /**
+ * Determines the index of the given node within this element.
+ *
+ * @return
+ * The index of the node, or <tt>-1</tt> if the node does not exist in
+ * this element.
+ */
@Override
- public int indexOf(Node item) {
- // TODO Auto-generated method stub
- return 0;
+ public int indexOf(Node node) {
+ return nodes.indexOf(node);
}
+ /**
+ * Returns the number of nodes contained by this element.
+ */
@Override
public int getLength() {
- // TODO Auto-generated method stub
- return 0;
+ return nodes.getLength();
}
+ /**
+ * @return
+ * <tt>null</tt>; elements cannot be sorted.
+ */
@Override
public Comparator<Node> getComparator() {
return null;
}
+ /**
+ * @throws UnsupportedOperationException
+ * Elements cannot be sorted.
+ */
@Override
public void setComparator(Comparator<Node> comparator) {
throw new UnsupportedOperationException();
}
+ /**
+ * Returns an iterator over this elements child nodes.
+ */
@Override
public Iterator<Node> iterator() {
- // TODO Auto-generated method stub
- return null;
+ return new ImmutableIterator<Node>(nodes.iterator());
}
+ /**
+ * Returns the element's listener list.
+ */
@Override
public ListenerList<ListListener<Node>> getListListeners() {
- // TODO Auto-generated method stub
- return null;
+ return listListeners;
}
/**
Modified: incubator/pivot/trunk/core/src/org/apache/pivot/xml/ElementListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/core/src/org/apache/pivot/xml/ElementListener.java?rev=834994&r1=834993&r2=834994&view=diff
==============================================================================
--- incubator/pivot/trunk/core/src/org/apache/pivot/xml/ElementListener.java (original)
+++ incubator/pivot/trunk/core/src/org/apache/pivot/xml/ElementListener.java Wed Nov 11 18:10:54 2009
@@ -24,28 +24,40 @@
* Element listener adapter.
*/
public static class Adapter implements ElementListener {
+ @Override
public void namespacePrefixChanged(Element element, String previousNamespacePrefix) {
}
+ @Override
public void localNameChanged(Element element, String previousLocalName) {
}
+ @Override
public void attributeAdded(Element element, String attribute) {
}
+ @Override
public void attributeUpdated(Element element, String attribute, String previousValue) {
}
- public void attributeRemoved(Element element, String attribute) {
+ @Override
+ public void attributeRemoved(Element element, String attribute, String value) {
}
+ @Override
+ public void defaultNamespaceURIChanged(Element element, String previousDefaultNamespaceURI) {
+ }
+
+ @Override
public void namespaceAdded(Element element, String prefix) {
}
+ @Override
public void namespaceUpdated(Element element, String prefix, String previousURI) {
}
- public void namespaceRemoved(Element element, String prefix) {
+ @Override
+ public void namespaceRemoved(Element element, String prefix, String uri) {
}
}
@@ -87,8 +99,17 @@
*
* @param element
* @param attribute
+ * @param value
+ */
+ public void attributeRemoved(Element element, String attribute, String value);
+
+ /**
+ * Called when an element's default namespace URI has changed.
+ *
+ * @param element
+ * @param previousDefaultNamespaceURI
*/
- public void attributeRemoved(Element element, String attribute);
+ public void defaultNamespaceURIChanged(Element element, String previousDefaultNamespaceURI);
/**
* Called when a namespace has been added to an element.
@@ -112,6 +133,7 @@
*
* @param element
* @param prefix
+ * @param uri
*/
- public void namespaceRemoved(Element element, String prefix);
+ public void namespaceRemoved(Element element, String prefix, String uri);
}
Modified: incubator/pivot/trunk/core/src/org/apache/pivot/xml/XMLSerializer.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/core/src/org/apache/pivot/xml/XMLSerializer.java?rev=834994&r1=834993&r2=834994&view=diff
==============================================================================
--- incubator/pivot/trunk/core/src/org/apache/pivot/xml/XMLSerializer.java (original)
+++ incubator/pivot/trunk/core/src/org/apache/pivot/xml/XMLSerializer.java Wed Nov 11 18:10:54 2009
@@ -20,6 +20,11 @@
import java.io.InputStream;
import java.io.OutputStream;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
import org.apache.pivot.serialization.SerializationException;
import org.apache.pivot.serialization.Serializer;
@@ -29,17 +34,100 @@
public class XMLSerializer implements Serializer<Element> {
public static final String MIME_TYPE = "text/xml";
+ private XMLInputFactory xmlInputFactory;
+
+ private Element element = null;
+
+ public static final String XMLNS_ATTRIBUTE_PREFIX = "xmlns";
+
+ public XMLSerializer() {
+ this(true);
+ }
+
+ public XMLSerializer(boolean coalesceText) {
+ xmlInputFactory = XMLInputFactory.newInstance();
+ xmlInputFactory.setProperty("javax.xml.stream.isCoalescing", coalesceText);
+ }
+
@Override
public Element readObject(InputStream inputStream) throws IOException, SerializationException {
- // TODO Auto-generated method stub
- return null;
+ if (inputStream == null) {
+ throw new IllegalArgumentException("inputStream is null.");
+ }
+
+ // Parse the XML stream
+ element = null;
+
+ try {
+ XMLStreamReader reader = xmlInputFactory.createXMLStreamReader(inputStream);
+
+ while (reader.hasNext()) {
+ int event = reader.next();
+
+ switch (event) {
+ case XMLStreamConstants.CHARACTERS: {
+ element.add(new TextNode(reader.getText()));
+ break;
+ }
+
+ case XMLStreamConstants.START_ELEMENT: {
+ // Create the element
+ String prefix = reader.getPrefix();
+ String localName = reader.getLocalName();
+
+ Element element = new Element(prefix, localName);
+
+ for (int i = 0, n = reader.getAttributeCount(); i < n; i++) {
+ String attributePrefix = reader.getAttributePrefix(i);
+ String attributeLocalName = reader.getAttributeLocalName(i);
+ String attributeValue = reader.getAttributeValue(i);
+
+ if (attributePrefix != null) {
+ if (!attributePrefix.equals(XMLNS_ATTRIBUTE_PREFIX)) {
+ throw new SerializationException("Attribute namespaces are not supported.");
+ }
+
+ element.getNamespaces().put(attributeLocalName, attributeValue);
+ } else {
+ element.put(attributeLocalName, attributeValue);
+ }
+ }
+
+ if (this.element == null) {
+ this.element = element;
+ } else {
+ this.element.add(element);
+ }
+
+ break;
+ }
+
+ case XMLStreamConstants.END_ELEMENT: {
+ // Move up the stack
+ Element parent = element.getParent();
+ if (parent != null) {
+ element = parent;
+ }
+
+ break;
+ }
+ }
+ }
+
+ reader.close();
+ } catch (XMLStreamException exception) {
+ throw new SerializationException(exception);
+ }
+
+ return element;
}
@Override
- public void writeObject(Element object, OutputStream outputStream) throws IOException,
- SerializationException {
- // TODO Auto-generated method stub
-
+ public void writeObject(Element object, OutputStream outputStream)
+ throws IOException, SerializationException {
+ // TODO (note that we'll need to check for valid namespace prefixes here,
+ // since we don't do it in Element)
+ throw new UnsupportedOperationException();
}
@Override
Modified: incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/content/TreeBranch.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/content/TreeBranch.java?rev=834994&r1=834993&r2=834994&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/content/TreeBranch.java (original)
+++ incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/content/TreeBranch.java Wed Nov 11 18:10:54 2009
@@ -102,15 +102,19 @@
@Override
public Sequence<TreeNode> remove(int index, int count) {
Sequence<TreeNode> removed = treeNodes.remove(index, count);
- listListeners.itemsRemoved(this, index, removed);
+ if (count > 0) {
+ listListeners.itemsRemoved(this, index, removed);
+ }
return removed;
}
@Override
public void clear() {
- treeNodes.clear();
- listListeners.listCleared(this);
+ if (getLength() > 0) {
+ treeNodes.clear();
+ listListeners.listCleared(this);
+ }
}
@Override