/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.felix.ipojo.metadata; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; /** * An element represents an XML Element. * It contains a name, a namepace, {@link Attribute} objects * and sub-elements. This class is used to parse iPOJO metadata. * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a> */ public class Element { /** * The name of the element. */ private String m_name; /** * The namespace of the element. */ private String m_nameSpace; /** * The map of attributes of the element (attribute name -> {@link Attribute}). * The map key is the qualified name of the attribute (<code>ns:name</code>) * The value is the attribute object. */ private Map m_attributes = new LinkedHashMap(); /** * The map of the sub-element of the element (element name -> {@link Element}. * The map key is the element qualified name (ns:name). * The value is the array of element of this name. */ private Map m_elements = new LinkedHashMap(); /** * Creates an Element. * @param name the name of the element * @param ns the namespace of the element */ public Element(String name, String ns) { m_name = name.toLowerCase(); if (ns != null && ns.length() > 0) { m_nameSpace = ns.toLowerCase(); } } /** * Gets sub-elements. * If no sub-elements, an empty array is returned. * @return the sub elements */ public Element[] getElements() { Collection col = m_elements.values(); Iterator it = col.iterator(); List list = new ArrayList(); while (it.hasNext()) { Element[] v = (Element[]) it.next(); for (int i = 0; i < v.length; i++) { list.add(v[i]); } } return (Element[]) list.toArray(new Element[list.size()]); } /** * Gets element attributes. * If no attributes, an empty array is returned. * @return the attributes */ public Attribute[] getAttributes() { return (Attribute[]) m_attributes.values().toArray(new Attribute[0]); } /** * Gets element name. * @return the name of the element */ public String getName() { return m_name; } /** * Gets element namespace. * @return the namespace of the element */ public String getNameSpace() { return m_nameSpace; } /** * Returns the value of the attribute given in parameter. * @param name the name of the searched attribute * @return the value of the attribute given in parameter, * <code>null</code> if the attribute does not exist */ public String getAttribute(String name) { name = name.toLowerCase(); Attribute att = (Attribute) m_attributes.get(name); if (att == null) { return null; } else { return att.getValue(); } } /** * Returns the value of the attribute "name" of the namespace "ns". * @param name the name of the attribute to find * @param ns the namespace of the attribute to find * @return the String value of the attribute, or * <code>null</code> if the attribute is not found. */ public String getAttribute(String name, String ns) { name = ns.toLowerCase() + ":" + name.toLowerCase(); return getAttribute(name); } /** * Gets the qualified name of the current element. * @return the qualified name of the current element. */ private String getQualifiedName() { if (m_nameSpace == null) { return m_name; } else { return m_nameSpace + ":" + m_name; } } /** * Adds a sub-element. * @param elem the element to add */ public void addElement(Element elem) { Element[] array = (Element[]) m_elements.get(elem.getQualifiedName()); if (array == null) { m_elements.put(elem.getQualifiedName(), new Element[] {elem}); } else { Element[] newElementsList = new Element[array.length + 1]; System.arraycopy(array, 0, newElementsList, 0, array.length); newElementsList[array.length] = elem; m_elements.put(elem.getQualifiedName(), newElementsList); } } /** * Removes a sub-element. * @param elem the element to remove */ public void removeElement(Element elem) { Element[] array = (Element[]) m_elements.get(elem.getQualifiedName()); if (array == null) { return; } else { int idx = -1; for (int i = 0; i < array.length; i++) { if (array[i] == elem) { idx = i; break; } } if (idx >= 0) { if ((array.length - 1) == 0) { m_elements.remove(elem.getQualifiedName()); } else { Element[] newElementsList = new Element[array.length - 1]; System.arraycopy(array, 0, newElementsList, 0, idx); if (idx < newElementsList.length) { System.arraycopy(array, idx + 1, newElementsList, idx, newElementsList.length - idx); } m_elements.put(elem.getQualifiedName(), newElementsList); // Update the stored list. } } } } /** * Adds a attribute. * @param att the attribute to add */ public void addAttribute(Attribute att) { String name = att.getName().toLowerCase(); if (att.getNameSpace() != null) { name = att.getNameSpace().toLowerCase() + ":" + name; } m_attributes.put(name, att); } /** * Removes an attribute. * @param att the attribute to remove */ public void removeAttribute(Attribute att) { String name = att.getName(); if (att.getNameSpace() != null) { name = att.getNameSpace() + ":" + name; } m_attributes.remove(name); } /** * Gets the elements array of the element type given in parameter. * This method looks for an empty namespace. * @param name the type of the element to find (element name) * @return the resulting element array (<code>null</code> if the search failed) */ public Element[] getElements(String name) { Element[] elems = (Element[]) m_elements.get(name.toLowerCase()); return elems; } /** * Gets the elements array of the element type given in parameter. * @param name the type of the element to find (element name) * @param ns the namespace of the element * @return the resulting element array (<code>null</code> if the search failed) */ public Element[] getElements(String name, String ns) { if (ns == null || ns.length() == 0) { return getElements(name); } name = ns + ":" + name; return getElements(name); } /** * Does the element contain a sub-element of the type given in parameter. * @param name the type of the element to check. * @return <code>true</code> if the element contains an element of the type "name" */ public boolean containsElement(String name) { return m_elements.containsKey(name.toLowerCase()); } /** * Does the element contain a sub-element of the type given in parameter. * @param name the type of the element to check. * @param ns the namespace of the element to check. * @return <code>true</code> if the element contains an element of the type "name" */ public boolean containsElement(String name, String ns) { if (ns != null && ns.length() != 0) { name = ns + ":" + name; } return containsElement(name); } /** * Does the element contain an attribute of the name given in parameter. * @param name the name of the element * @return <code>true</code> if the element contains an attribute of the type "name" */ public boolean containsAttribute(String name) { return m_attributes.containsKey(name.toLowerCase()); } /** * Gets the XML form of this element. * @return the XML snippet representing this element. */ public String toXMLString() { return toXMLString(0); } /** * Internal method to get XML form of an element. * @param indent the indentation to used. * @return the XML snippet representing this element. */ private String toXMLString(int indent) { StringBuffer xml = new StringBuffer(); StringBuffer tabs = new StringBuffer(); for (int j = 0; j < indent; j++) { tabs.append("\t"); } xml.append(tabs); if (m_nameSpace == null) { xml.append("<" + m_name); } else { xml.append("<" + m_nameSpace + ":" + m_name); } Set keys = m_attributes.keySet(); Iterator it = keys.iterator(); while (it.hasNext()) { Attribute current = (Attribute) m_attributes.get(it.next()); if (current.getNameSpace() == null) { xml.append(" " + current.getName() + "=\"" + current.getValue() + "\""); } else { xml.append(" " + current.getNameSpace() + ":" + current.getName() + "=\"" + current.getValue() + "\""); } } if (m_elements.size() == 0) { xml.append("/>"); return xml.toString(); } else { xml.append(">"); keys = m_elements.keySet(); it = keys.iterator(); while (it.hasNext()) { Element[] e = (Element[]) m_elements.get(it.next()); for (int i = 0; i < e.length; i++) { xml.append("\n"); xml.append(e[i].toXMLString(indent + 1)); } } xml.append("\n" + tabs + "</" + m_name + ">"); return xml.toString(); } } /** * To String method. * @return the String form of this element. * @see java.lang.Object#toString() */ public String toString() { return toString(0); } /** * Internal method to compute the toString method. * @param indent the indentation to use. * @return the String form of this element. */ private String toString(int indent) { StringBuffer xml = new StringBuffer(); StringBuffer tabs = new StringBuffer(); for (int j = 0; j < indent; j++) { tabs.append("\t"); } xml.append(tabs); if (m_nameSpace == null) { xml.append(m_name); } else { xml.append(m_nameSpace + ":" + m_name); } Set keys = m_attributes.keySet(); Iterator it = keys.iterator(); while (it.hasNext()) { Attribute current = (Attribute) m_attributes.get(it.next()); if (current.getNameSpace() == null) { xml.append(" " + current.getName() + "=\"" + current.getValue() + "\""); } else { xml.append(" " + current.getNameSpace() + ":" + current.getName() + "=\"" + current.getValue() + "\""); } } if (m_elements.size() == 0) { return xml.toString(); } else { keys = m_elements.keySet(); it = keys.iterator(); while (it.hasNext()) { Element[] e = (Element[]) m_elements.get(it.next()); for (int i = 0; i < e.length; i++) { xml.append("\n"); xml.append(e[i].toString(indent + 1)); } } return xml.toString(); } } }