/**************************************************************************
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
2010 Wildrich Fourie
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.core;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.ReentrantLock;
import org.omegat.core.data.EntryKey;
import org.omegat.core.data.IProject;
import org.omegat.core.data.NotLoadedProject;
import org.omegat.core.segmentation.Segmenter;
import org.omegat.core.spellchecker.ISpellChecker;
import org.omegat.core.spellchecker.SpellChecker;
import org.omegat.core.tagvalidation.ITagValidation;
import org.omegat.core.tagvalidation.TagValidationTool;
import org.omegat.core.threads.IAutoSave;
import org.omegat.core.threads.SaveThread;
import org.omegat.filters2.IFilter;
import org.omegat.filters2.master.FilterMaster;
import org.omegat.filters2.master.PluginUtils;
import org.omegat.gui.comments.CommentsTextArea;
import org.omegat.gui.comments.IComments;
import org.omegat.gui.dictionaries.DictionariesTextArea;
import org.omegat.gui.dictionaries.IDictionaries;
import org.omegat.gui.editor.EditorController;
import org.omegat.gui.editor.IEditor;
import org.omegat.gui.editor.mark.BidiMarkerFactory;
import org.omegat.gui.editor.mark.ComesFromAutoTMMarker;
import org.omegat.gui.editor.mark.FontFallbackMarker;
import org.omegat.gui.editor.mark.IMarker;
import org.omegat.gui.editor.mark.NBSPMarker;
import org.omegat.gui.editor.mark.ProtectedPartsMarker;
import org.omegat.gui.editor.mark.RemoveTagMarker;
import org.omegat.gui.editor.mark.ReplaceMarker;
import org.omegat.gui.editor.mark.WhitespaceMarkerFactory;
import org.omegat.gui.exttrans.IMachineTranslation;
import org.omegat.gui.exttrans.MachineTranslateTextArea;
import org.omegat.gui.glossary.GlossaryManager;
import org.omegat.gui.glossary.GlossaryTextArea;
import org.omegat.gui.glossary.IGlossaries;
import org.omegat.gui.glossary.TransTipsMarker;
import org.omegat.gui.issues.IIssues;
import org.omegat.gui.issues.IssuesPanelController;
import org.omegat.gui.main.ConsoleWindow;
import org.omegat.gui.main.IMainWindow;
import org.omegat.gui.main.MainWindow;
import org.omegat.gui.matches.IMatcher;
import org.omegat.gui.matches.MatchesTextArea;
import org.omegat.gui.multtrans.MultipleTransPane;
import org.omegat.gui.notes.INotes;
import org.omegat.gui.notes.NotesTextArea;
import org.omegat.gui.properties.SegmentPropertiesArea;
import org.omegat.languagetools.LanguageToolWrapper;
import org.omegat.tokenizer.ITokenizer;
import org.omegat.util.Preferences;
import org.omegat.util.RecentProjects;
/**
* Class which contains all components instances.
*
* Note about threads synchronization: each component must have only local
* synchronization. It mustn't synchronize around other components or some other
* objects.
*
* Components which works in Swing UI thread can have other synchronization
* idea: it can not be synchronized to access to some data which changed only in
* UI thread.
*
* @author Alex Buloichik (alex73mail@gmail.com)
* @author Wildrich Fourie
*/
public class Core {
private static IProject currentProject;
private static IMainWindow mainWindow;
protected static IEditor editor;
private static ITagValidation tagValidation;
private static IIssues issuesWindow;
private static IMatcher matcher;
private static ISpellChecker spellChecker;
private static FilterMaster filterMaster;
protected static IAutoSave saveThread;
private static final ReentrantLock exclusiveRunLock = new ReentrantLock();
protected static IGlossaries glossary;
private static GlossaryManager glossaryManager;
private static MachineTranslateTextArea machineTranslatePane;
private static DictionariesTextArea dictionaries;
@SuppressWarnings("unused")
private static MultipleTransPane multiple;
private static INotes notes;
private static IComments comments;
private static Segmenter segmenter;
private static Map<String, String> cmdLineParams = Collections.emptyMap();
private static List<String> pluginsLoadingErrors = Collections.synchronizedList(new ArrayList<String>());
private static final List<IMarker> markers = new ArrayList<IMarker>();
/** Get project instance. */
public static IProject getProject() {
return currentProject;
}
/** Set new current project. */
public static void setProject(final IProject newCurrentProject) {
currentProject = newCurrentProject;
}
/** Get main window instance. */
public static IMainWindow getMainWindow() {
return mainWindow;
}
/** Get editor instance. */
public static IEditor getEditor() {
return editor;
}
/** Get tag validation component instance. */
public static ITagValidation getTagValidation() {
return tagValidation;
}
public static IIssues getIssues() {
return issuesWindow;
}
/** Get matcher component instance. */
public static IMatcher getMatcher() {
return matcher;
}
/** Get spell checker instance. */
public static ISpellChecker getSpellChecker() {
return spellChecker;
}
public static FilterMaster getFilterMaster() {
return filterMaster;
}
public static void setFilterMaster(FilterMaster newFilterMaster) {
filterMaster = newFilterMaster;
EntryKey.setIgnoreFileContext(newFilterMaster.getConfig().isIgnoreFileContext());
}
public static MachineTranslateTextArea getMachineTranslatePane() {
return machineTranslatePane;
}
public static IAutoSave getAutoSave() {
return saveThread;
}
/** Get glossary instance. */
public static IGlossaries getGlossary() {
return glossary;
}
public static GlossaryManager getGlossaryManager() {
return glossaryManager;
}
/** Get notes instance. */
public static INotes getNotes() {
return notes;
}
/**
* Get comments area
*
* @return the comment area
*/
public static IComments getComments() {
return comments;
}
public static IDictionaries getDictionaries() {
return dictionaries;
}
public static Segmenter getSegmenter() {
return segmenter;
}
public static void setSegmenter(Segmenter newSegmenter) {
segmenter = newSegmenter;
}
/**
* Initialize application components.
*/
public static void initializeGUI(final Map<String, String> params) throws Exception {
cmdLineParams = params;
// 1. Initialize project
currentProject = new NotLoadedProject();
// 2. Initialize application frame
MainWindow me = new MainWindow();
mainWindow = me;
// Load recent used projects
RecentProjects.updateMenu();
Core.registerMarker(new ProtectedPartsMarker());
Core.registerMarker(new RemoveTagMarker());
Core.registerMarker(new NBSPMarker());
Core.registerMarker(new TransTipsMarker());
Core.registerMarker(new WhitespaceMarkerFactory.SpaceMarker());
Core.registerMarker(new WhitespaceMarkerFactory.TabMarker());
Core.registerMarker(new WhitespaceMarkerFactory.LFMarker());
Core.registerMarker(new BidiMarkerFactory.RLMMarker());
Core.registerMarker(new BidiMarkerFactory.LRMMarker());
Core.registerMarker(new BidiMarkerFactory.PDFMarker());
Core.registerMarker(new BidiMarkerFactory.LROMarker());
Core.registerMarker(new BidiMarkerFactory.RLOMarker());
Core.registerMarker(new ReplaceMarker());
Core.registerMarker(new ComesFromAutoTMMarker());
Core.registerMarker(new FontFallbackMarker());
LanguageToolWrapper.init();
segmenter = new Segmenter(Preferences.getSRX());
filterMaster = new FilterMaster(Preferences.getFilters());
// 3. Initialize other components. They add themselves to the main window.
editor = new EditorController(me);
tagValidation = new TagValidationTool();
issuesWindow = new IssuesPanelController(me);
matcher = new MatchesTextArea(me);
GlossaryTextArea glossaryArea = new GlossaryTextArea(me);
glossary = glossaryArea;
glossaryManager = new GlossaryManager(glossaryArea);
notes = new NotesTextArea(me);
comments = new CommentsTextArea(me);
machineTranslatePane = new MachineTranslateTextArea(me);
dictionaries = new DictionariesTextArea(me);
spellChecker = new SpellChecker();
multiple = new MultipleTransPane(me);
new SegmentPropertiesArea(me);
SaveThread th = new SaveThread();
saveThread = th;
th.start();
}
/**
* Initialize application components.
*/
public static void initializeConsole(final Map<String, String> params) throws Exception {
cmdLineParams = params;
tagValidation = new TagValidationTool();
currentProject = new NotLoadedProject();
mainWindow = new ConsoleWindow();
}
/**
* Set main window instance for unit tests.
*
* @param mainWindow
*/
protected static void setMainWindow(IMainWindow mainWindow) {
Core.mainWindow = mainWindow;
}
/**
* Set project instance for unit tests.
*
* @param currentProject
*/
protected static void setCurrentProject(IProject currentProject) {
Core.currentProject = currentProject;
}
/**
* Register class for calculate marks.
*
* @param marker
* marker implementation
*/
public static void registerMarker(IMarker marker) {
markers.add(marker);
}
public static List<IMarker> getMarkers() {
return markers;
}
public static Map<String, String> getParams() {
return cmdLineParams;
}
public static void registerFilterClass(Class<? extends IFilter> clazz) {
PluginUtils.getFilterClasses().add(clazz);
}
public static void registerMachineTranslationClass(Class<? extends IMachineTranslation> clazz) {
PluginUtils.getMachineTranslationClasses().add(clazz);
}
public static void registerMarkerClass(Class<? extends IMarker> clazz) {
PluginUtils.getMarkerClasses().add(clazz);
}
public static void registerTokenizerClass(Class<? extends ITokenizer> clazz) {
PluginUtils.getTokenizerClasses().add(clazz);
}
/**
* Get all plugin loading errors.
*/
public static List<String> getPluginsLoadingErrors() {
return pluginsLoadingErrors;
}
/**
* Any plugin can call this method for say about error on loading.
*/
public static void pluginLoadingError(String errorText) {
pluginsLoadingErrors.add(errorText);
}
/**
* Use this to perform operations that must not be run concurrently.
* <p>
* For instance project load/save/compile/autosave operations must not be executed in parallel because it
* will break project files, especially during team synchronization. For guaranteed non-parallel
* execution, all such operations must be executed via this method.
*
* @param waitForUnlock
* should execution wait for unlock 3 minutes
* @param run
* code for execute
* @throws InterruptedException,
* TimeoutException
*/
public static void executeExclusively(boolean waitForUnlock, Runnable run) throws InterruptedException, TimeoutException {
if (!exclusiveRunLock.tryLock(waitForUnlock ? 180000 : 1, TimeUnit.MILLISECONDS)) {
throw new TimeoutException();
}
try {
run.run();
} finally {
exclusiveRunLock.unlock();
}
}
}