From d25e31be1ebde517db2c00d3aedc71ba5d4f3da5 Mon Sep 17 00:00:00 2001 From: Dennis Schafroth Date: Thu, 16 Feb 2012 12:43:20 +0100 Subject: [PATCH] Moved common methods down to base class --- src/org/marc4j/TurboMarcXmlWriter.java | 323 +++----------------------------- 1 file changed, 25 insertions(+), 298 deletions(-) diff --git a/src/org/marc4j/TurboMarcXmlWriter.java b/src/org/marc4j/TurboMarcXmlWriter.java index 7a7deda..956069a 100644 --- a/src/org/marc4j/TurboMarcXmlWriter.java +++ b/src/org/marc4j/TurboMarcXmlWriter.java @@ -21,38 +21,23 @@ package org.marc4j; import java.io.BufferedWriter; -import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; -import java.io.Writer; -import java.util.Iterator; -import javax.xml.transform.OutputKeys; import javax.xml.transform.Result; import javax.xml.transform.Source; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.sax.SAXTransformerFactory; -import javax.xml.transform.sax.TransformerHandler; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; -import org.marc4j.converter.CharConverter; -import org.marc4j.marc.ControlField; -import org.marc4j.marc.DataField; -import org.marc4j.marc.Leader; -import org.marc4j.marc.Record; -import org.marc4j.marc.Subfield; import org.xml.sax.SAXException; -import org.xml.sax.helpers.AttributesImpl; -import com.ibm.icu.text.Normalizer; /** - * Class for writing MARC record objects in MARCXML format. This class outputs a + * Class for writing MARC record objects in Turbo MARC (XML) format. This class outputs a * SAX event stream to the given {@link java.io.OutputStream}  or * {@link javax.xml.transform.Result} object. It can be used in a SAX - * pipeline to postprocess the result. By default this class uses a nulll + * pipeline to postprocess the result. By default this class uses a null * transform. It is strongly recommended to use a dedicated XML serializer. * *

@@ -194,15 +179,18 @@ import com.ibm.icu.text.Normalizer; * @version $Revision: 1.9 $ * */ -public class TurboMarcXmlWriter implements MarcWriter { +public class TurboMarcXmlWriter extends BaseMarcXmlWriter { + + /** NS URI */ + public static final String TURBO_MARCXML_NS_URI = "http://www.indexdata.com/turbomarc"; protected static final String prefix = "tmarc:"; - protected static final String CONTROL_FIELD = "c"; - protected static final String Q_CONTROL_FIELD = prefix + CONTROL_FIELD; + protected static final String CONTROLFIELD = "c"; + protected static final String Q_CONTROL_FIELD = prefix + CONTROLFIELD; - protected static final String DATA_FIELD = "d"; - protected static final String Q_DATA_FIELD = prefix + DATA_FIELD; + protected static final String DATAFIELD = "d"; + protected static final String Q_DATA_FIELD = prefix + DATAFIELD; protected static final String SUBFIELD = "s"; protected static final String Q_SUBFIELD = prefix + SUBFIELD; @@ -216,22 +204,6 @@ public class TurboMarcXmlWriter implements MarcWriter { protected static final String LEADER = "l"; protected static final String Q_LEADER = prefix + LEADER; - private boolean indent = false; - - private TransformerHandler handler = null; - - private Writer writer = null; - - - /** - * Character encoding. Default is UTF-8. - */ - //private String encoding = "UTF8"; - - private CharConverter converter = null; - - private boolean normalize = false; - /** * Constructs an instance with the specified output stream. * @@ -271,6 +243,7 @@ public class TurboMarcXmlWriter implements MarcWriter { * @throws MarcException */ public TurboMarcXmlWriter(OutputStream out, String encoding, boolean indent) { + setup(); if (out == null) { throw new NullPointerException("null OutputStream"); } @@ -289,6 +262,18 @@ public class TurboMarcXmlWriter implements MarcWriter { writeStartDocument(); } + private void setup() { + setPrefix(prefix); + setNamespaceURI(TURBO_MARCXML_NS_URI); + setCollectionName(COLLECTION); + setRecordName(RECORD); + setLeaderName(LEADER); + setControlfieldTemplate(CONTROLFIELD); + setDatafieldTemplate(DATAFIELD); + setSubfieldTemplate(SUBFIELD); + setUseTurboMarc(true); + } + /** * Constructs an instance with the specified result. * @@ -296,6 +281,7 @@ public class TurboMarcXmlWriter implements MarcWriter { * @throws SAXException */ public TurboMarcXmlWriter(Result result) { + setup(); if (result == null) throw new NullPointerException("null Result"); setHandler(result, null); @@ -319,6 +305,7 @@ public class TurboMarcXmlWriter implements MarcWriter { * @throws SAXException */ public TurboMarcXmlWriter(Result result, Source stylesheet) { + setup(); if (stylesheet == null) throw new NullPointerException("null Source"); if (result == null) @@ -326,264 +313,4 @@ public class TurboMarcXmlWriter implements MarcWriter { setHandler(result, stylesheet); writeStartDocument(); } - - public void close() { - writeEndDocument(); - try { - if (writer != null) - writer.close(); - } catch (IOException e) { - throw new MarcException(e.getMessage(), e); - } - } - - /** - * Returns the character converter. - * - * @return CharConverter the character converter - */ - public CharConverter getConverter() { - return converter; - } - - /** - * Sets the character converter. - * - * @param converter - * the character converter - */ - public void setConverter(CharConverter converter) { - this.converter = converter; - } - - /** - * If set to true this writer will perform Unicode normalization on data - * elements using normalization form C (NFC). The default is false. - * - * The implementation used is ICU4J 2.6. This version is based on Unicode - * 4.0. - * - * @param normalize - * true if this writer performs Unicode normalization, false - * otherwise - */ - public void setUnicodeNormalization(boolean normalize) { - this.normalize = normalize; - } - - /** - * Returns true if this writer will perform Unicode normalization, false - * otherwise. - * - * @return boolean - true if this writer performs Unicode normalization, - * false otherwise. - */ - public boolean getUnicodeNormalization() { - return normalize; - } - - protected void setHandler(Result result, Source stylesheet) - throws MarcException { - try { - TransformerFactory factory = TransformerFactory.newInstance(); - if (!factory.getFeature(SAXTransformerFactory.FEATURE)) - throw new UnsupportedOperationException( - "SAXTransformerFactory is not supported"); - - SAXTransformerFactory saxFactory = (SAXTransformerFactory) factory; - if (stylesheet == null) - handler = saxFactory.newTransformerHandler(); - else - handler = saxFactory.newTransformerHandler(stylesheet); - handler.getTransformer() - .setOutputProperty(OutputKeys.METHOD, "xml"); - handler.setResult(result); - - } catch (Exception e) { - throw new MarcException(e.getMessage(), e); - } - } - - /** - * Writes the root start tag to the result. - * - * @throws SAXException - */ - protected void writeStartDocument() { - try { - AttributesImpl atts = new AttributesImpl(); - handler.startDocument(); - // The next line duplicates the namespace declaration for Marc XML - handler.startPrefixMapping("tmarc", Constants.TURBO_MARCXML_NS_URI); - // add namespace declaration using attribute - need better solution - atts.addAttribute(Constants.TURBO_MARCXML_NS_URI, "xmlns", "xmlns:tmarc", - "CDATA", Constants.TURBO_MARCXML_NS_URI); - handler.startElement(Constants.TURBO_MARCXML_NS_URI, COLLECTION, Q_COLLECTION, atts); - } catch (SAXException e) { - throw new MarcException( - "SAX error occured while writing start document", e); - } - } - - /** - * Writes the root end tag to the result. - * - * @throws SAXException - */ - protected void writeEndDocument() { - try { - if (indent) - handler.ignorableWhitespace("\n".toCharArray(), 0, 1); - - handler - .endElement(Constants.TURBO_MARCXML_NS_URI, COLLECTION, - Q_COLLECTION); - handler.endPrefixMapping(""); - handler.endDocument(); - } catch (SAXException e) { - throw new MarcException( - "SAX error occured while writing end document", e); - } - } - - /** - * Writes a Record object to the result. - * - * @param record - - * the Record object - * @throws SAXException - */ - public void write(Record record) { - try { - toXml(record); - } catch (SAXException e) { - throw new MarcException("SAX error occured while writing record", e); - } - } - - /** - * Returns true if indentation is active, false otherwise. - * - * @return boolean - */ - public boolean hasIndent() { - return indent; - } - - /** - * Activates or deactivates indentation. Default value is false. - * - * @param indent - */ - public void setIndent(boolean indent) { - this.indent = indent; - } - - protected void toXml(Record record) throws SAXException { - char temp[]; - AttributesImpl atts = new AttributesImpl(); - if (indent) - handler.ignorableWhitespace("\n ".toCharArray(), 0, 3); - - handler.startElement(Constants.TURBO_MARCXML_NS_URI, RECORD, Q_RECORD, atts); - - if (indent) - handler.ignorableWhitespace("\n ".toCharArray(), 0, 5); - - handler.startElement(Constants.TURBO_MARCXML_NS_URI, LEADER, Q_LEADER, atts); - Leader leader = record.getLeader(); - temp = leader.toString().toCharArray(); - handler.characters(temp, 0, temp.length); - handler.endElement(Constants.TURBO_MARCXML_NS_URI, LEADER, Q_LEADER); - - Iterator ci = record.getControlFields().iterator(); - while (ci.hasNext()) { - ControlField field = (ControlField) ci.next(); - atts = new AttributesImpl(); - //atts.addAttribute("", "tag", "tag", "CDATA", field.getTag()); - - if (indent) - handler.ignorableWhitespace("\n ".toCharArray(), 0, 5); - String elementName = CONTROL_FIELD + field.getTag(); - String qElementName = prefix + elementName; - handler.startElement(Constants.TURBO_MARCXML_NS_URI, elementName, qElementName, atts); - temp = getDataElement(field.getData()); - handler.characters(temp, 0, temp.length); - handler.endElement(Constants.TURBO_MARCXML_NS_URI, elementName, qElementName); - } - - Iterator di = record.getDataFields().iterator(); - while (di.hasNext()) { - DataField field = di.next(); - atts = new AttributesImpl(); - // atts.addAttribute("", "tag", "tag", "CDATA", field.getTag()); - atts.addAttribute("", "ind1", "ind1", "CDATA", String.valueOf(field - .getIndicator1())); - atts.addAttribute("", "ind2", "ind2", "CDATA", String.valueOf(field - .getIndicator2())); - - if (indent) - handler.ignorableWhitespace("\n ".toCharArray(), 0, 5); - StringBuffer elementName = new StringBuffer(DATA_FIELD); - StringBuffer qElementName = new StringBuffer(prefix); - elementName.append(field.getTag()); - qElementName.append(elementName); - handler.startElement(Constants.TURBO_MARCXML_NS_URI, elementName.toString(), - qElementName.toString(), atts); - - Iterator si = field.getSubfields().iterator(); - while (si.hasNext()) { - Subfield subfield = (Subfield) si.next(); - StringBuffer subfieldName = new StringBuffer(SUBFIELD); - StringBuffer qSubfieldName = new StringBuffer(prefix); - qSubfieldName.append(subfieldName); - - char code = subfield.getCode(); - // if [a-zA-Z0-9] append to elementName, otherwise use a attribute - if (code >= '0' && code <= '9' || - code >= 'a' && code <= 'z' || - code >= 'A' && code <= 'Z') { - subfieldName.append(code); - qSubfieldName.append(code); - } - else { - atts = new AttributesImpl(); - atts.addAttribute("", "code", "code", "CDATA", String - .valueOf(subfield.getCode())); - } - if (indent) - handler.ignorableWhitespace("\n ".toCharArray(), 0, 7); - - handler.startElement(Constants.TURBO_MARCXML_NS_URI, subfieldName.toString(), - qSubfieldName.toString(), atts); - temp = getDataElement(subfield.getData()); - handler.characters(temp, 0, temp.length); - handler - .endElement(Constants.TURBO_MARCXML_NS_URI, subfieldName.toString(), - qSubfieldName.toString()); - } - - if (indent) - handler.ignorableWhitespace("\n ".toCharArray(), 0, 5); - - handler - .endElement(Constants.TURBO_MARCXML_NS_URI, - elementName.toString(), qElementName.toString()); - } - - if (indent) - handler.ignorableWhitespace("\n ".toCharArray(), 0, 3); - - handler.endElement(Constants.TURBO_MARCXML_NS_URI, RECORD, Q_RECORD); - } - - protected char[] getDataElement(String data) { - String dataElement = null; - if (converter == null) - return data.toCharArray(); - dataElement = converter.convert(data); - if (normalize) - dataElement = Normalizer.normalize(dataElement, Normalizer.NFC); - return dataElement.toCharArray(); - } } \ No newline at end of file -- 1.7.10.4