Moved common methods down to base class
authorDennis Schafroth <dennis@indexdata.com>
Thu, 16 Feb 2012 11:43:20 +0000 (12:43 +0100)
committerDennis Schafroth <dennis@indexdata.com>
Thu, 16 Feb 2012 11:43:20 +0000 (12:43 +0100)
src/org/marc4j/TurboMarcXmlWriter.java

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