/**************************************************************************
OmegaT - Computer Assisted Translation (CAT) tool
with fuzzy matching, translation memory, keyword search,
glossaries, and translation leveraging into updated projects.
Copyright (C) 2000-2006 Keith Godfrey and Maxym Mykhalchuk
Home page: http://www.omegat.org/
Support center: http://groups.yahoo.com/group/OmegaT/
This file is part of OmegaT.
OmegaT is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OmegaT 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/
package org.omegat.filters3.xml.opendoc;
import java.awt.Window;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.omegat.filters2.AbstractFilter;
import org.omegat.filters2.FilterContext;
import org.omegat.filters2.Instance;
import org.omegat.filters2.TranslationException;
import org.omegat.util.Log;
import org.omegat.util.OStrings;
/**
* Filter for Open Document file format.
*
* @author Maxym Mykhalchuk
*/
public class OpenDocFilter extends AbstractFilter {
private static final Set<String> TRANSLATABLE = new HashSet<String>(Arrays.asList("content.xml",
"styles.xml", "meta.xml"));
protected boolean requirePrevNextFields() {
return true;
}
/** Returns true if it's OpenDocument file. */
public boolean isFileSupported(File inFile, Map<String, String> config, FilterContext fc) {
try {
ZipFile file = new ZipFile(inFile);
Enumeration<? extends ZipEntry> entries = file.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
if (TRANSLATABLE.contains(entry.getName())) {
file.close();
return true;
}
}
file.close();
} catch (IOException e) {
}
return false;
}
OpenDocXMLFilter xmlfilter = null;
private OpenDocXMLFilter createXMLFilter(Map<String, String> options) {
xmlfilter = new OpenDocXMLFilter();
xmlfilter.setCallbacks(entryParseCallback, entryTranslateCallback);
// Defining the actual dialect, because at this step
// we have the options
OpenDocDialect dialect = (OpenDocDialect) xmlfilter.getDialect();
dialect.defineDialect(new OpenDocOptions(options));
return xmlfilter;
}
/**
* Returns a temporary file for OpenOffice XML. A nasty hack, to say polite way.
*/
private File tmp() throws IOException {
return File.createTempFile("ot-oo-", ".xml");
}
/**
* Processes a single OpenDocument file, which is actually a ZIP file consisting of many XML files, some
* of which should be translated.
*/
@Override
public void processFile(File inFile, File outFile, FilterContext fc) throws IOException,
TranslationException {
ZipFile zipfile = new ZipFile(inFile);
ZipOutputStream zipout = null;
if (outFile != null)
zipout = new ZipOutputStream(new FileOutputStream(outFile));
Enumeration<? extends ZipEntry> zipcontents = zipfile.entries();
while (zipcontents.hasMoreElements()) {
ZipEntry zipentry = zipcontents.nextElement();
String shortname = zipentry.getName();
if (shortname.lastIndexOf('/') >= 0)
shortname = shortname.substring(shortname.lastIndexOf('/') + 1);
if (TRANSLATABLE.contains(shortname)) {
File tmpin = tmp();
FileUtils.copyInputStreamToFile(zipfile.getInputStream(zipentry), tmpin);
File tmpout = null;
if (zipout != null)
tmpout = tmp();
try {
createXMLFilter(processOptions).processFile(tmpin, tmpout, fc);
} catch (Exception e) {
zipfile.close();
throw new TranslationException(e.getLocalizedMessage() + "\n"
+ OStrings.getString("OpenDoc_ERROR_IN_FILE") + inFile);
}
if (zipout != null) {
ZipEntry outentry = new ZipEntry(zipentry.getName());
outentry.setMethod(ZipEntry.DEFLATED);
zipout.putNextEntry(outentry);
FileUtils.copyFile(tmpout, zipout);
zipout.closeEntry();
}
if (!tmpin.delete())
tmpin.deleteOnExit();
if (tmpout != null) {
if (!tmpout.delete())
tmpout.deleteOnExit();
}
} else {
if (zipout != null) {
ZipEntry outentry = new ZipEntry(zipentry.getName());
zipout.putNextEntry(outentry);
IOUtils.copy(zipfile.getInputStream(zipentry), zipout);
zipout.closeEntry();
}
}
}
if (zipout != null)
zipout.close();
zipfile.close();
}
/** Human-readable OpenDocument filter name. */
public String getFileFormatName() {
return OStrings.getString("OpenDoc_FILTER_NAME");
}
/** Extensions... */
public Instance[] getDefaultInstances() {
return new Instance[] { new Instance("*.sx?"), new Instance("*.st?"), new Instance("*.od?"),
new Instance("*.ot?"), };
}
/** Source encoding can not be varied by the user. */
public boolean isSourceEncodingVariable() {
return false;
}
/** Target encoding can not be varied by the user. */
public boolean isTargetEncodingVariable() {
return false;
}
/** Not implemented. */
protected void processFile(BufferedReader inFile, BufferedWriter outFile, FilterContext fc) throws IOException,
TranslationException {
throw new IOException("Not Implemented!");
}
/**
* Returns true to indicate that the OpenDoc filter has options.
*
* @return True, because the OpenDoc filter has options.
*/
public boolean hasOptions() {
return true;
}
/**
* OpenDoc Filter shows a <b>modal</b> dialog to edit its own options.
*
* @param currentOptions
* Current options to edit.
* @return Updated filter options if user confirmed the changes, and current options otherwise.
*/
public Map<String, String> changeOptions(Window parent, Map<String, String> currentOptions) {
try {
EditOpenDocOptionsDialog dialog = new EditOpenDocOptionsDialog(parent, currentOptions);
dialog.setVisible(true);
if (EditOpenDocOptionsDialog.RET_OK == dialog.getReturnStatus())
return dialog.getOptions().getOptionsMap();
else
return null;
} catch (Exception e) {
Log.logErrorRB("HTML_EXC_EDIT_OPTIONS");
Log.log(e);
return null;
}
}
@Override
public String getInEncodingLastParsedFile() {
//Encoding is 'binary', it is zipped. Inside there may be many files. It makes no sense to display the encoding of some xml file inside.
return "OpenDoc";
}
}