001 /*******************************************************************************
002 * Copyright (c) 2009 Progress Software, Inc.
003 * Copyright (c) 2008 IBM Corporation and others.
004 *
005 * All rights reserved. This program and the accompanying materials
006 * are made available under the terms of the Eclipse Public License v1.0
007 * which accompanies this distribution, and is available at
008 * http://www.eclipse.org/legal/epl-v10.html
009 *
010 *******************************************************************************/
011 package org.fusesource.hawtjni.generator;
012
013 import java.io.PrintStream;
014 import java.util.Arrays;
015 import java.util.Comparator;
016
017 import org.w3c.dom.Attr;
018 import org.w3c.dom.Document;
019 import org.w3c.dom.NamedNodeMap;
020 import org.w3c.dom.Node;
021 import org.w3c.dom.NodeList;
022
023 /**
024 *
025 * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
026 */
027 public class DOMWriter {
028
029 static String ENCONDING = "UTF8";
030 PrintStream out;
031 String[] attributeFilter;
032 String nodeFilter;
033
034 public DOMWriter(PrintStream out) {
035 this.out = new PrintStream(out);
036 }
037
038 String nodeName(Node node) {
039 // TODO use getLocalName()?
040 return node.getNodeName();
041 }
042
043 boolean filter(Attr attr) {
044 if (attributeFilter == null) return false;
045 String name = attr.getNodeName();
046 for (int i = 0; i < attributeFilter.length; i++) {
047 if (name.matches(attributeFilter[i])) return false;
048 }
049 return true;
050 }
051
052 void print(String str) {
053 out.print(str);
054 }
055 void println() {
056 out.println();
057 }
058
059 public void print(Node node) {
060 print(node, 0);
061 }
062
063 public void print(Node node, int level) {
064 if (node == null)
065 return;
066 int type = node.getNodeType();
067 switch (type) {
068 case Node.DOCUMENT_NODE: {
069 print("<?xml version=\"1.0\" encoding=\"");
070 print(ENCONDING);
071 print("\"?>");
072 println();
073 print(((Document) node).getDocumentElement());
074 break;
075 }
076 case Node.ELEMENT_NODE: {
077 Attr attrs[] = sort(node.getAttributes());
078 String name = nodeName(node);
079 boolean gen = name.equals("arg") || name.equals("retval");
080 for (int i = 0; i < attrs.length && !gen; i++) {
081 Attr attr = attrs[i];
082 if (nodeName(attr).startsWith(nodeFilter)) gen = true;
083 }
084 if (!gen) break;
085 for (int i = 0; i < level; i++) print("\t");
086 print("<");
087 print(name);
088 for (int i = 0; i < attrs.length; i++) {
089 Attr attr = attrs[i];
090 if (filter(attr)) continue;
091 print(" ");
092 print(nodeName(attr));
093 print("=\"");
094 print(normalize(attr.getNodeValue()));
095 print("\"");
096 }
097 print(">");
098 NodeList children = node.getChildNodes();
099 int count = 0;
100 if (children != null) {
101 int len = children.getLength();
102 for (int i = 0; i < len; i++) {
103 if (children.item(i).getNodeType() == Node.ELEMENT_NODE) count++;
104 }
105 if (count > 0) println();
106 for (int i = 0; i < len; i++) {
107 print(children.item(i), level + 1);
108 }
109 if (count > 0) {
110 for (int i = 0; i < level; i++) print("\t");
111 }
112 }
113 print("</");
114 print(nodeName(node));
115 print(">");
116 println();
117 break;
118 }
119 }
120 out.flush();
121 }
122
123 Attr[] sort(NamedNodeMap attrs) {
124 if (attrs == null)
125 return new Attr[0];
126 Attr result[] = new Attr[attrs.getLength()];
127 for (int i = 0; i < result.length; i++) {
128 result[i] = (Attr) attrs.item(i);
129 }
130 Arrays.sort(result, new Comparator<Node>() {
131 public int compare(Node arg0, Node arg1) {
132 return nodeName(arg0).compareTo(nodeName(arg1));
133 }
134 });
135 return result;
136 }
137
138 String normalize(String s) {
139 if (s == null) return "";
140 StringBuffer str = new StringBuffer();
141 for (int i = 0, length = s.length(); i < length; i++) {
142 char ch = s.charAt(i);
143 switch (ch) {
144 case '"': str.append("\""); break;
145 case '\r':
146 case '\n':
147 // FALL THROUGH
148 default: str.append(ch);
149 }
150 }
151 return str.toString();
152 }
153
154 public void setNodeFilter(String filter) {
155
156 nodeFilter = filter;
157 }
158
159 public void setAttributeFilter(String[] filter) {
160 attributeFilter = filter;
161 }
162 }