Java tutorial
/************************************************************************** OmegaT - Computer Assisted Translation (CAT) tool with fuzzy matching, translation memory, keyword search, glossaries, and translation leveraging into updated projects. Copyright (C) 2008 Alex Buloichik 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.filters; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathFactory; import org.omegat.core.Core; import org.omegat.core.data.EntryKey; import org.omegat.core.data.IProject; import org.omegat.core.data.ProjectProperties; import org.omegat.core.data.ProtectedPart; import org.omegat.core.data.RealProject; import org.omegat.core.data.SourceTextEntry; import org.omegat.filters2.AbstractFilter; import org.omegat.filters2.FilterContext; import org.omegat.filters2.IAlignCallback; import org.omegat.filters2.IFilter; import org.omegat.filters2.IParseCallback; import org.omegat.filters2.ITranslateCallback; import org.omegat.filters2.master.FilterMaster; import org.omegat.tokenizer.DefaultTokenizer; import org.omegat.util.Language; import org.omegat.util.TMXReader2; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.xml.sax.InputSource; import org.apache.commons.io.FileUtils; import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual; import static org.junit.Assert.*; /** * Base class for test filter parsing. * * @author Alex Buloichik <alex73mail@gmail.com> * @author Hiroshi Miura */ abstract class TestFilterBase { protected FilterContext context = new FilterContext(new Language("en"), new Language("be"), false) .setTargetTokenizerClass(DefaultTokenizer.class); protected File outFile; protected void setUp() throws Exception { Core.initializeConsole(Collections.emptyMap()); Core.setFilterMaster(new FilterMaster(FilterMaster.createDefaultFiltersConfig())); Core.setProject(new TestProject(new ProjectPropertiesTest())); } protected List<String> parse(IFilter filter, String resource) throws Exception { return parse(filter, resource, Collections.emptyMap()); } protected List<String> parse(IFilter filter, String resource, Map<String, String> options) throws Exception { final List<String> result = new ArrayList<>(); filter.parseFile(new File(this.getClass().getResource(resource).getFile()), options, context, new IParseCallback() { public void addEntry(String id, String source, String translation, boolean isFuzzy, String comment, IFilter filter) { addEntry(id, source, translation, isFuzzy, comment, null, filter, null); } public void addEntry(String id, String source, String translation, boolean isFuzzy, String comment, String path, IFilter filter, List<ProtectedPart> protectedParts) { String[] props = comment == null ? null : new String[] { "comment", comment }; addEntryWithProperties(id, source, translation, isFuzzy, props, path, filter, protectedParts); } public void addEntryWithProperties(String id, String source, String translation, boolean isFuzzy, String[] props, String path, IFilter filter, List<ProtectedPart> protectedParts) { if (!source.isEmpty()) { result.add(source); } } public void linkPrevNextSegments() { } }); return result; } protected void parse2(final AbstractFilter filter, final String filename, final Map<String, String> result, final Map<String, String> legacyTMX) throws Exception { filter.parseFile(new File(filename), Collections.emptyMap(), context, new IParseCallback() { public void addEntry(String id, String source, String translation, boolean isFuzzy, String comment, IFilter filter) { addEntry(id, source, translation, isFuzzy, comment, null, filter, null); } public void addEntry(String id, String source, String translation, boolean isFuzzy, String comment, String path, IFilter filter, List<ProtectedPart> protectedParts) { String[] props = comment == null ? null : new String[] { "comment", comment }; addEntryWithProperties(id, source, translation, isFuzzy, props, path, filter, protectedParts); } @Override public void addEntryWithProperties(String id, String source, String translation, boolean isFuzzy, String[] props, String path, IFilter filter, List<ProtectedPart> protectedParts) { String segTranslation = isFuzzy ? null : translation; result.put(source, segTranslation); if (translation != null) { // Add systematically the TU as a legacy TMX String tmxSource = isFuzzy ? "[" + filter.getFuzzyMark() + "] " + source : source; addFileTMXEntry(tmxSource, translation); } } public void addFileTMXEntry(String source, String translation) { legacyTMX.put(source, translation); } public void linkPrevNextSegments() { } }); } protected List<ParsedEntry> parse3(AbstractFilter filter, String filename, Map<String, String> options) throws Exception { final List<ParsedEntry> result = new ArrayList<ParsedEntry>(); filter.parseFile(new File(filename), options, context, new IParseCallback() { public void addEntry(String id, String source, String translation, boolean isFuzzy, String comment, IFilter filter) { addEntry(id, source, translation, isFuzzy, comment, null, filter, null); } public void addEntry(String id, String source, String translation, boolean isFuzzy, String comment, String path, IFilter filter, List<ProtectedPart> protectedParts) { String[] props = comment == null ? null : new String[] { "comment", comment }; addEntryWithProperties(id, source, translation, isFuzzy, props, path, filter, protectedParts); } @Override public void addEntryWithProperties(String id, String source, String translation, boolean isFuzzy, String[] props, String path, IFilter filter, List<ProtectedPart> protectedParts) { if (source.isEmpty()) { return; } ParsedEntry e = new ParsedEntry(); e.id = id; e.source = source; e.translation = translation; e.isFuzzy = isFuzzy; e.props = props; e.path = path; result.add(e); } public void linkPrevNextSegments() { } }); return result; } protected void translate(IFilter filter, String resource) throws Exception { translate(filter, resource, Collections.emptyMap()); } protected void translate(IFilter filter, String resource, Map<String, String> config) throws Exception { outFile = File.createTempFile("output", ".txt"); outFile.deleteOnExit(); filter.translateFile(new File(this.getClass().getResource(resource).getFile()), outFile, config, context, new ITranslateCallback() { public String getTranslation(String id, String source, String path) { return source; } public String getTranslation(String id, String source) { return source; } public void linkPrevNextSegments() { } public void setPass(int pass) { } }); } protected void align(IFilter filter, String in, String out, IAlignCallback callback) throws Exception { File inFile = new File("/data/filters/" + in); File outFile = new File("/data/filters/" + out); filter.alignFile(inFile, outFile, Collections.emptyMap(), context, callback); } protected void testTranslate(final IFilter filter, final String testcase) throws Exception { translateText(filter, "/" + testcase + ".txt"); } protected void translateText(IFilter filter, String resource) throws Exception { translateText(filter, resource, Collections.emptyMap()); } protected void translateText(IFilter filter, String resource, Map<String, String> config) throws Exception { translate(filter, resource, config); boolean result = FileUtils.contentEquals(new File(this.getClass().getResource(resource).getFile()), outFile); if (!result) { fails("Translated text, which should be as same as source one, is not equals with source."); } } protected void translateXML(AbstractFilter filter, String filename) throws Exception { translate(filter, filename); compareXML(new File(filename), outFile); } public static void compareBinary(File f1, File f2) throws Exception { ByteArrayOutputStream d1 = new ByteArrayOutputStream(); FileUtils.copyFile(f1, d1); ByteArrayOutputStream d2 = new ByteArrayOutputStream(); FileUtils.copyFile(f2, d2); assertEquals(d1.size(), d2.size()); byte[] a1 = d1.toByteArray(); byte[] a2 = d2.toByteArray(); for (int i = 0; i < d1.size(); i++) { assertEquals(a1[i], a2[i]); } } /** * Remove version and toolname, then compare. */ protected void compareTMX(File f1, File f2) throws Exception { XPathExpression exprVersion = XPathFactory.newInstance().newXPath() .compile("/tmx/header/@creationtoolversion"); XPathExpression exprTool = XPathFactory.newInstance().newXPath().compile("/tmx/header/@creationtool"); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder builder = factory.newDocumentBuilder(); builder.setEntityResolver(TMXReader2.TMX_DTD_RESOLVER); Document doc1 = builder.parse(f1); Document doc2 = builder.parse(f2); Node n; n = (Node) exprVersion.evaluate(doc1, XPathConstants.NODE); n.setNodeValue(""); n = (Node) exprVersion.evaluate(doc2, XPathConstants.NODE); n.setNodeValue(""); n = (Node) exprTool.evaluate(doc1, XPathConstants.NODE); n.setNodeValue(""); n = (Node) exprTool.evaluate(doc2, XPathConstants.NODE); n.setNodeValue(""); assertXMLEqual(doc1, doc2); } protected void compareXML(File f1, File f2) throws Exception { compareXML(f1.toURI().toURL(), f2.toURI().toURL()); } protected void compareXML(URL f1, URL f2) throws Exception { assertXMLEqual(new InputSource(f1.toExternalForm()), new InputSource(f2.toExternalForm())); } protected static class ParsedEntry { String id; String source; String translation; boolean isFuzzy; String[] props; String path; } protected IProject.FileInfo loadSourceFiles(IFilter filter, String resource, Map<String, String> filterOptions) throws Exception { ProjectPropertiesTest props = new ProjectPropertiesTest(); TestProject p = new TestProject(props); String file = this.getClass().getResource(resource).getFile(); return p.loadSourceFiles(filter, file, filterOptions); } protected IProject.FileInfo loadSourceFiles(IFilter filter, String file) throws Exception { return loadSourceFiles(filter, file, Collections.emptyMap()); } protected IProject.FileInfo fi; protected int fiCount; protected void checkMultiStart(IProject.FileInfo fi, String file) { this.fi = fi; fiCount = 0; for (SourceTextEntry ste : fi.entries) { assertEquals(file, ste.getKey().file); assertEquals(ste.getSrcText(), ste.getKey().sourceText); } } protected void checkMultiEnd() { assertEquals(fiCount, fi.entries.size()); } protected void checkMulti(String sourceText, String id, String path, String prev, String next, String comment) { assertEquals(new EntryKey(fi.filePath, sourceText, id, prev, next, path), fi.entries.get(fiCount).getKey()); assertEquals(comment, fi.entries.get(fiCount).getComment()); fiCount++; } protected void checkMultiProps(String sourceText, String id, String path, String prev, String next, String... props) { assertEquals(new EntryKey(fi.filePath, sourceText, id, prev, next, path), fi.entries.get(fiCount).getKey()); List<String> expected = Arrays.asList(props); String[] actual = fi.entries.get(fiCount).getRawProperties(); assertEquals(props.length, actual.length); for (int i = 0; i < actual.length; i += 2) { int keyIndex = expected.indexOf(actual[i]); assertFalse(keyIndex == -1); int valIndex = expected.indexOf(actual[i + 1]); assertEquals(keyIndex + 1, valIndex); } fiCount++; } protected SourceTextEntry checkMultiNoPrevNext(String sourceText, String id, String path, String comment) { SourceTextEntry ste = fi.entries.get(fiCount); assertEquals(path, ste.getKey().path); assertEquals(id, ste.getKey().id); assertEquals(sourceText, ste.getKey().sourceText); assertEquals(comment, ste.getComment()); fiCount++; return ste; } protected void skipMulti() { fiCount++; } /** * ProjectProperties successor for create project without directory. */ protected static class ProjectPropertiesTest extends ProjectProperties { ProjectPropertiesTest() { super(); setTargetTokenizer(DefaultTokenizer.class); } } /** * RealProject successor for load file testing only. */ protected class TestProject extends RealProject { public TestProject(ProjectProperties props) { super(props); } public FileInfo loadSourceFiles(IFilter filter, String file, Map<String, String> filterOptions) throws Exception { Core.setProject(this); Set<String> existSource = new HashSet<String>(); Set<EntryKey> existKeys = new HashSet<EntryKey>(); LoadFilesCallback loadFilesCallback = new LoadFilesCallback(existSource, existKeys); FileInfo fi = new FileInfo(); fi.filePath = file; loadFilesCallback.setCurrentFile(fi); filter.parseFile(new File(file), filterOptions, context, loadFilesCallback); loadFilesCallback.fileFinished(); return fi; } } protected List<AlignedEntry> al; protected int alCount; protected void checkAlignStart(TestAlignCallback calback) { this.al = calback.entries; alCount = 0; } protected void checkAlignEnd() { assertEquals(alCount, al.size()); } protected void checkAlign(String id, String source, String translation, String path) { AlignedEntry en = al.get(alCount); assertEquals(id, en.id); assertEquals(source, en.source); assertEquals(translation, en.translation); assertEquals(path, en.path); alCount++; } protected void checkAlignById(String id, String source, String translation, String path) { for (AlignedEntry en : al) { if (id.equals(en.id)) { assertEquals(source, en.source); assertEquals(translation, en.translation); assertEquals(path, en.path); alCount++; return; } } fail(); } protected static class TestAlignCallback implements IAlignCallback { public List<AlignedEntry> entries = new ArrayList<AlignedEntry>(); public void addTranslation(String id, String source, String translation, boolean isFuzzy, String path, IFilter filter) { AlignedEntry en = new AlignedEntry(); en.id = id; en.source = source; en.translation = translation; en.path = path; entries.add(en); } } protected static class AlignedEntry { public String id; public String source; public String translation; public String path; } /** * Create BufferedReader from specified file and encoding. * * @param inFile file to read. * @param inEncoding file encoding. * @return BufferReader object. * @throws IOException when file I/O error happened. */ protected static BufferedReader getBufferedReader(final File inFile, final String inEncoding) throws IOException { InputStreamReader isr; if (inEncoding == null) { isr = new InputStreamReader(new FileInputStream(inFile), Charset.defaultCharset()); } else { isr = new InputStreamReader(new FileInputStream(inFile), inEncoding); } return new BufferedReader(isr); } }