0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041:
0042: package org.netbeans.modules.uml.core.support.umlsupport;
0043:
0044: import java.io.BufferedWriter;
0045: import java.io.File;
0046: import java.io.IOException;
0047: import java.io.InputStreamReader;
0048: import java.io.OutputStreamWriter;
0049: import java.io.StringReader;
0050: import java.lang.ref.WeakReference;
0051: import java.text.MessageFormat;
0052: import java.util.HashMap;
0053: import java.util.List;
0054: import java.util.Vector;
0055:
0056: import java.util.logging.Level;
0057: import javax.xml.parsers.DocumentBuilder;
0058: import javax.xml.parsers.DocumentBuilderFactory;
0059:
0060: import javax.xml.parsers.ParserConfigurationException;
0061: import org.dom4j.Attribute;
0062: import org.dom4j.Branch;
0063: import org.dom4j.Document;
0064: import org.dom4j.DocumentFactory;
0065: import org.dom4j.Element;
0066: import org.dom4j.IDResolver;
0067: import org.dom4j.InvalidXPathException;
0068: import org.dom4j.Namespace;
0069: import org.dom4j.Node;
0070: import org.dom4j.QName;
0071: import org.dom4j.XPath;
0072: import org.dom4j.dom.DOMDocumentFactory;
0073: import org.dom4j.io.OutputFormat;
0074: import org.dom4j.io.SAXReader;
0075: import org.dom4j.io.XMLWriter;
0076: import org.dom4j.tree.DefaultDocument;
0077: import org.w3c.dom.DOMException;
0078:
0079: import org.netbeans.modules.uml.common.ETSystem;
0080: import org.netbeans.modules.uml.core.metamodel.structure.Project;
0081: import org.netbeans.modules.uml.core.support.UMLLogger;
0082: import org.openide.filesystems.FileObject;
0083: import org.openide.filesystems.FileUtil;
0084:
0085: /**
0086: * <p>Title: </p>
0087: * <p>Description: </p>
0088: * <p>Copyright: Copyright (c) 2003</p>
0089: * <p>Company: </p>
0090: * @author not attributable
0091: * @version 1.0
0092: */
0093:
0094: public class XMLManip {
0095: private static final String loggerName = "uml.core.support.umlsupport.XMLManip";
0096: private static HashMap<String, Namespace> m_Namespaces = new HashMap<String, Namespace>();
0097: private static Document m_XMIFragment;
0098: //static ResourceBundle messages =
0099: // ResourceBundle.getBundle("org.netbeans.modules.uml.core.MessagesBundle");
0100:
0101: private static DocumentBuilderFactory dbf = null;
0102: private static DocumentBuilder db = null;
0103: private static XMLManip xmlManip = new XMLManip();
0104:
0105: //this holds the already loaded documents with their file names
0106: //there were certain cases when documents were required for a given file
0107: // and parsing happenned multiple times.
0108: //private static HashMap < String, Document > m_LoadedDocs = new HashMap < String, Document >();
0109: private static HashMap<String, WeakReference> m_LoadedDocs = new HashMap<String, WeakReference>();
0110: private static HashMap<String, Long> m_LoadedDocsTimestamps = new HashMap<String, Long>();
0111:
0112: public static XMLManip instance() {
0113: if (xmlManip == null) {
0114: xmlManip = new XMLManip();
0115: }
0116: return xmlManip;
0117: }
0118:
0119: private XMLManip() {
0120: try {
0121: dbf = DocumentBuilderFactory.newInstance();
0122: dbf.setNamespaceAware(true);
0123: db = dbf.newDocumentBuilder();
0124: } catch (ParserConfigurationException ex) {
0125: UMLLogger.logException(loggerName, ex, Level.WARNING);
0126: }
0127:
0128: }
0129:
0130: /**
0131: * Searches under the given element for an element with the xmi.id supplied.
0132: *
0133: * @param branch The element to search under (Document or Element).
0134: * @param id The xmi.id of the element to look for.
0135: * @return The Element if found, or null.
0136: */
0137: public static Element findElementByID(Branch branch, String id) {
0138: if (branch == null || id == null)
0139: return null;
0140: Element pElement = branch.elementByID(id);
0141: // For performance, move the chec to DefaultDocument
0142: // if (pElement != null && pElement.getDocument() == null)
0143: // {
0144: // String pattern = ".//*[@xmi.id=\"" + id + "\"]";
0145: // pElement = (Element)selectSingleNode(branch, pattern);
0146: // }
0147:
0148: return pElement;
0149: }
0150:
0151: public static Document getDOMDocument(String fileName) {
0152: return getDOMDocument(fileName, new IDResolver("xmi.id"));
0153: }
0154:
0155: public static Document getDOMDocument(String fileName,
0156: IDResolver resolver) {
0157: Document doc = null;
0158: if (fileName != null && fileName.length() > 0) {
0159: File file = new File(fileName);
0160: if (!file.exists()) {
0161: return doc;
0162: }
0163: InputStreamReader ins = null;
0164: FileObject fo = FileUtil.toFileObject(file);
0165: if (fo != null && fo.getSize() > 0) {
0166: try {
0167: SAXReader reader = new SAXReader(DOMDocumentFactory
0168: .getInstance(), false);
0169: reader.setIDResolver(resolver);
0170: ins = new InputStreamReader(fo.getInputStream());
0171: doc = reader.read(ins);
0172:
0173: } catch (Exception ex) {
0174: UMLLogger.logException(loggerName, ex,
0175: Level.WARNING);
0176: } finally {
0177: if (ins != null) {
0178: try {
0179: ins.close();
0180: } catch (IOException ex) {
0181: UMLLogger.logMessage(loggerName, ex
0182: .getMessage(), Level.WARNING);
0183: }
0184: }
0185: }
0186: }
0187: }
0188: return doc;
0189: }
0190:
0191: public static Document getDOMDocumentUseWeakCache(String fileName) {
0192: Document doc = null;
0193:
0194: if (fileName != null && fileName.length() > 0) {
0195: WeakReference docRef = m_LoadedDocs.get(fileName);
0196: if (docRef != null) {
0197: doc = (Document) docRef.get();
0198: }
0199: long lm = -1;
0200: Long lmValue = m_LoadedDocsTimestamps.get(fileName);
0201: if (lmValue != null) {
0202: lm = lmValue.longValue();
0203: }
0204: long currentLastModified = new File(fileName)
0205: .lastModified();
0206: //doc = m_LoadedDocs.get(fileName);
0207: if (doc == null || (currentLastModified > lm)) {
0208: doc = getDOMDocument(fileName);
0209: m_LoadedDocs.put(fileName, new WeakReference(doc));
0210: m_LoadedDocsTimestamps.put(fileName, new Long(
0211: currentLastModified));
0212: }
0213: }
0214: return doc;
0215: }
0216:
0217: public static Document getDOMDocument() {
0218: return getDOMDocument(new IDResolver("xmi.id"));
0219: }
0220:
0221: public static Document getDOMDocument(IDResolver resolver) {
0222: Document doc = null;
0223: try {
0224: //SAXReader reader = new SAXReader();
0225: //doc = DocumentFactory.getInstance().createDocument();
0226: doc = DOMDocumentFactory.getInstance().createDocument();
0227: doc.setIDResolver(resolver);
0228:
0229: if (doc != null) {
0230: Element rootEle = DOMDocumentFactory.getInstance()
0231: .createElement("");
0232: doc.setRootElement(rootEle);
0233: Namespace space1 = DOMDocumentFactory.getInstance()
0234: .createNamespace("UML", "omg.org/UML/1.4");
0235: Namespace space2 = DOMDocumentFactory.getInstance()
0236: .createNamespace("EMBT", "www.sun.com");
0237: rootEle.add(space1);
0238: rootEle.add(space2);
0239: }
0240: //doc = db.newDocument();
0241: } catch (Exception ex) {
0242: UMLLogger.logException(loggerName, ex, Level.WARNING);
0243: }
0244: return doc;
0245: }
0246:
0247: public static Document getDOMDocumentFromString(String str) {
0248: Document doc = null;
0249: try {
0250: if (str != null && str.length() > 0) {
0251: //SAXReader reader = new SAXReader();
0252: SAXReader reader = new SAXReader(DOMDocumentFactory
0253: .getInstance(), false);
0254: doc = reader.read(str);
0255: //doc = db.parse(str);
0256: }
0257: } catch (Exception ex) {
0258: UMLLogger.logException(loggerName, ex, Level.WARNING);
0259: }
0260: return doc;
0261: }
0262:
0263: public static String getAttributeValue(Attribute attr) {
0264: String value = attr.getText();
0265: return value;
0266: }
0267:
0268: /**
0269: * Retreives a nodes attribute value as a string.
0270: *
0271: * @param n The node that is used to retrieve the attribute.
0272: * @param attr The name of the attribute value.
0273: */
0274: public static String getAttributeValue(org.dom4j.Node n, String str) {
0275: String value = null; //$NON-NLS-1$
0276: try {
0277: if (n != null
0278: && n.getNodeType() == org.dom4j.Node.ELEMENT_NODE) {
0279: org.dom4j.Element ele = (org.dom4j.Element) n;
0280: value = ele.attributeValue(str);
0281: }
0282: } catch (Exception e) {
0283: }
0284: return (value != null) ? value : "";
0285: }
0286:
0287: /**
0288: * Retreives a nodes attribute value as a boolean. If the value of the
0289: * attribute can not be converted to a boolean then <code>false</code>
0290: * will be returned.
0291: *
0292: * @param n The node that is used to retrieve the attribute.
0293: * @param str The name of the attribute value.
0294: * @return The boolean value of the attribute.
0295: */
0296: public static boolean getAttributeBooleanValue(Node n, String str) {
0297: return getAttributeBooleanValue(n, str, false);
0298: }
0299:
0300: /**
0301: * Retreives a nodes attribute value as a boolean. If the value of the
0302: * attribute can not be converted to a boolean then <code>false</code>
0303: * will be returned.
0304: *
0305: * @param n The node that is used to retrieve the attribute.
0306: * @param str The name of the attribute value.
0307: * @param defaultValue the value returned if the attribute is not found.
0308: * @return The boolean value of the attribute.
0309: */
0310: public static boolean getAttributeBooleanValue(Node n, String str,
0311: boolean defaultValue) {
0312: boolean retVal = defaultValue;
0313: if (n != null) {
0314: String val = getAttributeValue(n, str);
0315: if ((val != null) && (val.length() > 0)) {
0316: retVal = Boolean.valueOf(val).booleanValue();
0317: }
0318: }
0319: return retVal;
0320: }
0321:
0322: /**
0323: * Retreives a nodes attribute value as an integer. If the value of the
0324: * attribute can not be converted to an integer then zero will be returned.
0325: *
0326: * @param n The node that is used to retrieve the attribute.
0327: * @param attr The name of the attribute value.
0328: * @return The integer value of the attribute.
0329: * @throws NumberFormatException if the attribute does not contain a
0330: * parsable integer.
0331: */
0332: public static int getAttributeIntValue(Node n, String attr)
0333: throws NumberFormatException {
0334: int retVal = 0;
0335: if (n != null) {
0336: String val = getAttributeValue(n, attr);
0337: if (val.length() > 0) {
0338: retVal = Integer.parseInt(val);
0339: }
0340: }
0341: return retVal;
0342: }
0343:
0344: /**
0345: * Retreives a nodes attribute value as an double. If the value of the
0346: * attribute can not be converted to an integer then zero will be returned.
0347: *
0348: * @param n The node that is used to retrieve the attribute.
0349: * @param attr The name of the attribute value.
0350: * @return The integer value of the attribute.
0351: * @throws NumberFormatException if the attribute does not contain a
0352: * parsable integer.
0353: */
0354: public static double getAttributeDoubleValue(Node n, String attr)
0355: throws NumberFormatException {
0356: double retVal = 0;
0357: if (n != null) {
0358: String val = getAttributeValue(n, attr);
0359: if (val.length() > 0) {
0360: retVal = Double.parseDouble(val);
0361: }
0362: }
0363: return retVal;
0364: }
0365:
0366: /**
0367: *
0368: * Sets the XML attribute that has the passed in name to the passed in value.
0369: *
0370: * @param element[in] the element to set that attribute on.
0371: * @param attrName[in] the name of the XML attribute to set.
0372: * @param value[in] the actual value to set.
0373: *
0374: * @return HRESULT
0375: *
0376: */
0377: public static void setAttributeValue(Element elem, String name,
0378: String value) {
0379:
0380: if (elem != null) {
0381: if (value != null) {
0382: checkForIllegals(value);
0383: elem.addAttribute(name, value);
0384: } else {
0385: Attribute attr = elem.attribute(name);
0386: if (attr != null)
0387: elem.remove(attr);
0388: }
0389: }
0390: }
0391:
0392: public static void setAttributeValue(Node n, String name,
0393: String value) {
0394: if (n instanceof org.dom4j.Element) {
0395: org.dom4j.Element elem = (org.dom4j.Element) n;
0396: setAttributeValue(elem, name, value);
0397: }
0398: }
0399:
0400: /**
0401: *
0402: * Makes sure that there are no invalid characters in the value. If
0403: * there are, they are converted appropriately.
0404: * Specifically:
0405: '&' will be changed into &
0406: * '<' will be changed into <
0407: * '>' will be changed into >
0408: *
0409: * @param value The value to modify if needed.
0410: *
0411: * @return HRESULT
0412: */
0413: public static String checkForIllegals(String val) {
0414: String newval = val;
0415:
0416: if (val.length() > 0) {
0417: int pos = val.indexOf('&');
0418: if (pos >= 0) {
0419: newval = processIllegalCharacter(newval, '&');
0420: }
0421:
0422: pos = val.indexOf('<');
0423: if (pos >= 0) {
0424: newval = processIllegalCharacter(newval, '<');
0425: }
0426:
0427: pos = val.indexOf('>');
0428: if (pos >= 0) {
0429: newval = processIllegalCharacter(newval, '>');
0430: }
0431: }
0432:
0433: return newval;
0434: }
0435:
0436: /**
0437: *
0438: * Makes sure that there are no invalid characters in the value. If
0439: * there are, they are converted appropriately.
0440: * Specifically:
0441: '&' will be changed into &
0442: * '<' will be changed into <
0443: * '>' will be changed into >
0444: * ''' will be changed into ' We are currently not processing this character
0445: * '"' will be changed into " We are currently not processing this character
0446: *
0447: * @param value[in,out] The value to modify if needed.
0448: * @param ch[in] The character to replace
0449: *
0450: * @return HRESULT
0451: */
0452: private static String processIllegalCharacter(String str, char ch) {
0453: String newVal = str;
0454: if (ch == '&') {
0455: newVal = StringUtilities.splice(str, "&", "&"); //$NON-NLS-1$ //$NON-NLS-2$
0456: }
0457:
0458: if (ch == '<') {
0459: newVal = StringUtilities.splice(str, "<", "<"); //$NON-NLS-1$ //$NON-NLS-2$
0460: }
0461:
0462: if (ch == '>') {
0463: newVal = StringUtilities.splice(str, ">", ">"); //$NON-NLS-1$ //$NON-NLS-2$
0464: }
0465: return newVal;
0466: }
0467:
0468: /**
0469: *
0470: * Generates and retrieves the string representation of the DCE UUID globally
0471: * unique identifier. See section 3.5.1 in the XMI spec.
0472: *
0473: * @return the string. The form is like this: "DCE.2fac1234-31f8-11b4-a222-08002b34c003"
0474: * Perfect for the xmi.uuid attribute.
0475: *
0476: */
0477: public static String retrieveDCEID() {
0478: String retStr = ""; //$NON-NLS-1$
0479: RandomGUID guid = new RandomGUID();
0480: retStr = "DCE." + guid.toString(); //$NON-NLS-1$
0481: return retStr;
0482: }
0483:
0484: /**
0485: * Inserts a given child node at the given position in the parent's existing
0486: * child nodes. Note: to append the child node as the last child, it's easier
0487: * to directly call parent.add(child) than this method.
0488: *
0489: * It is not necessary to detach the child before calling this method.
0490: *
0491: * @param parent The parent XML Element.
0492: * @param child The child Node to be added to the parent.
0493: * @param position The number of the child node before which the new child
0494: * will be inserted.
0495: */
0496: public static void insertNode(Element parent, Node child,
0497: int position) {
0498: child.detach();
0499:
0500: List children = parent.elements();
0501: if (position >= children.size() || position < 0) {
0502: parent.add(child);
0503: return;
0504: }
0505:
0506: // The List dom4j gives us is backed by the element, so doing this
0507: // inserts child into parent's children.
0508: children.add(position, child);
0509:
0510: if (parent.getDocument() instanceof DefaultDocument) {
0511: DefaultDocument parentDoc = (DefaultDocument) parent
0512: .getDocument();
0513:
0514: if (child instanceof DefaultDocument) {
0515: DefaultDocument childDoc = (DefaultDocument) child;
0516: parentDoc.setIDTable(childDoc);
0517: } else if (child instanceof Element) {
0518: // List nodes = selectNodeList(child, "//*[@xmi.id]");
0519: // for (Iterator iter = nodes.iterator(); iter.hasNext();)
0520: // {
0521: // Element curElement = (Element)iter.next();
0522: Element curElement = (Element) child;
0523: Attribute attr = curElement.attribute("xmi.id");
0524: if (attr != null) {
0525: parentDoc.addIDtoTable(attr.getValue(), curElement);
0526: }
0527: // }
0528: }
0529: }
0530:
0531: }
0532:
0533: /**
0534: * Inserts a given child node before the reference node in the parent's
0535: * existing child nodes. Note: to append the child node as the last child,
0536: * it's easier to directly call parent.add(child) than this method.
0537: *
0538: * It is not necessary to detach the child before calling this method.
0539: *
0540: * @param parent The parent XML Element.
0541: * @param child The child Node to be added to the parent.
0542: * @param position The number of the child node before which the new child
0543: * will be inserted.
0544: */
0545: public static void insertNode(Element parent, Node child, Node ref) {
0546: child.detach();
0547:
0548: List children = parent.elements();
0549: for (int i = 0, count = children.size(); i < count; ++i) {
0550: Node cur = (Node) children.get(i);
0551: if (cur.equals(ref)) {
0552: children.add(i, child);
0553: return;
0554: }
0555: }
0556:
0557: parent.add(child);
0558: }
0559:
0560: /**
0561: * @param node
0562: * @param string
0563: * @return
0564: */
0565: public static Node getAttribute(Node node, String name) {
0566: Node retNode = null;
0567: if (node instanceof org.dom4j.Element) {
0568: org.dom4j.Element ele = (org.dom4j.Element) node;
0569: retNode = ele.attribute(name);
0570: }
0571: return retNode;
0572: }
0573:
0574: /**
0575: * @param pNode
0576: * @param pattern
0577: * @return
0578: */
0579: //public static List selectNodeList(Node pNode, String pattern) {
0580: // List list = null;
0581: // /*if (pNode.getNodeType() == Node.ELEMENT_NODE)
0582: // {
0583: // org.dom4j.Element elem = (org.dom4j.Element)pNode;
0584: // list = elem.getElementsByTagName(pattern);
0585: // }*/
0586: //
0587: // //first get the document for this node.
0588: // if (pNode != null)
0589: // {
0590: // Document doc = pNode.getOwnerDocument();
0591: //
0592: // //now create a Dom4j document from this.
0593: // DOMReader reader = new DOMReader();
0594: // org.dom4j.Document document = reader.read(doc);
0595: // List myList = document.selectNodes(pattern);
0596: // }
0597: // return list;
0598: //}
0599: //public static org.dom4j.Node selectSingleNode(Node pNode, String pattern) {
0600: // org.dom4j.Node node = null;
0601: // /*try
0602: // {
0603: // if (pNode != null)
0604: // {
0605: // org.dom4j.Element elem = (org.dom4j.Element)pNode;
0606: // node = XPathAPI.selectSingleNode(pNode, pattern);
0607: // }
0608: // }
0609: // catch (TransformerException e)
0610: // {
0611: // }*/
0612: // //first get the document for this node.
0613: // if (pNode != null)
0614: // {
0615: // Document doc = null;
0616: // if (pNode.getNodeType() == Node.DOCUMENT_NODE)
0617: // {
0618: // doc = (Document)pNode;
0619: // }
0620: // else
0621: // {
0622: // doc = pNode.getOwnerDocument();
0623: // }
0624: //
0625: // //now create a Dom4j document from this.
0626: // DOMReader reader = new DOMReader();
0627: // org.dom4j.Document document = reader.read(doc);
0628: // node = document.selectSingleNode(pattern);
0629: // }
0630: // return node;
0631: //}
0632: public static org.dom4j.Node selectSingleNode(org.dom4j.Node pNode,
0633: String pattern) {
0634: org.dom4j.Node node = null;
0635:
0636: if (pNode != null && pattern != null) {
0637: node = pNode.selectSingleNode(pattern);
0638: }
0639: return node;
0640: }
0641:
0642: public static List selectNodeList(org.dom4j.Node pNode,
0643: String pattern) {
0644: List list = null;
0645:
0646: if (pNode != null) {
0647: try {
0648: list = pNode.selectNodes(pattern);
0649: } catch (InvalidXPathException ex) {
0650: UMLLogger.logException(loggerName, ex, Level.WARNING);
0651: }
0652: }
0653: return list;
0654: }
0655:
0656: public static List selectNodeListNS(Node pNode, String pattern) {
0657: List list = null;
0658: /*try {
0659: list = XPathAPI.selectNodeList(pNode, pattern);
0660: } catch (TransformerException e) {
0661: }*/
0662:
0663: if (pNode != null) {
0664: Document doc = null;
0665: if (pNode.getNodeType() == Node.DOCUMENT_NODE) {
0666: doc = (Document) pNode;
0667: } else {
0668: doc = pNode.getDocument();
0669: }
0670:
0671: //now create a Dom4j document from this.
0672: //DOMReader reader = new DOMReader();
0673: //org.dom4j.Document document = reader.read(doc);
0674: list = doc.selectNodes(pattern);
0675: }
0676:
0677: return list;
0678: }
0679:
0680: /**
0681: * @param doc
0682: * @param header
0683: * @return
0684: */
0685: public static Document loadXML(String text) {
0686: return loadXML(text, false, new IDResolver("xmi.id"));
0687: }
0688:
0689: /**
0690: * Loads a DOM Document from the given XML text.
0691: *
0692: * @param text The XML text to parse and create a Document from.
0693: * @param validate <code>true</code> to validate the XML against any DTDs.
0694: * @return The <code>Document</code> created.
0695: */
0696: public static Document loadXML(String text, boolean validate) {
0697: return loadXML(text, validate, new IDResolver("xmi.id"));
0698: }
0699:
0700: /**
0701: * Loads a DOM Document from the given XML text.
0702: *
0703: * @param text The XML text to parse and create a Document from.
0704: * @param The ID resolver used to determine IDs.
0705: * @return The <code>Document</code> created.
0706: */
0707: public static Document loadXML(String text, IDResolver resolver) {
0708: return loadXML(text, false, resolver);
0709: }
0710:
0711: /**
0712: * Loads a DOM Document from the given XML text.
0713: *
0714: * @param text The XML text to parse and create a Document from.
0715: * @param validate <code>true</code> to validate the XML against any DTDs.
0716: * @return The <code>Document</code> created.
0717: */
0718: public static Document loadXML(String text, boolean validate,
0719: IDResolver resolver) {
0720: try {
0721: //SAXReader reader = new SAXReader(validate);
0722: SAXReader reader = new SAXReader(DOMDocumentFactory
0723: .getInstance(), validate, resolver);
0724: return reader.read(new StringReader(text));
0725: } catch (Exception ex) {
0726: UMLLogger.logException(loggerName, ex, Level.WARNING);
0727: }
0728: return null;
0729: }
0730:
0731: /**
0732: * Returns the locale specific value for the String message.
0733: * @param message
0734: */
0735: public static String getString(String message) {
0736: try {
0737: //return messages.getString(message);
0738: } catch (java.util.MissingResourceException mr) {
0739: return "!!" + message + "!! not found"; //$NON-NLS-1$ //$NON-NLS-2$
0740: }
0741: return null;
0742: }
0743:
0744: /**
0745: * Returns the locale specific message for the given message key, applying
0746: * a MessageFormat to it with the supplied parameters, if any.
0747: *
0748: * @param key The resource bundle key for the desired message.
0749: * @param params Additional parameters to customize the message.
0750: * @return String The locale-specific text
0751: */
0752: public static String getString(String key, Object[] params) {
0753: String text = getString(key);
0754: return (params != null) ? MessageFormat.format(text, params)
0755: : text;
0756: }
0757:
0758: /**
0759: * Retrieves the text of a given node.
0760: *
0761: * @param curNode[in] The node to query
0762: * @param query[in] The query to perform on curNode to find the node in
0763: * whose text value we require.
0764: * @param value[out] The text value
0765: *
0766: * @return HRESULTs
0767: */
0768: public static String retrieveNodeTextValue(Node curNode,
0769: String query) {
0770: try {
0771: Node node = curNode.selectSingleNode(query);
0772: //XPathAPI.selectSingleNode(curNode, query);
0773: if (node != null) {
0774: return node.getText();
0775: }
0776: } catch (Exception e) {
0777: }
0778: return "";//$NON-NLS-1$
0779: }
0780:
0781: ///////////////////////////////////////////////////////////////////////////////
0782: //
0783: // HRESULT XMLManip::RemoveChild( IXMLDOMNode* curNode, const xstring& query, IXMLDOMNode** removed )
0784: //
0785: // Removes the child node from the passed in node.
0786: //
0787: // INPUT:
0788: // curNode - the node whose child we are removing
0789: // query - query to perform to get the node
0790: //
0791: // OUTPUT:
0792: // removed - the removed node if successful
0793: //
0794: // RETURN:
0795: // HRESULTs
0796: //
0797: // CAVEAT:
0798: // None.
0799: //
0800: ///////////////////////////////////////////////////////////////////////////////
0801: public static Node removeChild(Node node, String query) {
0802: Node remNode = null;
0803: try {
0804: Node n = node.selectSingleNode(query);
0805: //XPathAPI.selectSingleNode(node, query);
0806: if (n != null) {
0807: remNode = removeNode(node, n);
0808: }
0809: } catch (Exception e) {
0810: }
0811: return remNode;
0812: }
0813:
0814: ///////////////////////////////////////////////////////////////////////////////
0815: //
0816: // HRESULT XMLManip::RemoveNode( IXMLDOMNode* parent, IXMLDOMNode* node, IXMLDOMNode** removed )
0817: //
0818: // Performs the basic node removal
0819: //
0820: // INPUT:
0821: // parent - the parent of the node that is being removed
0822: // node - the node to remove
0823: //
0824: // OUTPUT:
0825: // removed - holds the removed node if not 0
0826: //
0827: // RETURN:
0828: // HRESULTs
0829: //
0830: // CAVEAT:
0831: // None.
0832: //
0833: ///////////////////////////////////////////////////////////////////////////////
0834: private static Node removeNode(Node parent, Node node) {
0835: Node remNode = null;
0836: if (node != null && parent != null) {
0837: remNode = node.detach(); //parent.removeChild(node);
0838: }
0839: return remNode;
0840: }
0841:
0842: ///////////////////////////////////////////////////////////////////////////////
0843: //
0844: // xstring RetrieveSimpleName( IXMLDOMNode* node )
0845: //
0846: // Given an element name such as "UML:Model", "Model" will be returned.
0847: //
0848: // INPUT:
0849: // node - the node to retrieve its name and to filter.
0850: //
0851: // OUTPUT:
0852: // None.
0853: //
0854: // RETURN:
0855: // The sliced name, else ""
0856: //
0857: // CAVEAT:
0858: // None.
0859: //
0860: ///////////////////////////////////////////////////////////////////////////////
0861: //public static String retrieveSimpleName(Node node) {
0862: // String retName = "";
0863: // if (node != null)
0864: // {
0865: // String name = node.getNodeName();
0866: // if (name != null && name.length() > 0)
0867: // {
0868: // int pos = name.indexOf(":");
0869: // if (pos >= 0)
0870: // {
0871: // retName = name.substring(pos+1);
0872: // }
0873: // }
0874: // }
0875: // return retName;
0876: //}
0877:
0878: public static String retrieveSimpleName(org.dom4j.Node node) {
0879: String retName = ""; //$NON-NLS-1$
0880: if (node != null) {
0881: String name = node.getName();
0882: if (name != null && name.length() > 0) {
0883: int pos = name.indexOf(":"); //$NON-NLS-1$
0884: retName = pos >= 0 ? name.substring(pos + 1) : name;
0885: }
0886: }
0887: return retName;
0888: }
0889:
0890: /**
0891: * Sets the text value of a node.
0892: *
0893: * @param curNode[in] The node to query with
0894: * @param query[in] The query to find the node to set
0895: * @param value[in] The new value
0896: * @param useCData[in] true ( the default ) to automatically wrap value in a ![CDATA[...]] block,
0897: * else false to just set the data.
0898: *
0899: * @return HRESULTs
0900: */
0901: public static void setNodeTextValue(Node curNode, String query,
0902: String newVal, boolean useCData) {
0903: Node valNode = ensureNodeExists(curNode, query, query);
0904: if (valNode != null) {
0905: valNode.setText(removeIllegalXMLChars(newVal));
0906: }
0907: }
0908:
0909: /**
0910: * removes illegal for XML 1.0 (Chapter 2.2) characters
0911: * in the 0x0-0x1F range (excluding 0x9, 0xA, 0xD)
0912: *
0913: * @param input[in] The string the illegal chars to be removed from
0914: *
0915: * @return The string with illegal chars removed
0916: */
0917: private static String removeIllegalXMLChars(String input) {
0918: if (input == null) {
0919: return null;
0920: } else if (input.equals("")) {
0921: return "";
0922: }
0923: StringBuffer output = new StringBuffer("");
0924: for (int i = 0; i < input.length(); i++) {
0925: int ch = (int) input.charAt(i);
0926: if ((ch >= 0x20) || (ch == 0x9) || (ch == 0xA)
0927: || (ch == 0xD)) {
0928: output.append((char) ch);
0929: }
0930: }
0931: return output.toString();
0932: }
0933:
0934: ///////////////////////////////////////////////////////////////////////////////
0935: //
0936: // HRESULT EnsureElementExists( IXMLDOMNode* curNode,
0937: // const xstring& name,
0938: // const xstring& query,
0939: // IXMLDOMNode** node )
0940: //
0941: // Makes sure that the node with the passed in name is present
0942: // under curNode. If it isn't, one is created.
0943: //
0944: // INPUT:
0945: // curNode - the node to append to.
0946: // name - name of the node to check for existence for.
0947: // query - the query string to used to check for existence
0948: //
0949: // OUTPUT:
0950: // node - the node representing the element
0951: //
0952: // RETURN:
0953: // HRESULTs
0954: //
0955: // CAVEAT:
0956: // None.
0957: //
0958: ///////////////////////////////////////////////////////////////////////////////
0959: public static Node ensureNodeExists(Node curNode, String name,
0960: String query) {
0961: Node retNode = null;
0962: try {
0963: retNode = curNode.selectSingleNode(query);
0964: //XPathAPI.selectSingleNode(curNode, query);
0965: if (retNode == null) {
0966: // Node doesn't exist, so we need to create it.
0967: Document doc = curNode.getDocument();
0968: if (doc != null) {
0969: retNode = doc.getRootElement().addElement(name);
0970: appendNewLineElement(curNode, doc);
0971: retNode.detach();
0972: ((Element) curNode).add(retNode);
0973: }
0974: }
0975: } catch (Exception ex) {
0976: UMLLogger.logException(loggerName, ex, Level.WARNING);
0977: }
0978: return retNode;
0979: }
0980:
0981: /**
0982: *
0983: * Appends a newline to the passed in element
0984: *
0985: * @param parent[in] The parent to own the text node
0986: *
0987: * @return HRESULT
0988: *
0989: */
0990: public static void appendNewLineElement(Node parent, Document doc) {
0991: // if (doc == null)
0992: // {
0993: // doc = parent.getDocument();
0994: // }
0995: //
0996: // if (doc != null)
0997: // {
0998: // // org.dom4j.Element newLine = doc.addElement("\r\n"); //$NON-NLS-1$
0999: // // //parent.appendChild(newLine);
1000: // // newLine.setParent((org.dom4j.Element)parent);
1001: // }
1002: if (parent instanceof Element) {
1003: ((Element) parent).addText("\n"); //$NON-NLS-1$
1004: }
1005: }
1006:
1007: /**
1008: *
1009: * Creates a new DOM Element in a given XML namspace. This is a lower
1010: * level routine than the CreateElement that does not take a namespace
1011: * as an argument. This call does NOT add the new element to the passed
1012: * in DOM document.
1013: *
1014: * @param element [in] The element that will recieve the new element.
1015: * @param name[in] The name of the element to create.
1016: * @param xmlNamespace[in] The XML namespace that the new element should
1017: * belong to. For example, "omg.org/UML/1.4". The
1018: * default is "omg.org/UML/1.4"
1019: *
1020: * @return The new DOM node.
1021: *
1022: */
1023: public static Element createElement(Element element, String name,
1024: String xmlNamespace) {
1025: Element retVal = null;
1026:
1027: if (name.length() <= 0) {
1028: throw new NullPointerException(UMLSupportResource
1029: .getString("INVALID_CREATE_ELEMENT_PARAM"));
1030: }
1031:
1032: int pos = name.indexOf(':');
1033:
1034: if ((xmlNamespace == null || xmlNamespace.length() == 0)
1035: && pos > 0) {
1036: QName qname = getQName(element, name);
1037: retVal = DOMDocumentFactory.getInstance().createElement(
1038: qname);
1039: } else if ((xmlNamespace.length() > 0) && (pos > 0)) {
1040: String prefix = name.substring(0, pos);
1041: Namespace namespace = DOMDocumentFactory.getInstance()
1042: .createNamespace(prefix, xmlNamespace);
1043: QName qName = DOMDocumentFactory.getInstance().createQName(
1044: name.substring(pos + 1), namespace);
1045: retVal = DOMDocumentFactory.getInstance().createElement(
1046: qName);
1047: } else {
1048: retVal = DOMDocumentFactory.getInstance().createElement(
1049: name);
1050: }
1051:
1052: if ((element != null) && (retVal != null)) {
1053: element.add(retVal);
1054: }
1055:
1056: return retVal;
1057: }
1058:
1059: /**
1060: *
1061: * Creates a new DOM Element in a given XML namspace. This is a lower
1062: * level routine than the CreateElement that does not take a namespace
1063: * as an argument. This call does NOT add the new element to the passed
1064: * in DOM document.
1065: *
1066: * @param doc[in] The document that will receive the new element.
1067: * @param name[in] The name of the element to create.
1068: * @param xmlNamespace[in] The XML namespace that the new element should
1069: * belong to. For example, "omg.org/UML/1.4". The
1070: * default is "omg.org/UML/1.4"
1071: *
1072: * @return The new DOM node.
1073: *
1074: */
1075: public static Element createElement(Document doc, String name,
1076: String xmlNamespace) {
1077: Element retVal = null;
1078:
1079: if (name.length() <= 0) {
1080: throw new NullPointerException(UMLSupportResource
1081: .getString("INVALID_CREATE_ELEMENT_PARAM"));
1082: }
1083:
1084: int pos = name.indexOf(':');
1085:
1086: if ((xmlNamespace == null || xmlNamespace.length() == 0)
1087: && pos > 0) {
1088: QName qname = getQName(doc.getRootElement(), name);
1089: //retVal = DOMDocumentHelper.createElement(qname);
1090: retVal = DOMDocumentFactory.getInstance().createElement(
1091: qname);
1092: } else if ((xmlNamespace.length() > 0) && (pos > 0)) {
1093: // I am using StringBuffer because it is suppose to be
1094: // faster when building strings.
1095: StringBuffer uri = new StringBuffer("http://"); //$NON-NLS-1$
1096: uri.append(xmlNamespace);
1097:
1098: String prefix = name.substring(0, pos);
1099: // Namespace namespace =
1100: // DocumentHelper.createNamespace(prefix, uri.toString());
1101: Namespace namespace = DOMDocumentFactory.getInstance()
1102: .createNamespace(prefix, uri.toString());
1103: //QName qName = DocumentHelper.createQName(name.substring(pos + 1), namespace);
1104: QName qName = DOMDocumentFactory.getInstance().createQName(
1105: name.substring(pos + 1), namespace);
1106: //retVal = DocumentHelper.createElement(qName);
1107: retVal = DOMDocumentFactory.getInstance().createElement(
1108: qName);
1109: } else {
1110: //retVal = DocumentHelper.createElement(name);
1111: retVal = DOMDocumentFactory.getInstance().createElement(
1112: name);
1113: }
1114:
1115: return retVal;
1116: }
1117:
1118: /**
1119: * Obtains a DOM4J QName given a namespace prefixed nodeName.
1120: * @param nodeName The name of the node, probably qualified by a namespace
1121: * prefix.
1122: * @return A DOM4J QName, with the Namespace correctly set if the namespace
1123: * prefix matched a known namespace.
1124: */
1125: public static QName getQName(Element ref, String nodeName) {
1126: int nsPrefix;
1127: if ((nsPrefix = nodeName.indexOf(':')) == -1)
1128: return new QName(nodeName);
1129:
1130: String prefix = nodeName.substring(0, nsPrefix);
1131: String shortName = nodeName.substring(nsPrefix + 1);
1132:
1133: Namespace ns = XMLManip.getNamespace(ref, prefix);
1134: return ns == null ? new QName(nodeName) : new QName(shortName,
1135: ns, nodeName);
1136: }
1137:
1138: /**
1139: * Obtains a DOM4J Namespace given a namespace prefix by querying the XMI
1140: * fragment.
1141: * @param namespacePrefix A namespace prefix.
1142: * @return A DOM4J Namespace, if the namespacePrefix was known to us.
1143: */
1144: public static Namespace getNamespace(Element ref,
1145: String namespacePrefix) {
1146: Namespace retSpace = null;
1147: if (namespacePrefix == null)
1148: return null;
1149: if (m_Namespaces.containsKey(namespacePrefix))
1150: return m_Namespaces.get(namespacePrefix);
1151:
1152: if (ref != null) {
1153: return ref.getNamespaceForPrefix(namespacePrefix);
1154: }
1155:
1156: // Okay, have we loaded the XMI fragment?
1157: if (m_XMIFragment == null) {
1158: // TODO: This is an evil, dirty trick. Fix it.
1159: // Create a dummy project object.
1160: Project proj = new Project();
1161: proj.establishXMIHeaderInfo(); // Evil
1162:
1163: m_XMIFragment = proj.getDocument();
1164: }
1165:
1166: // Walk the tree, looking for 'namespacePrefix'
1167: if (m_XMIFragment != null) {
1168: retSpace = walkTree(m_XMIFragment.getRootElement(),
1169: namespacePrefix);
1170: m_Namespaces.put(namespacePrefix, retSpace);
1171: }
1172: return retSpace;
1173: }
1174:
1175: private static Namespace walkTree(Element elem, String prefix) {
1176: if (prefix.equals(elem.getNamespacePrefix()))
1177: return elem.getNamespace();
1178: Namespace ns = elem.getNamespaceForPrefix(prefix);
1179: if (ns != null)
1180: return ns;
1181: for (int i = elem.nodeCount() - 1; i >= 0; --i) {
1182: Node node = elem.node(i);
1183: if (node instanceof Element)
1184: walkTree((Element) node, prefix);
1185: }
1186: return null;
1187: }
1188:
1189: public static Element createElement(Element parentNode, String name)
1190: throws DOMException {
1191: Element retVal = null;
1192:
1193: if ((parentNode == null) || (name.length() <= 0)) {
1194: throw new NullPointerException(UMLSupportResource
1195: .getString("INVALID_CREATE_ELEMENT_PARAM"));
1196: }
1197:
1198: String xmlNamespace = "";
1199:
1200: // int pos = name.indexOf(':');
1201: // if(pos >= 0)
1202: // {
1203: // Namespace space = parentNode.getNamespaceForPrefix(name.substring(0, pos));
1204: // if(space != null)
1205: // {
1206: // xmlNamespace = space.getURI();
1207: // }
1208: // }
1209:
1210: retVal = createElement(parentNode.getDocument(), name,
1211: xmlNamespace);
1212: if (retVal != null) {
1213: retVal.detach();
1214: //appendNewLineElement(retVal, parentNode.getDocument());
1215:
1216: parentNode.add(retVal);
1217: }
1218:
1219: return retVal;
1220: }
1221:
1222: public static Element createElement(Document doc, String name) {
1223: if ((doc == null) || (name.length() <= 0)) {
1224: throw new NullPointerException(UMLSupportResource
1225: .getString("INVALID_CREATE_ELEMENT_PARAM"));
1226: }
1227:
1228: Element newNode = createElement(doc, name, "");
1229: if (newNode != null) {
1230: if (doc.getRootElement() == null)
1231: doc.add(newNode);
1232: else
1233: doc.getRootElement().add(newNode);
1234: }
1235:
1236: return newNode;
1237: }
1238:
1239: public static void saveNodePretty(Node node, String filename) {
1240: if (filename != null && filename.trim().length() > 0) {
1241: FileObject fo = FileUtil.toFileObject(new File(filename));
1242: if (fo != null) {
1243: OutputStreamWriter out = null;
1244: XMLWriter xmlWriter = null;
1245: try {
1246: out = new OutputStreamWriter(fo.getOutputStream());
1247: xmlWriter = new XMLWriter(out, OutputFormat
1248: .createPrettyPrint());
1249: xmlWriter.write(node);
1250: xmlWriter.flush();
1251: } catch (Exception ex) {
1252: UMLLogger.logException(loggerName, ex,
1253: Level.WARNING);
1254: } finally {
1255: try {
1256: if (out != null) {
1257: out.close();
1258: }
1259: if (xmlWriter != null) {
1260: xmlWriter.close();
1261: }
1262: } catch (IOException ex) {
1263: UMLLogger.logMessage(loggerName, ex
1264: .getMessage(), Level.WARNING);
1265: }
1266: }
1267: }
1268: }
1269: }
1270:
1271: public static void saveNode(Node node, String filename) {
1272: if (filename != null && filename.trim().length() > 0) {
1273: FileObject fo = FileUtil.toFileObject(new File(filename));
1274: if (fo != null) {
1275: OutputStreamWriter out = null;
1276: XMLWriter xmlWriter = null;
1277: try {
1278: out = new OutputStreamWriter(fo.getOutputStream());
1279: OutputFormat format = new OutputFormat();
1280: format.setNewlines(true);
1281: xmlWriter = new XMLWriter(out, format);
1282: xmlWriter.write(node);
1283: xmlWriter.flush();
1284: } catch (Exception ex) {
1285: UMLLogger.logException(loggerName, ex,
1286: Level.WARNING);
1287: } finally {
1288: try {
1289: if (out != null) {
1290: out.close();
1291: }
1292: if (xmlWriter != null) {
1293: xmlWriter.close();
1294: }
1295: } catch (IOException ex) {
1296: UMLLogger.logMessage(loggerName, ex
1297: .getMessage(), Level.WARNING);
1298: }
1299: }
1300: }
1301: }
1302: }
1303:
1304: /**
1305: * @param document
1306: * @param fileName
1307: */
1308: public static boolean save(Document document, String filename) {
1309: boolean successful = false;
1310: if (filename != null && filename.trim().length() > 0) {
1311: OutputStreamWriter out = null;
1312: BufferedWriter xmlWriter = null;
1313: try {
1314: FileObject fo = FileUtil.createData(new File(filename));
1315: out = new OutputStreamWriter(fo.getOutputStream());
1316: xmlWriter = new BufferedWriter(out);
1317: xmlWriter.write(document.asXML(), 0, document.asXML()
1318: .length());
1319: xmlWriter.flush();
1320: successful = true;
1321: } catch (Exception ex) {
1322: UMLLogger.logException(loggerName, ex, Level.WARNING);
1323: } finally {
1324: try {
1325: if (out != null) {
1326: out.close();
1327: }
1328: if (xmlWriter != null) {
1329: xmlWriter.close();
1330: }
1331: } catch (IOException ex) {
1332: UMLLogger.logMessage(loggerName, ex.getMessage(),
1333: Level.WARNING);
1334: }
1335: }
1336: }
1337: return successful;
1338: }
1339:
1340: public static boolean savePretty(Document document, String filename) {
1341: boolean successful = false;
1342: if (filename != null && filename.trim().length() > 0) {
1343: OutputStreamWriter out = null;
1344: XMLWriter xmlWriter = null;
1345: try {
1346: FileObject fo = FileUtil.createData(new File(filename));
1347:
1348: out = new OutputStreamWriter(fo.getOutputStream());
1349: xmlWriter = new XMLWriter(out, OutputFormat
1350: .createPrettyPrint());
1351: xmlWriter.write(document);
1352: xmlWriter.flush();
1353: successful = true;
1354: } catch (Exception ex) {
1355: UMLLogger.logException(loggerName, ex, Level.WARNING);
1356: } finally {
1357: try {
1358: if (out != null) {
1359: out.close();
1360: }
1361: if (xmlWriter != null) {
1362: xmlWriter.close();
1363: }
1364: } catch (IOException ex) {
1365: UMLLogger.logMessage(loggerName, ex.getMessage(),
1366: Level.WARNING);
1367: }
1368: }
1369: }
1370: return successful;
1371: }
1372:
1373: /**
1374: * @param element
1375: * @param b
1376: */
1377: public static void DebugXML(Element element, boolean perform) {
1378: if (perform == true) {
1379: ETSystem.out.println(element.asXML());
1380: }
1381:
1382: }
1383:
1384: /**
1385: *
1386: * Removes all child nodes from parentNode.
1387: *
1388: * @param parentNode[in] the element to modify.
1389: *
1390: * @return HRESULTs
1391: *
1392: */
1393: public static void removeAllChildNodes(Element nodeElement) {
1394: if (nodeElement != null) {
1395: List children = nodeElement.selectNodes(".//*");
1396: if (children != null) {
1397: int count = children.size();
1398: for (int i = count - 1; i >= 0; i--) {
1399: Node node = (Node) children.get(i);
1400: nodeElement.remove(node);
1401: }
1402: }
1403: }
1404: }
1405:
1406: /**
1407: * Returns the first child node of the given XML node.
1408: * @param node The node in question. Only DOM4J Element Nodes have child
1409: * nodes, so passing in any other Node will return null.
1410: * @return The first child node, or null if there are no children.
1411: */
1412: public static Node getFirstChild(Node node) {
1413: if (node instanceof Element) {
1414: Element el = (Element) node;
1415: if (el.nodeCount() > 0)
1416: return el.node(0);
1417: }
1418: return null;
1419: }
1420:
1421: /**
1422: * A query of "ancestor::*[@attrName='attrValue']" type
1423: *
1424: * @param node
1425: * @param attrName
1426: * @param attrValue
1427: *
1428: * @return The list of ancestors with required attribute value.
1429: */
1430: public static List selectAncestorNodesByAttribute(Node node,
1431: String attrName, String attrValue) {
1432: Vector result = new Vector();
1433: if (node != null && attrName != null && (!attrName.equals(""))
1434: && attrValue != null) {
1435: Node parent = node.getParent();
1436: while (parent != null) {
1437: if (parent instanceof org.dom4j.Element) {
1438: org.dom4j.Element parentElem = (org.dom4j.Element) parent;
1439: String value = parentElem.attributeValue(attrName);
1440: if (value != null && attrValue.equals(value)) {
1441: result.add(parentElem);
1442: }
1443: }
1444: parent = parent.getParent();
1445: }
1446: }
1447: return result;
1448: }
1449:
1450: private static HashMap<String, XPath> cachedXPaths;
1451:
1452: public static XPath getCreateCachedXPath(String query) {
1453: if (cachedXPaths == null) {
1454: cachedXPaths = new HashMap<String, XPath>();
1455: }
1456: XPath res = cachedXPaths.get(query);
1457: if (res == null) {
1458: DocumentFactory fact = DOMDocumentFactory.getInstance();
1459: res = fact.createXPath(query);
1460: if (res != null) {
1461: cachedXPaths.put(query, res);
1462: }
1463: }
1464: return res;
1465: }
1466:
1467: public static void clearCachedXPaths() {
1468: cachedXPaths = null;
1469: }
1470: }
|