/**************************************************************************
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
2009-2010 Alex Buloichik
2013 Alex Buloichik
2015 Didier Briel
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.gui.glossary;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import org.omegat.core.Core;
import org.omegat.core.glossaries.IGlossary;
import org.omegat.filters2.master.PluginUtils;
import org.omegat.util.DirectoryMonitor;
import org.omegat.util.Language;
import org.omegat.util.Log;
import org.omegat.util.OConsts;
import org.omegat.util.Preferences;
/**
* Class that loads glossary files and adds glossary entries to strings of the source files.
*
* This class don't need any threads synchronization code, since it only set and clear 'glossaryEntries' var.
*
* @author Keith Godfrey
* @author Maxym Mykhalchuk
* @author Alex Buloichik <alex73mail@gmail.com>
* @author Didier Briel
*/
public class GlossaryManager implements DirectoryMonitor.Callback {
protected DirectoryMonitor monitor;
private final GlossaryTextArea pane;
private final Map<String, List<GlossaryEntry>> glossaries = new TreeMap<String, List<GlossaryEntry>>();
protected File priorityGlossary;
protected IGlossary[] externalGlossaries;
public GlossaryManager(final GlossaryTextArea pane) {
this.pane = pane;
List<IGlossary> gl = new ArrayList<IGlossary>();
for (Class<?> glc : PluginUtils.getGlossaryClasses()) {
try {
gl.add((IGlossary) glc.newInstance());
} catch (Exception ex) {
Log.log(ex);
}
}
externalGlossaries = gl.toArray(new IGlossary[gl.size()]);
Preferences.addPropertyChangeListener(e -> {
if (Core.getProject().isProjectLoaded()) {
switch (e.getPropertyName()) {
case Preferences.GLOSSARY_TBX_DISPLAY_CONTEXT:
forceReloadTBX();
break;
case Preferences.GLOSSARY_NOT_EXACT_MATCH:
case Preferences.GLOSSARY_STEMMING:
forceUpdateGlossary();
break;
}
}
});
}
public void addGlossaryProvider(IGlossary provider) {
List<IGlossary> providers = new ArrayList<IGlossary>(Arrays.asList(externalGlossaries));
providers.add(provider);
externalGlossaries = providers.toArray(new IGlossary[providers.size()]);
}
public void start() {
File dir = new File(Core.getProject().getProjectProperties().getGlossaryRoot());
priorityGlossary = new File(Core.getProject().getProjectProperties().getWriteableGlossary());
monitor = new DirectoryMonitor(dir, this);
monitor.start();
}
public void stop() {
monitor.fin();
synchronized (this) {
glossaries.clear();
}
}
@Override
public void fileChanged(File file) {
synchronized (this) {
glossaries.remove(file.getPath());
}
if (file.exists()) {
try {
List<GlossaryEntry> entries = loadGlossaryFile(file);
if (entries != null) {
synchronized (this) {
Log.logRB("CT_LOADING_GLOSSARY_DETAILS", entries.size(), file.getName());
glossaries.put(file.getPath(), entries);
}
}
} catch (Exception ex) {
Log.logRB("CT_ERROR_ACCESS_GLOSSARY_DIR");
Log.log(ex);
}
}
pane.refresh();
}
public void forceReloadTBX() {
Set<File> files = monitor.getExistFiles();
for (File f : files) {
if (f.getName().toLowerCase().endsWith(OConsts.EXT_TBX)) {
fileChanged(f);
}
}
}
public void forceUpdateGlossary() {
pane.refresh();
}
/**
* Loads one glossary file. It choose and calls required required reader.
*/
private List<GlossaryEntry> loadGlossaryFile(final File file) throws Exception {
boolean isPriority = priorityGlossary.equals(file);
String fname_lower = file.getName().toLowerCase();
if (fname_lower.endsWith(OConsts.EXT_TSV_DEF)) {
Log.logRB("CT_LOADING_GLOSSARY", file.getName());
return GlossaryReaderTSV.read(file, isPriority);
} else if (fname_lower.endsWith(OConsts.EXT_TSV_UTF8) || fname_lower.endsWith(OConsts.EXT_TSV_TXT)) {
Log.logRB("CT_LOADING_GLOSSARY", file.getName());
return GlossaryReaderTSV.read(file, isPriority);
} else if (fname_lower.endsWith(OConsts.EXT_CSV_UTF8)) {
Log.logRB("CT_LOADING_GLOSSARY", file.getName());
return GlossaryReaderCSV.read(file, isPriority);
} else if (fname_lower.endsWith(OConsts.EXT_TBX)) {
Log.logRB("CT_LOADING_GLOSSARY", file.getName());
return GlossaryReaderTBX.read(file, isPriority);
} else {
return null;
}
}
/**
* Get glossary entries.
*
* @return all entries
* @param src
*/
public List<GlossaryEntry> getGlossaryEntries(String src) {
List<GlossaryEntry> result = new ArrayList<GlossaryEntry>();
synchronized (this) {
for (List<GlossaryEntry> en : glossaries.values()) {
result.addAll(en);
}
}
addExternalGlossaryEntries(result, src);
return result;
}
/**
* Get glossary entries for search operation. Almost the same as getGlossaryEntries(), except search
* usually executed for every segment in project, i.e. should work enough fast. Then, search should be
* produced by local files only.
*
* @return all entries
* @param src
*/
public List<GlossaryEntry> search(String src) {
List<GlossaryEntry> result = new ArrayList<GlossaryEntry>();
synchronized (this) {
for (List<GlossaryEntry> en : glossaries.values()) {
result.addAll(en);
}
}
return result;
}
private void addExternalGlossaryEntries(List<GlossaryEntry> result, String src) {
Language source = Core.getProject().getProjectProperties().getSourceLanguage();
Language target = Core.getProject().getProjectProperties().getTargetLanguage();
for (IGlossary gl : externalGlossaries) {
try {
result.addAll(gl.search(source, target, src));
} catch (Exception ex) {
Log.log(ex);
}
}
}
}