| /* |
| * Copyright 2000-2013 JetBrains s.r.o. |
| * |
| * Licensed 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 com.intellij.openapi.util; |
| |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.util.text.StringUtil; |
| import com.intellij.openapi.vfs.CharsetToolkit; |
| import com.intellij.util.ArrayUtil; |
| import com.intellij.util.containers.StringInterner; |
| import com.intellij.util.io.URLUtil; |
| import com.intellij.util.io.fs.IFile; |
| import com.intellij.util.text.CharArrayUtil; |
| import com.intellij.util.text.CharSequenceReader; |
| import com.intellij.util.text.StringFactory; |
| import org.jdom.*; |
| import org.jdom.filter.ElementFilter; |
| import org.jdom.filter.Filter; |
| import org.jdom.input.DOMBuilder; |
| import org.jdom.input.SAXBuilder; |
| import org.jdom.output.DOMOutputter; |
| import org.jdom.output.Format; |
| import org.jdom.output.XMLOutputter; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| import org.xml.sax.EntityResolver; |
| import org.xml.sax.InputSource; |
| |
| import java.io.*; |
| import java.lang.ref.SoftReference; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| /** |
| * @author mike |
| */ |
| @SuppressWarnings({"HardCodedStringLiteral"}) |
| public class JDOMUtil { |
| private static final ThreadLocal<SoftReference<SAXBuilder>> ourSaxBuilder = new ThreadLocal<SoftReference<SAXBuilder>>(); |
| |
| private JDOMUtil() { } |
| |
| @NotNull |
| public static List<Element> getChildren(@Nullable Element parent) { |
| if (parent == null) { |
| return Collections.emptyList(); |
| } |
| else { |
| return parent.getChildren(); |
| } |
| } |
| |
| @NotNull |
| public static List<Element> getChildren(@Nullable Element parent, @NotNull String name) { |
| if (parent != null) { |
| return parent.getChildren(name); |
| } |
| return Collections.emptyList(); |
| } |
| |
| @SuppressWarnings("UtilityClassWithoutPrivateConstructor") |
| private static class LoggerHolder { |
| private static final Logger ourLogger = Logger.getInstance("#com.intellij.openapi.util.JDOMUtil"); |
| } |
| |
| private static Logger getLogger() { |
| return LoggerHolder.ourLogger; |
| } |
| |
| public static boolean areElementsEqual(Element e1, Element e2) { |
| if (e1 == null && e2 == null) return true; |
| if (e1 == null || e2 == null) return false; |
| |
| return Comparing.equal(e1.getName(), e2.getName()) |
| && attListsEqual(e1.getAttributes(), e2.getAttributes()) |
| && contentListsEqual(e1.getContent(CONTENT_FILTER), e2.getContent(CONTENT_FILTER)); |
| } |
| |
| private static final EmptyTextFilter CONTENT_FILTER = new EmptyTextFilter(); |
| |
| public static int getTreeHash(@NotNull final Element root) { |
| return addToHash(0, root); |
| } |
| |
| public static int getTreeHash(@NotNull Document document) { |
| return getTreeHash(document.getRootElement()); |
| } |
| |
| private static int addToHash(int i, @NotNull final Element element) { |
| i = addToHash(i, element.getName()); |
| |
| for (Attribute aList : element.getAttributes()) { |
| i = addToHash(i, aList); |
| } |
| |
| List<Content> content = element.getContent(); |
| for (Content child : content) { |
| if (child instanceof Element) { |
| i = addToHash(i, (Element)child); |
| } |
| else if (child instanceof Text) { |
| i = addToHash(i, ((Text)child).getText()); |
| } |
| } |
| |
| return i; |
| } |
| |
| private static int addToHash(int i, @NotNull final Attribute attribute) { |
| i = addToHash(i, attribute.getName()); |
| i = addToHash(i, attribute.getValue()); |
| return i; |
| } |
| |
| private static int addToHash(final int i, @NotNull final String s) { |
| return i * 31 + s.hashCode(); |
| } |
| |
| @NotNull |
| public static Object[] getChildNodesWithAttrs(@NotNull Element e) { |
| ArrayList<Object> result = new ArrayList<Object>(); |
| result.addAll(e.getContent()); |
| result.addAll(e.getAttributes()); |
| return ArrayUtil.toObjectArray(result); |
| } |
| |
| @NotNull |
| public static Content[] getContent(@NotNull Element m) { |
| List<Content> list = m.getContent(); |
| return list.toArray(new Content[list.size()]); |
| } |
| |
| @NotNull |
| public static Element[] getElements(@NotNull Element m) { |
| List<Element> list = m.getChildren(); |
| return list.toArray(new Element[list.size()]); |
| } |
| |
| @NotNull |
| public static String concatTextNodesValues(@NotNull final Object[] nodes) { |
| StringBuilder result = new StringBuilder(); |
| for (Object node : nodes) { |
| result.append(((Content)node).getValue()); |
| } |
| return result.toString(); |
| } |
| |
| public static void addContent(@NotNull final Element targetElement, final Object node) { |
| if (node instanceof Content) { |
| Content content = (Content)node; |
| targetElement.addContent(content); |
| } |
| else if (node instanceof List) { |
| //noinspection unchecked |
| targetElement.addContent((List)node); |
| } |
| else { |
| throw new IllegalArgumentException("Wrong node: " + node); |
| } |
| } |
| |
| public static void internElement(@NotNull Element element, @NotNull StringInterner interner) { |
| element.setName(intern(interner, element.getName())); |
| |
| for (Attribute attr : element.getAttributes()) { |
| attr.setName(intern(interner, attr.getName())); |
| attr.setValue(intern(interner, attr.getValue())); |
| } |
| |
| for (Content o : element.getContent()) { |
| if (o instanceof Element) { |
| Element e = (Element)o; |
| internElement(e, interner); |
| } |
| else if (o instanceof Text) { |
| Text text = (Text)o; |
| text.setText(intern(interner, text.getText())); |
| } |
| else if (o instanceof Comment) { |
| Comment comment = (Comment)o; |
| comment.setText(intern(interner, comment.getText())); |
| } |
| else { |
| throw new IllegalArgumentException("Wrong node: " + o); |
| } |
| } |
| } |
| |
| @NotNull |
| private static String intern(@NotNull final StringInterner interner, @NotNull final String s) { |
| return interner.intern(s); |
| } |
| |
| @NotNull |
| public static String legalizeText(@NotNull String str) { |
| return legalizeChars(str).toString(); |
| } |
| |
| @NotNull |
| public static CharSequence legalizeChars(@NotNull CharSequence str) { |
| StringBuilder result = new StringBuilder(str.length()); |
| for (int i = 0, len = str.length(); i < len; i ++) { |
| appendLegalized(result, str.charAt(i)); |
| } |
| return result; |
| } |
| |
| public static void appendLegalized(@NotNull StringBuilder sb, char each) { |
| if (each == '<' || each == '>') { |
| sb.append(each == '<' ? "<" : ">"); |
| } |
| else if (!Verifier.isXMLCharacter(each)) { |
| sb.append("0x").append(StringUtil.toUpperCase(Long.toHexString(each))); |
| } |
| else { |
| sb.append(each); |
| } |
| } |
| |
| private static class EmptyTextFilter implements Filter { |
| @Override |
| public boolean matches(Object obj) { |
| return !(obj instanceof Text) || !CharArrayUtil.containsOnlyWhiteSpaces(((Text)obj).getText()); |
| } |
| } |
| |
| private static boolean contentListsEqual(final List c1, final List c2) { |
| if (c1 == null && c2 == null) return true; |
| if (c1 == null || c2 == null) return false; |
| |
| Iterator l1 = c1.listIterator(); |
| Iterator l2 = c2.listIterator(); |
| while (l1.hasNext() && l2.hasNext()) { |
| if (!contentsEqual((Content)l1.next(), (Content)l2.next())) { |
| return false; |
| } |
| } |
| |
| return l1.hasNext() == l2.hasNext(); |
| } |
| |
| private static boolean contentsEqual(Content c1, Content c2) { |
| if (!(c1 instanceof Element) && !(c2 instanceof Element)) { |
| return c1.getValue().equals(c2.getValue()); |
| } |
| |
| return c1 instanceof Element && c2 instanceof Element && areElementsEqual((Element)c1, (Element)c2); |
| |
| } |
| |
| private static boolean attListsEqual(@NotNull List a1, @NotNull List a2) { |
| if (a1.size() != a2.size()) return false; |
| for (int i = 0; i < a1.size(); i++) { |
| if (!attEqual((Attribute)a1.get(i), (Attribute)a2.get(i))) return false; |
| } |
| return true; |
| } |
| |
| private static boolean attEqual(@NotNull Attribute a1, @NotNull Attribute a2) { |
| return a1.getName().equals(a2.getName()) && a1.getValue().equals(a2.getValue()); |
| } |
| |
| public static boolean areDocumentsEqual(@NotNull Document d1, @NotNull Document d2) { |
| if(d1.hasRootElement() != d2.hasRootElement()) return false; |
| |
| if(!d1.hasRootElement()) return true; |
| |
| CharArrayWriter w1 = new CharArrayWriter(); |
| CharArrayWriter w2 = new CharArrayWriter(); |
| |
| try { |
| writeDocument(d1, w1, "\n"); |
| writeDocument(d2, w2, "\n"); |
| } |
| catch (IOException e) { |
| getLogger().error(e); |
| } |
| |
| return w1.size() == w2.size() && w1.toString().equals(w2.toString()); |
| |
| } |
| |
| @NotNull |
| public static Document loadDocument(char[] chars, int length) throws IOException, JDOMException { |
| return getSaxBuilder().build(new CharArrayReader(chars, 0, length)); |
| } |
| |
| @NotNull |
| public static Document loadDocument(byte[] bytes) throws IOException, JDOMException { |
| final ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes); |
| try { |
| return loadDocument(inputStream); |
| } |
| finally { |
| inputStream.close(); |
| } |
| |
| } |
| |
| private static SAXBuilder getSaxBuilder() { |
| SoftReference<SAXBuilder> reference = ourSaxBuilder.get(); |
| SAXBuilder saxBuilder = com.intellij.reference.SoftReference.dereference(reference); |
| if (saxBuilder == null) { |
| saxBuilder = new SAXBuilder(); |
| saxBuilder.setEntityResolver(new EntityResolver() { |
| @Override |
| @NotNull |
| public InputSource resolveEntity(String publicId, String systemId) { |
| return new InputSource(new CharArrayReader(ArrayUtil.EMPTY_CHAR_ARRAY)); |
| } |
| }); |
| ourSaxBuilder.set(new SoftReference<SAXBuilder>(saxBuilder)); |
| } |
| return saxBuilder; |
| } |
| |
| @NotNull |
| public static Document loadDocument(@NotNull CharSequence seq) throws IOException, JDOMException { |
| return getSaxBuilder().build(new CharSequenceReader(seq)); |
| } |
| |
| @NotNull |
| public static Document loadDocument(File file) throws JDOMException, IOException { |
| final BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(file)); |
| try { |
| return loadDocument(inputStream); |
| } |
| finally { |
| inputStream.close(); |
| } |
| } |
| |
| @NotNull |
| public static Document loadDocument(@NotNull final IFile iFile) throws IOException, JDOMException { |
| final BufferedInputStream inputStream = new BufferedInputStream(iFile.openInputStream()); |
| try { |
| return loadDocument(inputStream); |
| } |
| finally { |
| inputStream.close(); |
| } |
| } |
| |
| @NotNull |
| public static Document loadDocument(@NotNull InputStream stream) throws JDOMException, IOException { |
| InputStreamReader reader = new InputStreamReader(stream, CharsetToolkit.UTF8_CHARSET); |
| try { |
| return getSaxBuilder().build(reader); |
| } |
| finally { |
| reader.close(); |
| } |
| } |
| |
| @NotNull |
| public static Document loadDocument(@NotNull Class clazz, String resource) throws JDOMException, IOException { |
| InputStream stream = clazz.getResourceAsStream(resource); |
| if (stream == null) { |
| throw new FileNotFoundException(resource); |
| } |
| return loadDocument(stream); |
| } |
| |
| @NotNull |
| public static Document loadDocument(URL url) throws JDOMException, IOException { |
| return loadDocument(URLUtil.openStream(url)); |
| } |
| |
| @NotNull |
| public static Document loadResourceDocument(URL url) throws JDOMException, IOException { |
| return loadDocument(URLUtil.openResourceStream(url)); |
| } |
| |
| public static void writeDocument(@NotNull Document document, @NotNull String filePath, String lineSeparator) throws IOException { |
| OutputStream stream = new BufferedOutputStream(new FileOutputStream(filePath)); |
| try { |
| writeDocument(document, stream, lineSeparator); |
| } |
| finally { |
| stream.close(); |
| } |
| } |
| |
| public static void writeDocument(@NotNull Document document, @NotNull File file, String lineSeparator) throws IOException { |
| writeParent(document, file, lineSeparator); |
| } |
| |
| public static void writeParent(@NotNull Parent element, @NotNull File file, String lineSeparator) throws IOException { |
| OutputStream stream = new BufferedOutputStream(new FileOutputStream(file)); |
| try { |
| writeParent(element, stream, lineSeparator); |
| } |
| finally { |
| stream.close(); |
| } |
| } |
| |
| public static void writeDocument(@NotNull Document document, @NotNull OutputStream stream, String lineSeparator) throws IOException { |
| writeParent(document, stream, lineSeparator); |
| } |
| |
| public static void writeParent(@NotNull Parent element, @NotNull OutputStream stream, @NotNull String lineSeparator) throws IOException { |
| OutputStreamWriter writer = new OutputStreamWriter(stream, CharsetToolkit.UTF8_CHARSET); |
| try { |
| if (element instanceof Document) { |
| writeDocument((Document)element, writer, lineSeparator); |
| } |
| else { |
| writeElement((Element) element, writer, lineSeparator); |
| } |
| } |
| finally { |
| writer.close(); |
| } |
| } |
| |
| @NotNull |
| public static byte[] printDocument(@NotNull Document document, String lineSeparator) throws IOException { |
| CharArrayWriter writer = new CharArrayWriter(); |
| writeDocument(document, writer, lineSeparator); |
| |
| return StringFactory.createShared(writer.toCharArray()).getBytes(CharsetToolkit.UTF8_CHARSET); |
| } |
| |
| @NotNull |
| public static String writeDocument(@NotNull Document document, String lineSeparator) { |
| try { |
| final StringWriter writer = new StringWriter(); |
| writeDocument(document, writer, lineSeparator); |
| return writer.toString(); |
| } |
| catch (IOException e) { |
| // Can't be |
| return ""; |
| } |
| } |
| |
| @NotNull |
| public static String writeParent(Parent element, String lineSeparator) { |
| try { |
| final StringWriter writer = new StringWriter(); |
| writeParent(element, writer, lineSeparator); |
| return writer.toString(); |
| } |
| catch (IOException ignored) { |
| throw new RuntimeException(ignored); |
| } |
| } |
| |
| public static void writeParent(Parent element, Writer writer, String lineSeparator) throws IOException { |
| if (element instanceof Element) { |
| writeElement((Element) element, writer, lineSeparator); |
| } else if (element instanceof Document) { |
| writeDocument((Document) element, writer, lineSeparator); |
| } |
| } |
| |
| public static void writeElement(@NotNull Element element, Writer writer, String lineSeparator) throws IOException { |
| XMLOutputter xmlOutputter = createOutputter(lineSeparator); |
| try { |
| xmlOutputter.output(element, writer); |
| } |
| catch (NullPointerException ex) { |
| getLogger().error(ex); |
| printDiagnostics(element, ""); |
| } |
| } |
| |
| @NotNull |
| public static String writeElement(@NotNull Element element) { |
| return writeElement(element, "\n"); |
| } |
| |
| @NotNull |
| public static String writeElement(@NotNull Element element, String lineSeparator) { |
| try { |
| final StringWriter writer = new StringWriter(); |
| writeElement(element, writer, lineSeparator); |
| return writer.toString(); |
| } |
| catch (IOException ignored) { |
| throw new RuntimeException(ignored); |
| } |
| } |
| |
| @NotNull |
| public static String writeChildren(@Nullable final Element element, @NotNull final String lineSeparator) { |
| try { |
| final StringWriter writer = new StringWriter(); |
| for (Element child : getChildren(element)) { |
| writeElement(child, writer, lineSeparator); |
| writer.append(lineSeparator); |
| } |
| return writer.toString(); |
| } |
| catch (IOException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| public static void writeDocument(@NotNull Document document, @NotNull Writer writer, String lineSeparator) throws IOException { |
| XMLOutputter xmlOutputter = createOutputter(lineSeparator); |
| try { |
| xmlOutputter.output(document, writer); |
| } |
| catch (NullPointerException ex) { |
| getLogger().error(ex); |
| printDiagnostics(document.getRootElement(), ""); |
| } |
| } |
| |
| @NotNull |
| public static XMLOutputter createOutputter(String lineSeparator) { |
| XMLOutputter xmlOutputter = new MyXMLOutputter(); |
| Format format = Format.getCompactFormat(). |
| setIndent(" "). |
| setTextMode(Format.TextMode.TRIM). |
| setEncoding(CharsetToolkit.UTF8). |
| setOmitEncoding(false). |
| setOmitDeclaration(false). |
| setLineSeparator(lineSeparator); |
| xmlOutputter.setFormat(format); |
| return xmlOutputter; |
| } |
| |
| /** |
| * Returns null if no escapement necessary. |
| */ |
| @Nullable |
| private static String escapeChar(char c, boolean escapeApostrophes, boolean escapeSpaces, boolean escapeLineEnds) { |
| switch (c) { |
| case '\n': return escapeLineEnds ? " " : null; |
| case '\r': return escapeLineEnds ? " " : null; |
| case '\t': return escapeLineEnds ? "	" : null; |
| case ' ' : return escapeSpaces ? "" : null; |
| case '<': return "<"; |
| case '>': return ">"; |
| case '\"': return """; |
| case '\'': return escapeApostrophes ? "'": null; |
| case '&': return "&"; |
| } |
| return null; |
| } |
| |
| @NotNull |
| public static String escapeText(@NotNull String text) { |
| return escapeText(text, false, false); |
| } |
| |
| @NotNull |
| public static String escapeText(@NotNull String text, boolean escapeSpaces, boolean escapeLineEnds) { |
| return escapeText(text, false, escapeSpaces, escapeLineEnds); |
| } |
| |
| @NotNull |
| public static String escapeText(@NotNull String text, boolean escapeApostrophes, boolean escapeSpaces, boolean escapeLineEnds) { |
| StringBuffer buffer = null; |
| for (int i = 0; i < text.length(); i++) { |
| final char ch = text.charAt(i); |
| final String quotation = escapeChar(ch, escapeApostrophes, escapeSpaces, escapeLineEnds); |
| |
| if (buffer == null) { |
| if (quotation != null) { |
| // An quotation occurred, so we'll have to use StringBuffer |
| // (allocate room for it plus a few more entities). |
| buffer = new StringBuffer(text.length() + 20); |
| // Copy previous skipped characters and fall through |
| // to pickup current character |
| buffer.append(text.substring(0, i)); |
| buffer.append(quotation); |
| } |
| } |
| else { |
| if (quotation == null) { |
| buffer.append(ch); |
| } |
| else { |
| buffer.append(quotation); |
| } |
| } |
| } |
| // If there were any entities, return the escaped characters |
| // that we put in the StringBuffer. Otherwise, just return |
| // the unmodified input string. |
| return buffer == null ? text : buffer.toString(); |
| } |
| |
| @NotNull |
| public static List<Element> getChildrenFromAllNamespaces(@NotNull final Element element, @NotNull @NonNls final String name) { |
| final ArrayList<Element> result = new ArrayList<Element>(); |
| final List children = element.getChildren(); |
| for (final Object aChildren : children) { |
| Element child = (Element)aChildren; |
| if (name.equals(child.getName())) { |
| result.add(child); |
| } |
| } |
| return result; |
| } |
| |
| public static class MyXMLOutputter extends XMLOutputter { |
| @Override |
| @NotNull |
| public String escapeAttributeEntities(@NotNull String str) { |
| return escapeText(str, false, true); |
| } |
| |
| @Override |
| @NotNull |
| public String escapeElementEntities(@NotNull String str) { |
| return escapeText(str, false, false); |
| } |
| } |
| |
| private static void printDiagnostics(@NotNull Element element, String prefix) { |
| ElementInfo info = getElementInfo(element); |
| prefix += "/" + info.name; |
| if (info.hasNullAttributes) { |
| //noinspection UseOfSystemOutOrSystemErr |
| System.err.println(prefix); |
| } |
| |
| List<Element> children = getChildren(element); |
| for (final Element child : children) { |
| printDiagnostics(child, prefix); |
| } |
| } |
| |
| @NotNull |
| private static ElementInfo getElementInfo(@NotNull Element element) { |
| ElementInfo info = new ElementInfo(); |
| StringBuilder buf = new StringBuilder(element.getName()); |
| List attributes = element.getAttributes(); |
| if (attributes != null) { |
| int length = attributes.size(); |
| if (length > 0) { |
| buf.append("["); |
| for (int idx = 0; idx < length; idx++) { |
| Attribute attr = (Attribute)attributes.get(idx); |
| if (idx != 0) { |
| buf.append(";"); |
| } |
| buf.append(attr.getName()); |
| buf.append("="); |
| buf.append(attr.getValue()); |
| if (attr.getValue() == null) { |
| info.hasNullAttributes = true; |
| } |
| } |
| buf.append("]"); |
| } |
| } |
| info.name = buf.toString(); |
| return info; |
| } |
| |
| public static void updateFileSet(@NotNull File[] oldFiles, @NotNull String[] newFilePaths, @NotNull Document[] newFileDocuments, String lineSeparator) |
| throws IOException { |
| getLogger().assertTrue(newFilePaths.length == newFileDocuments.length); |
| |
| ArrayList<String> writtenFilesPaths = new ArrayList<String>(); |
| |
| // check if files are writable |
| for (String newFilePath : newFilePaths) { |
| File file = new File(newFilePath); |
| if (file.exists() && !file.canWrite()) { |
| throw new IOException("File \"" + newFilePath + "\" is not writeable"); |
| } |
| } |
| for (File file : oldFiles) { |
| if (file.exists() && !file.canWrite()) { |
| throw new IOException("File \"" + file.getAbsolutePath() + "\" is not writeable"); |
| } |
| } |
| |
| for (int i = 0; i < newFilePaths.length; i++) { |
| String newFilePath = newFilePaths[i]; |
| |
| writeDocument(newFileDocuments[i], newFilePath, lineSeparator); |
| writtenFilesPaths.add(newFilePath); |
| } |
| |
| // delete files if necessary |
| |
| outer: |
| for (File oldFile : oldFiles) { |
| String oldFilePath = oldFile.getAbsolutePath(); |
| for (final String writtenFilesPath : writtenFilesPaths) { |
| if (oldFilePath.equals(writtenFilesPath)) { |
| continue outer; |
| } |
| } |
| boolean result = oldFile.delete(); |
| if (!result) { |
| throw new IOException("File \"" + oldFilePath + "\" was not deleted"); |
| } |
| } |
| } |
| |
| private static class ElementInfo { |
| @NotNull public String name = ""; |
| public boolean hasNullAttributes = false; |
| } |
| |
| public static org.w3c.dom.Element convertToDOM(@NotNull Element e) { |
| try { |
| final Document d = new Document(); |
| final Element newRoot = new Element(e.getName()); |
| final List attributes = e.getAttributes(); |
| |
| for (Object o : attributes) { |
| Attribute attr = (Attribute)o; |
| newRoot.setAttribute(attr.getName(), attr.getValue(), attr.getNamespace()); |
| } |
| |
| d.addContent(newRoot); |
| newRoot.addContent(e.cloneContent()); |
| |
| return new DOMOutputter().output(d).getDocumentElement(); |
| } |
| catch (JDOMException e1) { |
| throw new RuntimeException(e1); |
| } |
| } |
| |
| public static Element convertFromDOM(org.w3c.dom.Element e) { |
| return new DOMBuilder().build(e); |
| } |
| |
| public static String getValue(Object node) { |
| if (node instanceof Content) { |
| Content content = (Content)node; |
| return content.getValue(); |
| } |
| else if (node instanceof Attribute) { |
| Attribute attribute = (Attribute)node; |
| return attribute.getValue(); |
| } |
| else { |
| throw new IllegalArgumentException("Wrong node: " + node); |
| } |
| } |
| |
| @Nullable |
| public static Element cloneElement(@NotNull Element element, @NotNull ElementFilter elementFilter) { |
| Element result = new Element(element.getName(), element.getNamespace()); |
| List<Attribute> attributes = element.getAttributes(); |
| if (!attributes.isEmpty()) { |
| ArrayList<Attribute> list = new ArrayList<Attribute>(attributes.size()); |
| for (Attribute attribute : attributes) { |
| list.add(attribute.clone()); |
| } |
| result.setAttributes(list); |
| } |
| |
| for (Namespace namespace : element.getAdditionalNamespaces()) { |
| result.addNamespaceDeclaration(namespace); |
| } |
| |
| boolean hasContent = false; |
| for (Content content : element.getContent()) { |
| if (content instanceof Element) { |
| if (elementFilter.matches(content)) { |
| hasContent = true; |
| } |
| else { |
| continue; |
| } |
| } |
| result.addContent(content.clone()); |
| } |
| return hasContent ? result : null; |
| } |
| |
| public static boolean isEmpty(@NotNull Element element) { |
| return element.getAttributes().isEmpty() && element.getContent().isEmpty(); |
| } |
| } |