001/******************************************************************************* 002 * Copyright (C) 2009-2011 FuseSource Corp. 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 *******************************************************************************/ 011package org.fusesource.hawtjni.generator; 012 013import java.io.PrintStream; 014import java.util.Arrays; 015import java.util.Comparator; 016 017import org.w3c.dom.Attr; 018import org.w3c.dom.Document; 019import org.w3c.dom.NamedNodeMap; 020import org.w3c.dom.Node; 021import org.w3c.dom.NodeList; 022 023/** 024 * 025 * @author <a href="http://hiramchirino.com">Hiram Chirino</a> 026 */ 027public 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}