⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 element.java

📁 非常接近C/S操作方式的Java Ajax框架-ZK 用ZK框架使你的B/S应用程序更漂亮更易操作。 官网:www.zkoss.org
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* Element.java{{IS_NOTE	Purpose:	Description:	History:	2001/10/22 17:10:29, Create, Tom M. Yeh}}IS_NOTECopyright (C) 2001 Potix Corporation. All Rights Reserved.{{IS_RIGHT	This program is distributed under GPL Version 2.0 in the hope that	it will be useful, but WITHOUT ANY WARRANTY.}}IS_RIGHT*/package org.zkoss.idom;import java.util.Map;import java.util.LinkedHashMap;import java.util.Collection;import java.util.AbstractCollection;import java.util.List;import java.util.Iterator;import java.util.LinkedList;import java.util.Collections;import java.util.NoSuchElementException;import java.util.regex.Pattern;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import javax.xml.transform.TransformerException;import org.w3c.dom.Attr;import org.w3c.dom.Node;import org.w3c.dom.NodeList;import org.w3c.dom.NamedNodeMap;import org.w3c.dom.TypeInfo;import org.zkoss.mesg.Messages;import org.zkoss.mesg.MCommon;import org.zkoss.util.CollectionsX;import org.zkoss.util.CheckableTreeArray;import org.zkoss.xml.FacadeNodeList;import org.zkoss.idom.impl.*;/** * The iDOM element. * * @author tomyeh * @see Attribute */public class Element extends AbstractGroupimplements Attributable, Namespaceable, org.w3c.dom.Element {	/** The namespace. */	protected Namespace _ns;	/** The local name. */	protected String _lname;	/** The attributes. May be null. */	protected List _attrs = null;	/** Additional namespaces. May be null*/	protected Map _addNamespaces = null;	/** Whether it is aware of the attribute modification. */	boolean _attrModAware = false;	/**	 * Constructor.	 *	 * @param nsURI the namespace URI	 * @param tname the tag name	 */	public Element(String nsURI, String tname) {		int kp = tname.indexOf(':');		String prefix = kp >= 0 ? tname.substring(0, kp): "";		String lname  = kp >= 0 ? tname.substring(kp + 1): tname;		setNamespace(prefix, nsURI);		setLocalName(lname);	}	/**	 * Constructor.	 *	 * @param ns the namespace; if null, the default namespace is assumed	 * (not necessary {@link Namespace#NO_NAMESPACE}).	 * @param lname the local name	 */	public Element(Namespace ns, String lname) {		setNamespace(ns);		setLocalName(lname);	}	/**	 * Constructor without a namespace (i.e., {@link Namespace#NO_NAMESPACE}).	 *	 * @param lname the local name	 */	public Element(String lname) {		this(Namespace.NO_NAMESPACE, lname);	}	/**	 * Constructor.	 * Unlike other constructors, it doesn't set the modification flag.	 */	protected Element() {		_ns = Namespace.NO_NAMESPACE;	}	//-- Element extras --//	/**	 * Tests whether this element is the root element of	 * the owning document.	 *	 * <p>Note: false is returned if it doesn't has any parent.	 */	public final boolean isRootElement() {		return getParent() instanceof Document;	}	/**	 * Returns the Namespace in scope on this element for the given	 * prefix (this involves searching up the tree, so the results depend	 * on the current location of the element), or null if not found.	 *	 * <p>If prefix is empty, it searches for the "default" namespace	 * in scope. Thus, to search for attribute's namespace, caller	 * have to skip this one and use NO_NAMESPACE.	 * (due XML, an attribute without prefix is NO_NAMESPACE)	 *	 * @param prefix namespace prefix to look up; null for empty	 */	public final Namespace getNamespace(String prefix) {		if (prefix == null)			prefix = "";		Namespace ns = Namespace.getSpecial(prefix);		if (ns != null)			return ns;		ns = getNamespace(); //might be null if in constructor		if (ns != null && prefix.equals(ns.getPrefix()))			return ns;		if (_addNamespaces != null) {			ns = (Namespace)_addNamespaces.get(prefix);			if (ns != null)				return ns;		}		if (getParent() instanceof Element) //only Element implements it; not Namespaceable			return ((Element)getParent()).getNamespace(prefix);		return prefix.length() > 0 ? null: Namespace.NO_NAMESPACE;	}	/**	 * Returns namespace declared on this element.	 *	 * <p>It is <i>not</i> a "live" representation. Also, it is read-only.	 *	 * <p>Note: Namespace.equals compares namespace's URI. However,	 * the distinction here is the prefix, because it is mainly for	 * getNamespace(prefix).	 *	 * @return the namespace declarations.	 */	public final Collection getDeclaredNamespaces() {		return _addNamespaces == null ?			Collections.EMPTY_LIST: _addNamespaces.values();	}	/**	 * Adds a namespace to the namespace declaration.	 *	 * @return true if the namespace is added	 * @exception DOMException if the name space with the same prefix	 * already exists but with different URI	 */	public final boolean addDeclaredNamespace(Namespace ns) {		if (ns.equalsAll(_ns)) //throws DOMException if...			return false; //exists		if (_addNamespaces == null) {			_addNamespaces = new LinkedHashMap(5);		} else {			final Namespace old = (Namespace)_addNamespaces.get(ns.getPrefix());			if (old != null) {				if (!old.equals(ns))					throw new DOMException(DOMException.NAMESPACE_ERR, "Add a conflict namespace: "+ns+", while "+old+" already exists");				return false;			}		}		_addNamespaces.put(ns.getPrefix(), ns);		return true;	}	/**	 * Gets the content of this element.	 *	 * <p>The content of an element is the first Binary or Text child of	 * the element. Each element can has zero or one content.	 *	 * <p>Note: {@link #getText} returns the catenation of all Text	 * children, not just the first one.	 *	 * @return the content of this element; null if no such child	 * @see #getContent(String)	 */	public final Object getContent() {		for (final  Iterator it = _children.iterator(); it.hasNext();) {			Object o = it.next();			if (o instanceof Text) {				return ((Text)o).getText();			} else if (o instanceof Binary) {				return ((Binary)o).getValue();			} else if (o instanceof CData) {				return ((CData)o).getText();			}		}		return null;	}	/**	 * Sets the content of this element.	 *	 * <p>All existent Binary or Text children of this element are removed	 * first. If the object is a String, a Text item is created to hold	 * it. Otherwise, a Binary item is created to hold it.	 *	 * <p>Non-Binary/Text children are preserved.	 *	 * <p>If obj is a {@link Item} or an array/collection of {@link Item},	 * this method will add them as child vertices rather than	 * being the content.	 * Moreever, if the first item of the array/collection is {@link Item},	 * it is assumed to be all valid component to being has valid vertices.	 * If not, an exception is thrown.	 *	 * <p>Thus, getContent might not return the object being set by setContent.	 *	 * @param obj the object to set; null is OK	 * @return the previous content	 * @see #getContent()	 */	public final Object setContent(Object obj) {		if (obj instanceof Item) {			getChildren().add(obj);			return null; //done		}		if (obj instanceof Collection) {			final Collection c = (Collection)obj;			final Iterator it = c.iterator();			if (it.hasNext() && (it.next() instanceof Item)) {				getChildren().addAll(c);				return null; //done			}		} else if (obj instanceof Object[]) {			Object[] ary = (Object[])obj;			if (ary.length > 0 && (ary[0] instanceof Item)) {				for (int j = 0; j < ary.length; ++j)					getChildren().add(ary[j]);				return null; //done			}		}		Object ret = null;		boolean retFound = false;		boolean bStr = obj instanceof String;		for (final Iterator it = _children.iterator(); it.hasNext();) {			Object o = it.next();			if (o instanceof Text) {				if (!retFound) {					retFound = true;					ret = ((Text)o).getText();				}				if (!bStr || obj == null) {					it.remove();				} else {					((Text)o).setText((String)obj);					obj = null; //then, the following will be removed				}			} else if (o instanceof Binary) {				if (!retFound) {					retFound = true;					ret = ((Binary)o).getValue();				}				if (bStr || obj == null) {					it.remove();				} else {					((Binary)o).setValue(obj);					obj = null; //then, the following will be removed				}			} else if (o instanceof CData) {				if (!retFound) {					retFound = true;					ret = ((CData)o).getText();				}				it.remove(); //always remove and add			}		}		if (obj != null)			_children.add(0,				bStr ? (Object)new Text((String)obj): (Object)new Binary(obj));		return ret;	}	/**	 * Returns the content of the child element with the giving path, or	 * null if the content is null or the child element doesn't exist.	 *	 * <p>Note that there might be more than one child with the same path	 * in an idom tree; this method simply picks the first one that matchs and	 * returns its content. To access certain one, you might use [n] to	 * [@attr = value] specify which one to access.	 *	 *	 * <p>To know whether the child element exists or conent is null,	 * use {@link #hasContent}.	 *	 * <p>The content of an element is a special feature of iDOM.	 * Like a Map, it is designed to let developers use names (in a path-like	 * format) to access objects. See {@link #setContent(String, Object)}.	 *	 * <p>Like Unix path, the giving name could use '/' to catenate a series	 * of child elements.	 *	 * <p>An empty path denotes this element itself. Leading, ending	 * and consecutive '/' will be ignored.	 *	 * <p>Example:<br>	 * <code>Object o = element.getContent("abc/def");<br>	 * String s = Objects.toString(element.getContent("ab/cd"));<br>	 * element.setContent("t:ab/cd/f:ef", new Integer(10));</code>	 *	 * <p>TODO: support [n] and [@attr = value]	 *	 * @param path a path; e.g., "b", "a/b", "t:a/t:b"	 * @see #getContent()	 */	public final Object getContent(String path) {		Element e = this;		int j = 0;		while (true) {			int k = path.indexOf('/', j);			String tname = k >= 0 ? path.substring(j, k): path.substring(j);			if (tname.length() > 0) {				e = e.getElement(tname);				if (e == null)					return null;			}			if (k < 0)				return e.getContent();			j = k + 1;		}	}	/**	 * Tests whether the child element with the giving path exists. Note that	 * there might be more than one child with the same path in an idom tree;	 * this method simply tell you that "yes", at least on such path exist.	 *	 * To get the content, use {@link #getContent(String)}.	 */	public final boolean hasContent(String path) {		Element e = this;		int j = 0;		while (true) {			int k = path.indexOf('/', j);			String tname = k >= 0 ? path.substring(j, k): path.substring(j);			if (tname.length() > 0) {				e = e.getElement(tname);				if (e == null)					return false;			}			if (k < 0)				return true;			j = k + 1;		}	}	/**	 * Sets the content of the child element with the giving path.	 *	 * <p>Note that there might be more than one child with the same path	 * in an idom tree; this method simply pick one that matchs and set	 * its content (see {@link #setContent(Object)}).	 *	 * <p>The content of an element is a special feature of iDOM.	 * Like a Map, it is designed to let developers use names (in a path-like	 * format) to access objects. See {@link #getContent(String)}.	 *	 * <p>Like Unix path, the giving name could use '/' to catenate a series	 * of child elements.	 *	 * <p>An empty path denotes this element itself. Leading, ending	 * and consecutive '/' will be ignored.	 *	 * <p>If any element in the path is not found, it will be created	 * automatically.	 *	 * @param path a path; e.g., "b", "a/b", "t:a/t:b"	 * @param obj the object to set; null is acceptable	 * @return the previous content	 *	 * @see #setContent(Object)	 * @see #removeContent	 * @see #hasContent	 */	public final Object setContent(String path, Object obj) {		Element e = this;		int j = 0;		while (true) {			int k = path.indexOf('/', j);			String tname = k >= 0 ? path.substring(j, k): path.substring(j);			if (tname.length() > 0) {				Element e2 = e.getElement(tname);				if (e2 == null) {					e2 = new Element(e.getNamespace().getURI(), tname);					e.getChildren().add(e2);				}				e = e2;			}			if (k < 0)				return e.setContent(obj);			j = k + 1;		}	}	/**	 * Removes the content of the child element with the giving path,	 * and the child element itself if no other child.	 *	 * <p>Unlike {@link #setContent(String, Object)} with null,	 * the child element identified by path will be detached if it has no	 * other child (but the content). So does its parent	 * <i>excluding</i> this element. Thus, removeContent(path)	 * could undo setContent(path, v).	 *	 * @return the previous content	 * @see #setContent(String, Object)	 */	public final Object removeContent(String path) {		Element e = this;		int j = 0;		while (true) {			int k = path.indexOf('/', j);			String tname = k >= 0 ? path.substring(j, k): path.substring(j);			if (tname.length() > 0) {				e = e.getElement(tname);				if (e == null)					return null;			}			if (k < 0) {				Object ret = e.setContent(null);				//try to remove e; not including this				for (Group group = e;				group != this && group.getChildren().size() == 0;) {					Group parent = group.getParent();					group.detach();					group = parent;				}				return ret;			}			j = k + 1;		}	}	//-- utilities --//	/** Returns the text of a child; never null. */	private static final String getTextOfChild(Object o) {		if (!(o instanceof AbstractTextual))			return "";		final AbstractTextual t = (AbstractTextual)o;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -