/************************************************************************ * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ package org.openoffice.xmerge.converter.xml.sxw.aportisdoc; import org.w3c.dom.NodeList; import org.w3c.dom.Node; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Element; import java.io.IOException; import org.openoffice.xmerge.Document; import org.openoffice.xmerge.ConvertData; import org.openoffice.xmerge.ConvertException; import org.openoffice.xmerge.DocumentSerializer; import org.openoffice.xmerge.converter.xml.OfficeConstants; import org.openoffice.xmerge.converter.xml.sxw.SxwDocument; import org.openoffice.xmerge.converter.palm.PdbEncoder; import org.openoffice.xmerge.converter.palm.PdbDecoder; import org.openoffice.xmerge.converter.palm.PalmDB; import org.openoffice.xmerge.converter.palm.Record; import org.openoffice.xmerge.converter.palm.PalmDocument; import org.openoffice.xmerge.util.Debug; import org.openoffice.xmerge.util.XmlUtil; /** *

AportisDoc implementation of * org.openoffice.xmerge.DocumentSerializer * for the {@link * org.openoffice.xmerge.converter.xml.sxw.aportisdoc.PluginFactoryImpl * PluginFactoryImpl}.

* *

The serialize method traverses the DOM * document from the given Document object. It uses a * DocEncoder object for the actual conversion of * contents to the AportisDoc format.

* * @author Herbie Ong */ public final class DocumentSerializerImpl implements OfficeConstants, DocConstants, DocumentSerializer { /** A DocEncoder object for encoding to AportisDoc. */ private DocEncoder encoder = null; /** SXW Document object that this converter processes. */ private SxwDocument sxwDoc = null; /** * Constructor. * * @param doc A SXW Document to be converted. */ public DocumentSerializerImpl(Document doc) { sxwDoc = (SxwDocument) doc; } /** *

Method to convert a Document into a PDB. * It passes back the converted data as a ConvertData * object.

* *

This method is not thread safe for performance reasons. * This method should not be called from within two threads. * It would be best to call this method only once per object * instance.

* * @return The ConvertData object containing the output. * * @throws ConvertException If any conversion error occurs. * @throws IOException If any I/O error occurs. */ public ConvertData serialize() throws ConvertException, IOException { // get the server document name String docName = sxwDoc.getName(); // get DOM document org.w3c.dom.Document domDoc = sxwDoc.getContentDOM(); encoder = new DocEncoder(); // Traverse to the office:body element. // There should only be one. NodeList list = domDoc.getElementsByTagName(TAG_OFFICE_BODY); int len = list.getLength(); if (len > 0) { Node node = list.item(0); traverseBody(node); } // create a ConvertData object. // Record records[] = encoder.getRecords(); ConvertData cd = new ConvertData(); PalmDocument palmDoc = new PalmDocument(docName, DocConstants.CREATOR_ID, DocConstants.TYPE_ID, 0, PalmDB.PDB_HEADER_ATTR_BACKUP, records); cd.addDocument(palmDoc); return cd; } /** * This method traverses office:body element. * * @param node office:body Node. * * @throws IOException If any I/O error occurs. */ private void traverseBody(Node node) throws IOException { log(""); log(""); if (node.hasChildNodes()) { NodeList nodeList = node.getChildNodes(); int len = nodeList.getLength(); for (int i = 0; i < len; i++) { Node child = nodeList.item(i); if (child.getNodeType() == Node.ELEMENT_NODE) { String nodeName = child.getNodeName(); if (nodeName.equals(TAG_PARAGRAPH) || nodeName.equals(TAG_HEADING)) { traverseParagraph(child); } else if (nodeName.equals(TAG_UNORDERED_LIST)) { traverseList(child); } else if (nodeName.equals(TAG_ORDERED_LIST)) { traverseList(child); } else { log(""); } } } } log(""); } /** * This method traverses the text:p and text:h * element Node objects. * * @param node A text:p or text:h * Node. * * @throws IOException If any I/O error occurs. */ private void traverseParagraph(Node node) throws IOException { log(""); traverseParaContents(node); encoder.addText(EOL_CHAR); log(""); } /** * This method traverses a paragraph content. * It uses the traverseParaElem method to * traverse into Element Node objects. * * @param node A paragraph or content Node. * * @throws IOException If any I/O error occurs. */ private void traverseParaContents(Node node) throws IOException { if (node.hasChildNodes()) { NodeList nodeList = node.getChildNodes(); int len = nodeList.getLength(); for (int i = 0; i < len; i++) { Node child = nodeList.item(i); short nodeType = child.getNodeType(); switch (nodeType) { case Node.TEXT_NODE: // this is for grabbing text nodes. String s = child.getNodeValue(); if (s.length() > 0) { encoder.addText(s); } log(""); log(s); log(""); break; case Node.ELEMENT_NODE: traverseParaElem(child); break; case Node.ENTITY_REFERENCE_NODE: log(""); traverseParaContents(child); log(""); break; default: log(""); } } } } /** * This method traverses an Element Node * within a paragraph. * * @param node Element Node within a * paragraph. * * @throws IOException If any I/O error occurs. */ private void traverseParaElem(Node node) throws IOException { String nodeName = node.getNodeName(); if (nodeName.equals(TAG_SPACE)) { // this is for text:s tags. NamedNodeMap map = node.getAttributes(); Node attr = map.getNamedItem(ATTRIBUTE_SPACE_COUNT); StringBuffer space = new StringBuffer(SPACE_CHAR); int count = 1; if (attr != null) { try { String countStr = attr.getNodeValue(); count = Integer.parseInt(countStr.trim()); } catch (NumberFormatException e) { // TODO: for now, throw IOException. // later, perhaps will have to throw // some other conversion exception instead. throw new IOException(e.getMessage()); } } for (int j = 0; j < count; j++) { space.append(SPACE_CHAR); } encoder.addText(space.toString()); log(""); } else if (nodeName.equals(TAG_TAB_STOP)) { // this is for text:tab-stop encoder.addText(TAB_CHAR); log(""); } else if (nodeName.equals(TAG_LINE_BREAK)) { // commented out by Csaba: There is no point to convert a linebreak // into a EOL, because it messes up the number of XML nodes and the // merge won't work properly. Other solution would be to implement such // nodemerger, which would be able to merge embedded tags in a paragraph // this is for text:line-break // encoder.addText(EOL_CHAR); log("skipped "); } else if (nodeName.equals(TAG_SPAN)) { // this is for text:span log(""); traverseParaContents(node); log(""); } else if (nodeName.equals(TAG_HYPERLINK)) { // this is for text:a log(""); traverseParaContents(node); log(""); } else if (nodeName.equals(TAG_BOOKMARK) || nodeName.equals(TAG_BOOKMARK_START)) { log(""); } else if (nodeName.equals(TAG_TEXT_VARIABLE_SET) || nodeName.equals(TAG_TEXT_VARIABLE_GET) || nodeName.equals(TAG_TEXT_EXPRESSION) || nodeName.equals(TAG_TEXT_USER_FIELD_GET) || nodeName.equals(TAG_TEXT_PAGE_VARIABLE_GET) || nodeName.equals(TAG_TEXT_SEQUENCE) || nodeName.equals( TAG_TEXT_VARIABLE_INPUT) || nodeName.equals(TAG_TEXT_TIME) || nodeName.equals( TAG_TEXT_PAGE_COUNT) || nodeName.equals(TAG_TEXT_PAGE_NUMBER ) || nodeName.equals(TAG_TEXT_SUBJECT) || nodeName.equals(TAG_TEXT_TITLE) || nodeName.equals(TAG_TEXT_CREATION_TIME) || nodeName.equals(TAG_TEXT_DATE) || nodeName.equals(TAG_TEXT_TEXT_INPUT) || nodeName.equals(TAG_TEXT_AUTHOR_INITIALS)) { log(""); traverseParaContents(node); log(""); }else if (nodeName.startsWith(TAG_TEXT)) { log(""); traverseParaContents(node); log(""); }else { log(""); } } /** * This method traverses list tags text:unordered-list and * text:ordered-list. A list can only contain one optional * text:list-header and one or more text:list-item * elements. * * @param node A list Node. * * @throws IOException If any I/O error occurs. */ private void traverseList(Node node) throws IOException { log(""); if (node.hasChildNodes()) { NodeList nodeList = node.getChildNodes(); int len = nodeList.getLength(); for (int i = 0; i < len; i++) { Node child = nodeList.item(i); if (child.getNodeType() == Node.ELEMENT_NODE) { String nodeName = child.getNodeName(); if (nodeName.equals(TAG_LIST_ITEM)) { traverseListItem(child); } else if (nodeName.equals(TAG_LIST_HEADER)) { traverseListHeader(child); } else { log(""); } } } } log(""); } /** * This method traverses a text:list-header element. * It contains one or more text:p elements. * * @param node A list header Node. * * @throws IOException If any I/O error occurs. */ private void traverseListHeader(Node node) throws IOException { log(""); if (node.hasChildNodes()) { NodeList nodeList = node.getChildNodes(); int len = nodeList.getLength(); for (int i = 0; i < len; i++) { Node child = nodeList.item(i); if (child.getNodeType() == Node.ELEMENT_NODE) { String nodeName = child.getNodeName(); if (nodeName.equals(TAG_PARAGRAPH)) { traverseParagraph(child); } else { log(""); } } } } log(""); } /** *

This method will traverse a text:list-item. * A list item may contain one or more of text:p, * text:h, text:section, text:ordered-list * and text:unordered-list.

* *

This method currently only implements grabbing text:p, * text:h, text:unordered-list and * text:ordered-list.

* * @param node The Node. * * @throws IOException If any I/O error occurs. */ private void traverseListItem(Node node) throws IOException { log(""); if (node.hasChildNodes()) { NodeList nodeList = node.getChildNodes(); int len = nodeList.getLength(); for (int i = 0; i < len; i++) { Node child = nodeList.item(i); if (child.getNodeType() == Node.ELEMENT_NODE) { String nodeName = child.getNodeName(); if (nodeName.equals(TAG_PARAGRAPH)) { traverseParagraph(child); } else if (nodeName.equals(TAG_UNORDERED_LIST)) { traverseList(child); } else if (nodeName.equals(TAG_ORDERED_LIST)) { traverseList(child); } else { log(""); } } } } log(""); } /** * Logs debug messages. * * @param str The debug message. */ private void log(String str) { Debug.log(Debug.TRACE, str); } }