001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 */ 021package org.biojava.utils.stax; 022 023import java.util.ArrayList; 024import java.util.List; 025 026import org.xml.sax.Attributes; 027import org.xml.sax.Locator; 028import org.xml.sax.SAXException; 029import org.xml.sax.helpers.DefaultHandler; 030 031/** 032 * Lightweight adaptor which translates SAX content events into 033 * StAX form, and provides delegation services. 034 * 035 * @author Thomas Down 036 */ 037 038public class SAX2StAXAdaptor extends DefaultHandler { 039 private List stack; 040 private HandlerBinding current; 041 042 { 043 stack = new ArrayList(); 044 } 045 046 /** 047 * Construct a new SAX Content handler which wraps a StAX 048 * handler. 049 */ 050 051 public SAX2StAXAdaptor(StAXContentHandler rootHandler) { 052 current = new HandlerBinding(rootHandler); 053 stack.add(current); 054 } 055 056 public void startDocument() throws SAXException { 057 current.handler.startTree(); 058 } 059 060 public void endDocument() throws SAXException { 061 current.handler.endTree(); 062 } 063 064 public void characters(char[] ch, 065 int start, 066 int end) 067 throws SAXException 068 { 069 current.handler.characters(ch, start, end); 070 } 071 072 public void ignorableWhitespace(char[] ch, 073 int start, 074 int end) 075 throws SAXException 076 { 077 current.handler.ignorableWhitespace(ch, start, end); 078 } 079 080 public void startPrefixMapping(String prefix, String uri) 081 throws SAXException 082 { 083 current.handler.startPrefixMapping(prefix, uri); 084 } 085 086 public void endPrefixMapping(String prefix) 087 throws SAXException 088 { 089 current.handler.endPrefixMapping(prefix); 090 } 091 092 public void processingInstruction(String target, String data) 093 throws SAXException 094 { 095 current.handler.processingInstruction(target, data); 096 } 097 098 public void setDocumentLocator(Locator locator) { 099 current.handler.setDocumentLocator(locator); 100 } 101 102 public void skippedEntity(String name) 103 throws SAXException 104 { 105 current.handler.skippedEntity(name); 106 } 107 108 public void startElement(final String nsURI, 109 final String localName, 110 final String qName, 111 final Attributes attrs) 112 throws SAXException 113 { 114 S2SDelegationManager dm = new S2SDelegationManager(); 115 current.handler.startElement(nsURI, 116 localName, 117 qName, 118 attrs, 119 dm); 120 121 if (dm.getDelegate() != null) { 122 current = new HandlerBinding(dm.getDelegate()); 123 stack.add(current); 124 current.handler.startTree(); 125 startElement(nsURI, localName, qName, attrs); // Recurse until someone 126 // takes responsibility. 127 } else { 128 current.count++; 129 } 130 } 131 132 private static class S2SDelegationManager implements DelegationManager { 133 private StAXContentHandler delegate; 134 135 public void delegate(StAXContentHandler handler) 136 throws SAXException 137 { 138 if (this.delegate != null) { 139 throw new SAXException("Tried to multiply delegate a single StAX element"); 140 } 141 142 this.delegate = handler; 143 } 144 145 private StAXContentHandler getDelegate() { 146 return delegate; 147 } 148 } 149 150 public void endElement(String nsURI, String localName, String qName) 151 throws SAXException 152 { 153 current.handler.endElement(nsURI, localName, qName, null); 154 current.count--; 155 while (current.count == 0 && stack.size() > 1) { 156 StAXContentHandler oldHandler = current.handler; 157 current.handler.endTree(); 158 stack.remove(stack.size() - 1); 159 current = (HandlerBinding) stack.get(stack.size() - 1); 160 current.handler.endElement(nsURI, localName, qName, oldHandler); 161 } 162 } 163 164 private class HandlerBinding { 165 public StAXContentHandler handler; 166 public int count; 167 168 private HandlerBinding(StAXContentHandler handler) { 169 this.handler = handler; 170 this.count = 0; 171 } 172 } 173}