Writer2xhtml custom config ui + EPUB export

git-svn-id: svn://svn.code.sf.net/p/writer2latex/code/trunk@55 f0f2a975-2e09-46c8-9428-3b39399b9f3c
This commit is contained in:
henrikjust 2010-03-29 11:07:24 +00:00
parent a58ea7fa19
commit ce61f7bc3b
41 changed files with 1118 additions and 212 deletions

View file

@ -16,11 +16,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* Copyright: 2002-2009 by Henrik Just
* Copyright: 2002-2010 by Henrik Just
*
* All Rights Reserved.
*
* Version 1.2 (2009-06-11)
* Version 1.2 (2010-03-29)
*
*/
@ -46,13 +46,13 @@ import writer2latex.api.MIMETypes;
import writer2latex.util.Misc;
/**
* <p>Commandline utility to convert an OpenOffice.org Writer XML file into XHTML/LaTeX/BibTeX</p>
* <p>Command line utility to convert an OpenOffice.org Writer XML file into XHTML/LaTeX/BibTeX</p>
* <p>The utility is invoked with the following command line:</p>
* <pre>java -jar writer2latex.jar [options] source [target]</pre>
* <p>Where the available options are
* <ul>
* <li><code>-latex</code>, <code>-bibtex</code>, <code>-xhtml</code>,
<code>-xhtml+mathml</code>, <code>-xhtml+mathml+xsl</code>
<code>-xhtml+mathml</code>, <code>-xhtml+mathml+xsl</code>, <code>-epub</code>
* <li><code>-recurse</code>
* <li><code>-ultraclean</code>, <code>-clean</code>, <code>-pdfscreen</code>,
* <code>-pdfprint</code>, <code>-cleanxhtml</code>
@ -279,6 +279,7 @@ public final class Application {
System.out.println(" -xhtml11");
System.out.println(" -xhtml+mathml");
System.out.println(" -xhtml+mathml+xsl");
System.out.println(" -epub");
System.out.println(" -recurse");
System.out.println(" -template[=]<template file>");
System.out.println(" -ultraclean");
@ -312,6 +313,7 @@ public final class Application {
else if ("-xhtml11".equals(sArg)) { sTargetMIME = MIMETypes.XHTML11; }
else if ("-xhtml+mathml".equals(sArg)) { sTargetMIME = MIMETypes.XHTML_MATHML; }
else if ("-xhtml+mathml+xsl".equals(sArg)) { sTargetMIME = MIMETypes.XHTML_MATHML_XSL; }
else if ("-epub".equals(sArg)) { sTargetMIME = MIMETypes.EPUB; }
else if ("-recurse".equals(sArg)) { bRecurse = true; }
else if ("-ultraclean".equals(sArg)) { configFileNames.add("*ultraclean.xml"); }
else if ("-clean".equals(sArg)) { configFileNames.add("*clean.xml"); }

View file

@ -20,7 +20,7 @@
*
* All Rights Reserved.
*
* Version 1.2 (2010-03-12)
* Version 1.2 (2010-03-29)
*
*/
@ -33,11 +33,12 @@ public class ConverterFactory {
// Version information
private static final String VERSION = "1.1.2";
private static final String DATE = "2010-03-14";
private static final String DATE = "2010-03-29";
/** Return version information
* @return the Writer2LaTeX version in the form
* (major version).(minor version).(development version).(patch level)
/** Return the Writer2LaTeX version in the form
* (major version).(minor version).(patch level)<br/>
* Development versions have an odd minor version number
* @return the version number
*/
public static String getVersion() { return VERSION; }
@ -60,6 +61,7 @@ public class ConverterFactory {
* <li><code>application/xhtml+xml</code> for XHTML+MathML</li>
* <li><code>application/xml</code> for XHTML+MathML using stylesheets from w3c's
* math working group</li>
* <li><code>application/epub+zip</code></li> for EPUB format
* </ul>
*
* @param sMIME the MIME type of the target format
@ -86,6 +88,9 @@ public class ConverterFactory {
else if (MIMETypes.XHTML_MATHML_XSL.equals(sMIME)) {
converter = createInstance("writer2latex.xhtml.XhtmlMathMLXSLConverter");
}
else if (MIMETypes.EPUB.equals(sMIME)) {
converter = createInstance("writer2latex.epub.EPUBConverter");
}
return converter instanceof Converter ? (Converter) converter : null;
}
@ -117,7 +122,7 @@ public class ConverterFactory {
private static Object createInstance(String sClassName) {
try {
return Class.forName(sClassName).newInstance();
return Class.forName(sClassName).newInstance();
}
catch (java.lang.ClassNotFoundException e) {
return null;

View file

@ -20,7 +20,7 @@
*
* All Rights Reserved.
*
* Version 1.2 (2010-03-16)
* Version 1.2 (2010-03-28)
*
*/
@ -29,6 +29,7 @@ package writer2latex.api;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
/** A <code>ConverterResult</code> represent a document, which is the result
* of a conversion performed by a <code>Converter</code>implementation.
@ -36,12 +37,16 @@ import java.util.Iterator;
public interface ConverterResult {
/** Get the master document
* Deprecated as of Writer2LaTeX 1.2: The master document is always the first document
* returned by the <code>iterator</code>
*
* @return <code>OutputFile</code> the master document
*/
public OutputFile getMasterDocument();
@Deprecated public OutputFile getMasterDocument();
/** Gets an <code>Iterator</code> to access all files in the
* <code>ConverterResult</code>. This <em>includes</em> the master document.
* <code>ConverterResult</code>. The iterator will return the master documents first
* in logical order (starting with the primary master document)
* @return an <code>Iterator</code> of all files
*/
public Iterator<OutputFile> iterator();
@ -51,6 +56,37 @@ public interface ConverterResult {
*/
public MetaData getMetaData();
/** Get the content table (based on headings) for this <code>ConverterResult</code>
*
* @return list view of the content
*/
public List<ContentEntry> getContent();
/** Get the entry which contains the table of contents
*
* @return the entry
*/
public ContentEntry getTocFile();
/** Get the entry which contains the list of tables
*
* @return the entry
*/
public ContentEntry getLotFile();
/** Get the entry which contains the list of figures
*
* @return the entry
*/
public ContentEntry getLofFile();
/** Get the entry which contains the alphabetical index
*
* @return the entry
*/
public ContentEntry getIndexFile();
/** Write all files of the <code>ConverterResult</code> to a directory.
* Subdirectories are created as required by the individual
* <code>OutputFile</code>s.

View file

@ -16,17 +16,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* Copyright: 2002-2009 by Henrik Just
* Copyright: 2002-2010 by Henrik Just
*
* All Rights Reserved.
*
* Version 1.2 (2009-05-29)
* Version 1.2 (2010-03-29)
*
*/
package writer2latex.api;
/* Some helpers to handle the MIME types used by OOo
/* Some helpers to handle the MIME types used by OOo and Writer2LaTeX
*/
public class MIMETypes {
@ -50,6 +50,7 @@ public class MIMETypes {
public static final String XHTML11="application/xhtml11";
public static final String XHTML_MATHML="application/xhtml+xml";
public static final String XHTML_MATHML_XSL="application/xml";
public static final String EPUB="application/epub+zip";
public static final String LATEX="application/x-latex";
public static final String BIBTEX="application/x-bibtex";
public static final String TEXT="text";

View file

@ -20,7 +20,7 @@
*
* All Rights Reserved.
*
* Version 1.2 (2010-03-15)
* Version 1.2 (2010-03-28)
*
*/
@ -29,7 +29,7 @@ package writer2latex.api;
import java.io.OutputStream;
import java.io.IOException;
/** An <code>OutputFile</code> represent a single file in a
/** An <code>OutputFile</code> represents a single file in a
* {@link ConverterResult}, which is output from a {@link Converter}
* implementation.
*/
@ -56,4 +56,10 @@ public interface OutputFile {
*/
public String getMIMEType();
/** Test whether this document is part of the main document flow (master documents) or
* an auxiliary document
*
* @return true if this document is a master document
*/
public boolean isMasterDocument();
}

View file

@ -0,0 +1,60 @@
/************************************************************************
*
* ConverterResultImpl.java
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library 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 for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* Copyright: 2002-2010 by Henrik Just
*
* All Rights Reserved.
*
* Version 1.2 (2010-03-24)
*
*/
package writer2latex.base;
import writer2latex.api.ContentEntry;
import writer2latex.api.OutputFile;
public class ContentEntryImpl implements ContentEntry {
private String sTitle;
private int nLevel;
private OutputFile file;
private String sTarget;
public ContentEntryImpl(String sTitle, int nLevel, OutputFile file, String sTarget) {
this.sTitle = sTitle;
this.nLevel = nLevel;
this.file = file;
this.sTarget = sTarget;
}
public String getTitle() {
return sTitle;
}
public int getLevel() {
return nLevel;
}
public OutputFile getFile() {
return file;
}
public String getTarget() {
return sTarget;
}
}

View file

@ -16,11 +16,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* Copyright: 2002-2008 by Henrik Just
* Copyright: 2002-2010 by Henrik Just
*
* All Rights Reserved.
*
* Version 1.0 (2008-11-23)
* Version 1.2 (2010-03-29)
*
*/
@ -31,7 +31,6 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.IOException;
import writer2latex.api.GraphicConverter;
import writer2latex.api.Converter;
import writer2latex.api.ConverterResult;
@ -57,12 +56,12 @@ public abstract class ConverterBase implements Converter {
// The output file(s)
protected String sTargetFileName;
protected ConverterResultImpl convertData;
protected ConverterResultImpl converterResult;
// Constructor
public ConverterBase() {
graphicConverter = null;
convertData = new ConverterResultImpl();
converterResult = new ConverterResultImpl();
}
// Implement the interface
@ -91,11 +90,16 @@ public abstract class ConverterBase implements Converter {
// Prepare output
this.sTargetFileName = sTargetFileName;
convertData.reset();
converterResult.reset();
converterResult.setMetaData(metaData);
if (metaData.getLanguage()==null || metaData.getLanguage().length()==0) {
metaData.setLanguage(ofr.getMajorityLanguage());
}
convertInner();
return convertData;
return converterResult;
}
// The subclass must provide the implementation
@ -105,7 +109,7 @@ public abstract class ConverterBase implements Converter {
public ImageLoader getImageLoader() { return imageLoader; }
public void addDocument(OutputFile doc) { convertData.addDocument(doc); }
public void addDocument(OutputFile doc) { converterResult.addDocument(doc); }
public EmbeddedObject getEmbeddedObject(String sHref) {
return odDoc.getEmbeddedObject(sHref);

View file

@ -20,7 +20,7 @@
*
* All Rights Reserved.
*
* Version 1.2 (2010-03-22)
* Version 1.2 (2010-03-28)
*
*/
@ -29,125 +29,164 @@ package writer2latex.base;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Vector;
import java.util.Iterator;
import writer2latex.api.ConverterResult;
import writer2latex.api.MetaData;
import writer2latex.api.OutputFile;
import writer2latex.api.ContentEntry;
/**
* <p><code>ConvertData</code> is used as a container for passing
* <code>OutputFile</code> objects in and out of the <code>Convert</code>
* class. The <code>ConvertData</code> contains a <code>String</code>
* name and a <code>Vector</code> of <code>OutputFile</code> objects.</p>
*
* @author Martin Maher
* TODO: Rewrite to support extended API
/** <code>ConverterResultImpl</code> is a straightforward implementation of <code>ConverterResult</code>
*/
public class ConverterResultImpl implements ConverterResult {
/**
* Vector of <code>OutputFile</code> objects.
*/
private Vector<OutputFile> v = new Vector<OutputFile>();
private List<OutputFile> files;
/** Master doc */
private OutputFile masterDoc = null;
/**
* Name of the <code>ConvertData</code> object.
*/
private String name;
private List<ContentEntry> content;
private ContentEntry tocFile;
private ContentEntry lofFile;
private ContentEntry lotFile;
private ContentEntry indexFile;
private MetaData metaData = null;
/**
* Resets ConvertData. This empties all <code>OutputFile</code>
* objects from this class. This allows reuse of a
* <code>ConvertData</code>.
*/
public void reset() {
name = null;
v.removeAllElements();
}
/**
* Returns the <code>OutputFile</code> name.
*
* @return The <code>OutputFile</code> name.
*/
public String getName() {
return name;
}
/**
* Sets the <code>OutputFile</code> name.
*
* @param docName The name of the <code>OutputFile</code>.
*/
public void setName(String docName) {
name = docName;
}
/**
* Adds a <code>OutputFile</code> to the vector.
*
* @param doc The <code>OutputFile</code> to add.
*/
public void addDocument(OutputFile doc) {
if (v.size()==0) { masterDoc = doc; }
v.add(doc);
private int nMasterCount;
/** Construct a new <code>ConverterResultImpl</code> with empty content
*/
public ConverterResultImpl() {
reset();
}
/** Get the master document
/** Resets all data. This empties all <code>OutputFile</code> and <code>ContentEntry</code> objects
* objects from this class. This allows reuse of a <code>ConvertResult</code> object.
*/
public void reset() {
files = new Vector<OutputFile>();
content = new Vector<ContentEntry>();
tocFile = null;
lofFile = null;
lotFile = null;
indexFile = null;
metaData = null;
nMasterCount = 0;
}
/** Adds an <code>OutputFile</code> to the list
*
* @param file The <code>OutputFile</code> to add.
*/
public void addDocument(OutputFile file) {
if (file.isMasterDocument()) {
files.add(nMasterCount++, file);
}
else {
files.add(file);
}
}
/** Get the first master document
*
* @return <code>OutputFile</code> the master document
*/
public OutputFile getMasterDocument() {
return masterDoc;
return files.size()>0 ? files.get(0) : null;
}
/** Check if a given document is the master document
* @param doc The <code>OutputFile</code> to check
* @return true if this is the master document
*/
public boolean isMasterDocument(OutputFile doc) {
return doc == masterDoc;
}
/**
* Gets an <code>Iterator</code> to access the <code>Vector</code>
* Gets an <code>Iterator</code> to access the <code>List</code>
* of <code>OutputFile</code> objects
*
* @return The <code>Iterator</code> to access the
* <code>Vector</code> of <code>OutputFile</code> objects.
* <code>List</code> of <code>OutputFile</code> objects.
*/
public Iterator<OutputFile> iterator() {
return v.iterator();
return files.iterator();
}
public MetaData getMetaData() {
return metaData;
}
/** Add an entry to the "external" table of contents
*
* @param entry the entry to add
*/
public void addContentEntry(ContentEntry entry) {
content.add(entry);
}
public List<ContentEntry> getContent() {
return Collections.unmodifiableList(content);
}
/** Define the entry which contains the table of contents
*
* @param entry the entry
*/
public void setTocFile(ContentEntry entry) {
tocFile = entry;
}
public ContentEntry getTocFile() {
return tocFile;
}
/** Define the entry which contains the list of figures
*
* @param entry the entry
*/
public void setLofFile(ContentEntry entry) {
lofFile = entry;
}
public ContentEntry getLofFile() {
return lofFile;
}
/** Define the entry which contains the list of tables
*
* @param entry the entry
*/
public void setLotFile(ContentEntry entry) {
lotFile = entry;
}
public ContentEntry getLotFile() {
return lotFile;
}
/** Define the entry which contains the alphabetical index
*
* @param entry the entry
*/
public void setIndexFile(ContentEntry entry) {
indexFile = entry;
}
public ContentEntry getIndexFile() {
return indexFile;
}
/** Set the meta data of this <code>ConverterResult</code>
*
* @param metaData the meta data
*/
public void setMetaData(MetaData metaData) {
this.metaData = metaData;
}
/**
* Gets the number of <code>OutputFile</code> objects currently stored
*
* @return The number of <code>OutputFile</code> objects currently
* stored.
*/
public int getNumDocuments() {
return (v.size());
/** Get the meta data of this <code>ConverterResult</code>
*
* @return the meta data
*/
public MetaData getMetaData() {
return metaData;
}
/** Write all files to a given directory
*
* @param dir the directory to use
*/
public void write(File dir) throws IOException {
if (dir!=null && !dir.exists()) throw new IOException("Directory does not exist");
Iterator<OutputFile> docEnum = iterator();

View file

@ -20,7 +20,7 @@
*
* All Rights Reserved.
*
* Version 1.2 (2010-03-15)
* Version 1.2 (2010-03-28)
*
*/
@ -55,6 +55,8 @@ public class BibTeXDocument implements Document {
private Hashtable<String, BibMark> entries = new Hashtable<String, BibMark>();
private ExportNameCollection exportNames = new ExportNameCollection("",true,"_-:");
private I18n i18n;
private boolean bIsMaster;
/**
* <p>Constructs a new BibTeX Document.</p>
@ -64,8 +66,9 @@ public class BibTeXDocument implements Document {
*
* @param sName The name of the <code>BibTeXDocument</code>.
*/
public BibTeXDocument(String sName) {
public BibTeXDocument(String sName, boolean bIsMaster) {
this.sName = trimDocumentName(sName);
this.bIsMaster = bIsMaster;
// Use default config (only ascii, no extra font packages)
i18n = new ClassicI18n(new LaTeXConfig());
}
@ -105,6 +108,10 @@ public class BibTeXDocument implements Document {
public String getMIMEType() {
return MIMETypes.BIBTEX;
}
public boolean isMasterDocument() {
return bIsMaster;
}
/**
* <p>Writes out the <code>Document</code> content to the specified

View file

@ -16,11 +16,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* Copyright: 2001-2008 by Henrik Just
* Copyright: 2001-2010 by Henrik Just
*
* All Rights Reserved.
*
* version 1.0 (2008-11-22)
* version 1.2 (2010-03-28)
*
*/
@ -70,7 +70,7 @@ public final class Converter extends ConverterBase {
public void convertInner() throws IOException {
sTargetFileName = Misc.trimDocumentName(sTargetFileName,".bib");
BibTeXDocument bibDoc = new BibTeXDocument(sTargetFileName);
BibTeXDocument bibDoc = new BibTeXDocument(sTargetFileName,true);
// Collect all text:bibliography-mark elements from the content
Element doc = ofr.getContent();
@ -85,7 +85,7 @@ public final class Converter extends ConverterBase {
}
// Add result
convertData.addDocument(bibDoc);
converterResult.addDocument(bibDoc);
}
}

View file

@ -0,0 +1,77 @@
/************************************************************************
*
* ContainerWriter.java
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library 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 for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* Copyright: 2001-2010 by Henrik Just
*
* All Rights Reserved.
*
* version 1.2 (2010-03-29)
*
*/
package writer2latex.epub;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import writer2latex.xmerge.NewDOMDocument;
/** This class creates the required META-INF/container.xml file for an EPUB package
* (see http://www.idpf.org/ocf/ocf1.0/download/ocf10.htm)
*/
public class ContainerWriter extends NewDOMDocument {
public ContainerWriter(String sRootFile) {
super("container", "xml");
// create DOM
Document contentDOM = null;
try {
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
DOMImplementation domImpl = builder.getDOMImplementation();
DocumentType doctype = domImpl.createDocumentType("container","","");
contentDOM = domImpl.createDocument("urn:oasis:names:tc:opendocument:xmlns:container","container",doctype);
}
catch (ParserConfigurationException t) { // this should never happen
throw new RuntimeException(t);
}
// Populate the DOM tree
Element container = contentDOM.getDocumentElement();
container.setAttribute("version", "1.0");
container.setAttribute("xmlns","urn:oasis:names:tc:opendocument:xmlns:container");
Element rootfiles = contentDOM.createElement("rootfiles");
container.appendChild(rootfiles);
Element rootfile = contentDOM.createElement("rootfile");
rootfile.setAttribute("full-path", sRootFile);
rootfile.setAttribute("media-type", "application/oebps-package+xml");
rootfiles.appendChild(rootfile);
setContentDOM(contentDOM);
}
}

View file

@ -0,0 +1,55 @@
/************************************************************************
*
* EPUBConverter.java
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library 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 for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* Copyright: 2001-2010 by Henrik Just
*
* All Rights Reserved.
*
* version 1.2 (2010-03-28)
*
*/
package writer2latex.epub;
import java.io.IOException;
import java.io.InputStream;
import writer2latex.api.ConverterResult;
import writer2latex.base.ConverterResultImpl;
import writer2latex.xhtml.Xhtml11Converter;
/** This class converts an OpenDocument file to an EPUB document.
*/
public final class EPUBConverter extends Xhtml11Converter {
// Constructor
public EPUBConverter() {
super();
}
@Override public ConverterResult convert(InputStream is, String sTargetFileName) throws IOException {
ConverterResult xhtmlResult = super.convert(is, sTargetFileName);
ConverterResultImpl epubResult = new ConverterResultImpl();
epubResult.addDocument(new EPUBWriter(xhtmlResult,sTargetFileName));
epubResult.setMetaData(xhtmlResult.getMetaData());
return epubResult;
}
}

View file

@ -0,0 +1,122 @@
/************************************************************************
*
* EPUBWriter.java
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library 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 for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* Copyright: 2001-2010 by Henrik Just
*
* All Rights Reserved.
*
* version 1.2 (2010-03-29)
*
*/
package writer2latex.epub;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import writer2latex.api.ConverterResult;
import writer2latex.api.OutputFile;
import writer2latex.util.Misc;
/** This class repackages an XHTML document into EPUB format
*
*/
public class EPUBWriter implements OutputFile {
private static final byte[] mimeBytes = { 'a', 'p', 'p', 'l', 'i', 'c', 'a', 't', 'i', 'o', 'n', '/',
'e', 'p', 'u', 'b', '+', 'z', 'i', 'p'};
private ConverterResult xhtmlResult;
private String sFileName;
public EPUBWriter(ConverterResult xhtmlResult, String sFileName) {
this.xhtmlResult = xhtmlResult;
this.sFileName = Misc.removeExtension(sFileName);
}
public String getFileName() {
return sFileName+".epub";
}
public String getMIMEType() {
return "application/epub+zip";
}
public boolean isMasterDocument() {
return true;
}
public void write(OutputStream os) throws IOException {
ZipOutputStream zos = new ZipOutputStream(os);
// Write MIME type as first entry
ZipEntry mimeEntry = new ZipEntry("mimetype");
mimeEntry.setMethod(ZipEntry.STORED);
mimeEntry.setCrc(0x2CAB616F);
mimeEntry.setSize(mimeBytes.length);
zos.putNextEntry(mimeEntry);
zos.write(mimeBytes, 0, mimeBytes.length);
zos.closeEntry();
// Write container entry next
OutputFile containerWriter = new ContainerWriter("OEBPS/book.opf");
ZipEntry containerEntry = new ZipEntry("META-INF/container.xml");
zos.putNextEntry(containerEntry);
writeZipEntry(containerWriter,zos);
zos.closeEntry();
// Then manifest
OutputFile manifest = new OPFWriter(xhtmlResult, "xxx", "book.ncx", "book.opf");
ZipEntry manifestEntry = new ZipEntry("OEBPS/book.opf");
zos.putNextEntry(manifestEntry);
writeZipEntry(manifest,zos);
zos.closeEntry();
// And content table
OutputFile ncx = new NCXWriter(xhtmlResult, "xxx", "book.ncx");
ZipEntry ncxEntry = new ZipEntry("OEBPS/book.ncx");
zos.putNextEntry(ncxEntry);
writeZipEntry(ncx,zos);
zos.closeEntry();
// Finally XHTML content in the OEBPS sub directory
Iterator<OutputFile> iter = xhtmlResult.iterator();
while (iter.hasNext()) {
OutputFile file = iter.next();
ZipEntry entry = new ZipEntry("OEBPS/"+file.getFileName());
zos.putNextEntry(entry);
writeZipEntry(file, zos);
zos.closeEntry();
}
zos.close();
}
private void writeZipEntry(OutputFile file, ZipOutputStream zos) throws IOException {
// TODO: Fix this waste of memory :-)
ByteArrayOutputStream baos = new ByteArrayOutputStream();
file.write(baos);
byte[] content = baos.toByteArray();
zos.write(content, 0, content.length);
}
}

View file

@ -0,0 +1,141 @@
/************************************************************************
*
* NCXWriter.java
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library 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 for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* Copyright: 2001-2010 by Henrik Just
*
* All Rights Reserved.
*
* version 1.2 (2010-03-29)
*
*/
package writer2latex.epub;
import java.util.Iterator;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import writer2latex.api.ContentEntry;
import writer2latex.api.ConverterResult;
import writer2latex.util.Misc;
import writer2latex.xmerge.NewDOMDocument;
/** This class creates the required NXC file for an EPUB document
* (see http://www.idpf.org/2007/opf/OPF_2.0_final_spec.html#Section2.4)
*
*/
public class NCXWriter extends NewDOMDocument {
public NCXWriter(ConverterResult cr, String sUUID, String sFileName) {
super(Misc.removeExtension(sFileName), "ncx");
// create DOM
Document contentDOM = null;
try {
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
DOMImplementation domImpl = builder.getDOMImplementation();
DocumentType doctype = domImpl.createDocumentType("ncx","","");
contentDOM = domImpl.createDocument("http://www.daisy.org/z3986/2005/ncx/","ncx",doctype);
}
catch (ParserConfigurationException t) { // this should never happen
throw new RuntimeException(t);
}
System.out.println("populating the ncx");
// Populate the DOM tree
Element ncx = contentDOM.getDocumentElement();
ncx.setAttribute("version", "2005-1");
ncx.setAttribute("xml:lang", cr.getMetaData().getLanguage());
ncx.setAttribute("xmlns","http://www.daisy.org/z3986/2005/ncx/");
// The head has four required meta data items
Element head = contentDOM.createElement("head");
ncx.appendChild(head);
Element uid = contentDOM.createElement("meta");
uid.setAttribute("name","dtb:uid");
uid.setAttribute("content", sUUID);
head.appendChild(uid);
Element depth = contentDOM.createElement("meta");
depth.setAttribute("name","dtb:depth");
depth.setAttribute("content", "1");
head.appendChild(depth);
Element totalPageCount = contentDOM.createElement("meta");
totalPageCount.setAttribute("name","dtb:totalPageCount");
totalPageCount.setAttribute("content", "0");
head.appendChild(totalPageCount);
Element maxPageNumber = contentDOM.createElement("meta");
maxPageNumber.setAttribute("name","dtb:maxPageNumber");
maxPageNumber.setAttribute("content", "0");
head.appendChild(maxPageNumber);
// The ncx must contain a docTitle element
Element docTitle = contentDOM.createElement("docTitle");
ncx.appendChild(docTitle);
Element docTitleText = contentDOM.createElement("text");
docTitle.appendChild(docTitleText);
docTitleText.appendChild(contentDOM.createTextNode(cr.getMetaData().getTitle()));
// Build the navMap from the content table in the converter result
Element navMap = contentDOM.createElement("navMap");
ncx.appendChild(navMap);
int nPlayOrder = 0;
Iterator<ContentEntry> content = cr.getContent().iterator();
while (content.hasNext()) {
ContentEntry entry = content.next();
//if (entry.getLevel()==1) {
System.out.println("Found content entry "+entry.getTitle());
Element navPoint = contentDOM.createElement("navPoint");
navPoint.setAttribute("playOrder", Integer.toString(++nPlayOrder));
navPoint.setAttribute("id", "text"+nPlayOrder);
navMap.appendChild(navPoint);
Element navLabel = contentDOM.createElement("navLabel");
navPoint.appendChild(navLabel);
Element navLabelText = contentDOM.createElement("text");
navLabel.appendChild(navLabelText);
navLabelText.appendChild(contentDOM.createTextNode(entry.getTitle()));
Element navPointContent = contentDOM.createElement("content");
String sHref = entry.getFile().getFileName();
if (entry.getTarget()!=null) { sHref+="#"+entry.getTarget(); }
navPointContent.setAttribute("src", sHref);
navPoint.appendChild(navPointContent);
//}
}
setContentDOM(contentDOM);
System.out.println("finished populating the ncx");
}
}

View file

@ -0,0 +1,159 @@
/************************************************************************
*
* OPFWriter.java
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library 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 for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* Copyright: 2001-2010 by Henrik Just
*
* All Rights Reserved.
*
* version 1.2 (2010-03-29)
*
*/
package writer2latex.epub;
import java.util.Iterator;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import writer2latex.api.ContentEntry;
import writer2latex.api.ConverterResult;
import writer2latex.api.OutputFile;
import writer2latex.util.Misc;
import writer2latex.xmerge.NewDOMDocument;
/** This class writes an OPF-file for an EPUB document (see http://www.idpf.org/2007/opf/OPF_2.0_final_spec.html)
*
*/
public class OPFWriter extends NewDOMDocument {
public OPFWriter(ConverterResult cr, String sUUID, String sNcxFileName, String sFileName) {
super(Misc.removeExtension(sFileName), "opf");
// create DOM
Document contentDOM = null;
try {
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
DOMImplementation domImpl = builder.getDOMImplementation();
DocumentType doctype = domImpl.createDocumentType("package","","");
contentDOM = domImpl.createDocument("http://www.idpf.org/2007/opf","package",doctype);
}
catch (ParserConfigurationException t) { // this should never happen
throw new RuntimeException(t);
}
// Populate the DOM tree
Element pack = contentDOM.getDocumentElement();
pack.setAttribute("version", "2.0");
pack.setAttribute("xmlns","http://www.idpf.org/2007/opf");
pack.setAttribute("unique-identifier", "BookId");
// Meta data, at least dc:title, dc:language and dc:identifier are required by the specification
Element metadata = contentDOM.createElement("metadata");
metadata.setAttribute("xmlns:dc", "http://purl.org/dc/elements/1.1/");
metadata.setAttribute("xmlns:opf", "http://www.idpf.org/2007/opf");
pack.appendChild(metadata);
Element title = contentDOM.createElement("dc:title");
metadata.appendChild(title);
title.appendChild(contentDOM.createTextNode(cr.getMetaData().getTitle()));
Element language = contentDOM.createElement("dc:language");
metadata.appendChild(language);
language.appendChild(contentDOM.createTextNode(cr.getMetaData().getLanguage()));
Element identifier = contentDOM.createElement("dc:identifier");
identifier.setAttribute("id", "BookId");
identifier.setAttribute("opf:scheme", "UUID");
metadata.appendChild(identifier);
identifier.appendChild(contentDOM.createTextNode(sUUID));
// Manifest must contain references to all the files in the XHTML converter result
// Spine should contain references to all the master documents within the converter result
Element manifest = contentDOM.createElement("manifest");
pack.appendChild(manifest);
Element spine = contentDOM.createElement("spine");
spine.setAttribute("toc", "ncx");
pack.appendChild(spine);
int nMasterCount = 0;
int nResourceCount = 0;
Iterator<OutputFile> iterator = cr.iterator();
while (iterator.hasNext()) {
OutputFile file = iterator.next();
Element item = contentDOM.createElement("item");
manifest.appendChild(item);
item.setAttribute("href",file.getFileName());
item.setAttribute("media-type", file.getMIMEType());
if (file.isMasterDocument()) {
String sId = "text"+(++nMasterCount);
item.setAttribute("id", sId);
Element itemref = contentDOM.createElement("itemref");
itemref.setAttribute("idref", sId);
spine.appendChild(itemref);
}
else {
item.setAttribute("id", "resource"+(++nResourceCount));
}
}
Element item = contentDOM.createElement("item");
item.setAttribute("href", sNcxFileName);
item.setAttribute("media-type", "application/x-dtbncx+xml");
item.setAttribute("id", "ncx");
manifest.appendChild(item);
// The guide may contain references to some fundamental structural components
Element guide = contentDOM.createElement("guide");
pack.appendChild(guide);
addGuideReference(contentDOM,guide,"toc",cr.getTocFile());
addGuideReference(contentDOM,guide,"index",cr.getIndexFile());
addGuideReference(contentDOM,guide,"loi",cr.getLofFile());
addGuideReference(contentDOM,guide,"lot",cr.getLotFile());
// TODO addGuideReference(contentDOM,guide,"bibliography",cr.getBibliographyile());
List<ContentEntry> contents = cr.getContent();
if (contents.size()>0) {
addGuideReference(contentDOM,guide,"text",contents.get(0));
}
setContentDOM(contentDOM);
}
private void addGuideReference(Document contentDOM, Element guide, String sType, ContentEntry entry) {
if (entry!=null) {
Element reference = contentDOM.createElement("reference");
reference.setAttribute("type", sType);
reference.setAttribute("title", entry.getTitle());
String sHref = entry.getFile().getFileName();
if (entry.getTarget()!=null) { sHref+="#"+entry.getTarget(); }
reference.setAttribute("href", sHref);
guide.appendChild(reference);
}
}
}

View file

@ -16,11 +16,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* Copyright: 2002-2009 by Henrik Just
* Copyright: 2002-2010 by Henrik Just
*
* All Rights Reserved.
*
* Version 1.2 (2009-06-05)
* Version 1.2 (2010-03-28)
*
*/
@ -103,7 +103,7 @@ public class BibConverter extends ConverterHelper {
.append("}").nl();
}
else {
if (bibDoc==null) { bibDoc = new BibTeXDocument(palette.getOutFileName()); }
if (bibDoc==null) { bibDoc = new BibTeXDocument(palette.getOutFileName(),false); }
ldp.append("\\bibliography{")
.append(bibDoc.getName())
.append("}").nl();
@ -129,7 +129,7 @@ public class BibConverter extends ConverterHelper {
String sIdentifier = node.getAttribute(XMLString.TEXT_IDENTIFIER);
if (sIdentifier!=null) {
if (config.externalBibtexFiles().length()==0) {
if (bibDoc==null) { bibDoc = new BibTeXDocument(palette.getOutFileName()); }
if (bibDoc==null) { bibDoc = new BibTeXDocument(palette.getOutFileName(),false); }
if (!bibDoc.containsKey(sIdentifier)) {
bibDoc.put(new BibMark(node));
}

View file

@ -20,7 +20,7 @@
*
* All Rights Reserved.
*
* Version 1.2 (2010-03-15)
* Version 1.2 (2010-03-28)
*
*/
@ -174,7 +174,7 @@ public final class ConverterPalette extends ConverterBase {
info = new Info(ofr,config,this);
// Create master document and add this
this.texDoc = new LaTeXDocument(sTargetFileName,config.getWrapLinesAfter());
this.texDoc = new LaTeXDocument(sTargetFileName,config.getWrapLinesAfter(),true);
if (config.getBackend()!=LaTeXConfig.XETEX) {
texDoc.setEncoding(ClassicI18n.writeJavaEncoding(config.getInputencoding()));
}
@ -182,7 +182,7 @@ public final class ConverterPalette extends ConverterBase {
texDoc.setEncoding("UTF-8");
}
convertData.addDocument(texDoc);
converterResult.addDocument(texDoc);
// Create other data
globalOptions = new CSVList(',');
@ -288,7 +288,7 @@ public final class ConverterPalette extends ConverterBase {
// Add BibTeX document if there's any bibliographic data
if (bibCv.getBibTeXDocument()!=null) {
convertData.addDocument(bibCv.getBibTeXDocument());
converterResult.addDocument(bibCv.getBibTeXDocument());
}
}

View file

@ -20,7 +20,7 @@
*
* All Rights Reserved.
*
* Version 1.2 (2010-03-15)
* Version 1.2 (2010-03-28)
*
*/
@ -42,6 +42,8 @@ public class LaTeXDocument implements Document {
private static final String FILE_EXTENSION = ".tex";
private String sName;
private boolean bIsMaster;
private String sEncoding = "ASCII";
@ -57,10 +59,12 @@ public class LaTeXDocument implements Document {
*
* @param sName The name of the <code>LaTeXDocument</code>.
* @param nWrap Lines should be wrapped after this position
* @param bIsMaster true if this is a master document
*/
public LaTeXDocument(String sName,int nWrap) {
public LaTeXDocument(String sName,int nWrap,boolean bIsMaster) {
this.nWrap = nWrap;
this.sName = trimDocumentName(sName);
this.bIsMaster = bIsMaster;
contents = new LaTeXDocumentPortion(true);
}
@ -99,6 +103,10 @@ public class LaTeXDocument implements Document {
public String getMIMEType() {
return MIMETypes.LATEX;
}
public boolean isMasterDocument() {
return bIsMaster;
}
/**
* <p>Writes out the <code>Document</code> content to the specified

View file

@ -20,7 +20,7 @@
*
* All Rights Reserved.
*
* Version 1.2 (2010-03-15)
* Version 1.2 (2010-03-28)
*
*/
@ -80,7 +80,7 @@ public class SectionConverter extends ConverterHelper {
LaTeXDocumentPortion sectionLdp = ldp;
if (sFileName!=null) {
LaTeXDocument newDoc = new LaTeXDocument(sFileName,config.getWrapLinesAfter());
LaTeXDocument newDoc = new LaTeXDocument(sFileName,config.getWrapLinesAfter(),false);
if (config.getBackend()!=LaTeXConfig.XETEX) {
newDoc.setEncoding(ClassicI18n.writeJavaEncoding(config.getInputencoding()));
}

View file

@ -20,7 +20,7 @@
*
* All Rights Reserved.
*
* Version 1.2 (2010-03-15)
* Version 1.2 (2010-03-29)
*
*/
@ -142,6 +142,10 @@ public class MetaData implements writer2latex.api.MetaData {
* @return the language of the document
*/
public String getLanguage() { return sLanguage; }
public void setLanguage(String sLanguage) {
this.sLanguage = sLanguage;
}
/** <p> Get the subject of this document (may be null)</p>
* @return the subject of the document

View file

@ -20,7 +20,7 @@
*
* All Rights Reserved.
*
* Version 1.2 (2010-03-15)
* Version 1.2 (2010-03-25)
*
*/
@ -44,8 +44,10 @@ import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import writer2latex.api.Config;
import writer2latex.api.ContentEntry;
import writer2latex.api.ConverterFactory;
//import writer2latex.api.ConverterResult;
import writer2latex.base.ContentEntryImpl;
import writer2latex.base.ConverterBase;
//import writer2latex.latex.LaTeXDocumentPortion;
//import writer2latex.latex.util.Context;
@ -57,7 +59,7 @@ import writer2latex.util.ExportNameCollection;
import writer2latex.util.Misc;
/**
* <p>This class converts an OpenDocument file to an XHTML(+MathML) document<.</p>
* <p>This class converts an OpenDocument file to an XHTML(+MathML) document.</p>
*
*/
public class Converter extends ConverterBase {
@ -86,6 +88,8 @@ public class Converter extends ConverterBase {
private XhtmlDocument htmlDoc; // current outfile
private Document htmlDOM; // current DOM, usually within htmlDoc
private boolean bNeedHeaderFooter = false;
private int nTocFileIndex = -1;
private int nAlphabeticalIndex = -1;
// Hyperlinks
Hashtable<String, Integer> targets = new Hashtable<String, Integer>();
@ -123,6 +127,28 @@ public class Converter extends ConverterBase {
protected int getType() { return nType; }
protected int getOutFileIndex() { return nOutFileIndex; }
protected void addContentEntry(String sTitle, int nLevel, String sTarget) {
converterResult.addContentEntry(new ContentEntryImpl(sTitle,nLevel,htmlDoc,sTarget));
}
protected void setTocFile(String sTarget) {
converterResult.setTocFile(new ContentEntryImpl(l10n.get(L10n.CONTENTS),1,htmlDoc,sTarget));
nTocFileIndex = nOutFileIndex;
}
protected void setLofFile(String sTarget) {
converterResult.setLofFile(new ContentEntryImpl("Figures",1,htmlDoc,sTarget));
}
protected void setLotFile(String sTarget) {
converterResult.setLotFile(new ContentEntryImpl("Tables",1,htmlDoc,sTarget));
}
protected void setIndexFile(String sTarget) {
converterResult.setIndexFile(new ContentEntryImpl(l10n.get(L10n.INDEX),1,htmlDoc,sTarget));
nAlphabeticalIndex = nOutFileIndex;
}
protected Element createElement(String s) { return htmlDOM.createElement(s); }
@ -327,13 +353,14 @@ public class Converter extends ConverterBase {
}
}
}
}
private void addNavigationLink(Document dom, Node node, String s, int nIndex) {
if (nIndex>=0 && nIndex<=nOutFileIndex) {
Element a = dom.createElement("a");
a.setAttribute("href",Misc.makeHref(getOutFileName(nIndex,true)));
a.setAttribute("href",getOutFileName(nIndex,true));
a.appendChild(dom.createTextNode(s));
//node.appendChild(dom.createTextNode("["));
node.appendChild(a);
@ -446,7 +473,7 @@ public class Converter extends ConverterBase {
if (template!=null) { htmlDoc.readFromTemplate(template); }
else if (bNeedHeaderFooter) { htmlDoc.createHeaderFooter(); }
outFiles.add(nOutFileIndex,htmlDoc);
convertData.addDocument(htmlDoc);
converterResult.addDocument(htmlDoc);
// Create head + body
htmlDOM = htmlDoc.getContentDOM();

View file

@ -20,7 +20,7 @@
*
* All Rights Reserved.
*
* Version 1.2 (2010-03-12)
* Version 1.2 (2010-03-26)
*
*/
@ -568,10 +568,17 @@ public class TextConverter extends ConverterHelper {
heading.appendChild(span);
span.appendChild( converter.createTextNode(sLabel) );
}
// Add to toc
if (!bInToc) {
converter.addTarget(heading,"toc"+(++nTocIndex));
// Add in external content
if (nLevel<=nSplit) {
converter.addContentEntry(sLabel+(sLabel.length()>0 ? " " : "")+Misc.getPCDATA(onode), nLevel, null);
}
// Add to real toc
TocEntry entry = new TocEntry();
entry.onode = (Element) onode;
entry.sLabel = sLabel;
@ -1014,6 +1021,8 @@ public class TextConverter extends ConverterHelper {
if (!ofr.getTocReader((Element)onode).isByChapter()) {
nTocFileIndex = converter.getOutFileIndex();
}
converter.setTocFile(null);
Element div = converter.createElement("div");
hnode.appendChild(div);
@ -1175,6 +1184,8 @@ public class TextConverter extends ConverterHelper {
*/
private void handleAlphabeticalIndex (Node onode, Node hnode) {
nAlphabeticalIndex = converter.getOutFileIndex();
converter.setIndexFile(null);
Node source = Misc.getChildByTagName(onode,XMLString.TEXT_ALPHABETICAL_INDEX_SOURCE);
if (source!=null) {
Element div = converter.createElement("div");

View file

@ -173,6 +173,10 @@ public class XhtmlDocument extends DOMDocument {
return "";
}
@Override public boolean isMasterDocument() {
return true;
}
public Element getHeadNode() { return headNode; }
public Element getBodyNode() { return bodyNode; }

View file

@ -20,7 +20,7 @@
*
* All Rights Reserved.
*
* Version 1.2 (2010-03-15)
* Version 1.2 (2010-03-28)
*
*/
@ -166,5 +166,9 @@ public class BinaryGraphicsDocument implements Document {
public String getMIMEType() {
return sMimeType;
}
public boolean isMasterDocument() {
return false;
}
}

View file

@ -393,10 +393,14 @@ public class DOMDocument
return doc;
}
// We need this because we implement OutputFile
// We need these because we implement OutputFile
public String getMIMEType() {
return "";
}
public boolean isMasterDocument() {
return false;
}
}

View file

@ -37,7 +37,7 @@
************************************************************************/
// This version is adapted for Writer2LaTeX
// Version 1.2 (2010-03-15)
// Version 1.2 (2010-03-28)
package writer2latex.xmerge;
@ -1287,6 +1287,10 @@ public class OfficeDocument
public String getMIMEType() {
return "";
}
public boolean isMasterDocument() {
return false;
}
}