package com.vistatec.ocelot.tm.gui.match; import java.awt.Component; import java.awt.Container; import java.awt.event.ContainerEvent; import java.awt.event.ContainerListener; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import javax.swing.JOptionPane; import javax.swing.JTabbedPane; import net.sf.okapi.common.LocaleId; import net.sf.okapi.common.resource.TextContainer; import net.sf.okapi.common.resource.TextFragment; import net.sf.okapi.tm.pensieve.common.TmHit; import net.sf.okapi.tm.pensieve.common.TranslationUnit; import net.sf.okapi.tm.pensieve.common.TranslationUnitVariant; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.eventbus.Subscribe; import com.vistatec.ocelot.events.OpenFileEvent; import com.vistatec.ocelot.events.SegmentTargetUpdateFromMatchEvent; import com.vistatec.ocelot.events.api.OcelotEventQueue; import com.vistatec.ocelot.events.api.OcelotEventQueueListener; import com.vistatec.ocelot.segment.model.BaseSegmentVariant; import com.vistatec.ocelot.segment.model.OcelotSegment; import com.vistatec.ocelot.segment.model.SegmentAtom; import com.vistatec.ocelot.segment.model.SegmentVariant; import com.vistatec.ocelot.segment.model.enrichment.TranslationEnrichment; import com.vistatec.ocelot.segment.model.okapi.TextContainerVariant; import com.vistatec.ocelot.tm.TmMatch; import com.vistatec.ocelot.tm.TmService; import com.vistatec.ocelot.tm.okapi.PensieveTmMatch; import com.vistatec.ocelot.xliff.XLIFFDocument; /** * This class stands over all graphic processes pertaining the TM match * functionalities: translations matches and concordance search. It manages two * detachable panels: the <code>TranslationsPanel</code>. */ public class TmGuiMatchController implements OcelotEventQueueListener { private static final Logger LOG = LoggerFactory.getLogger(TmGuiMatchController.class); /** * The TM service providing methods for translations match and concordance * search. */ private TmService tmService; /** The Ocelot event queue. */ private OcelotEventQueue eventQueue; /** The current selected segment in the Ocelot main grid. */ private OcelotSegment currSelectedSegment; /** The concordance search panel. */ private ConcordanceSearchPanel concordancePanel; /** The translations panel. */ private TranslationsPanel translationsPanel; /** The tabbed pane containing translations and concordance search panel. */ private JTabbedPane tmPanel; /** The component containing the TM tabbed panel in Ocelot main frame. */ private Container tmPanelContainer; /** Current XLIFF document. **/ private XLIFFDocument xliff; /** * Constructor. * * @param tmService * the TM service * @param eventQueue * the Ocelot event queue. */ public TmGuiMatchController(final TmService tmService, final OcelotEventQueue eventQueue) { this.tmService = tmService; this.eventQueue = eventQueue; eventQueue.registerListener(this); } @Subscribe public void openFile(OpenFileEvent e) { this.xliff = e.getDocument(); } /** * Gets translations matches for the selected segment. * * @param currentSelection * the list of segment atoms for the selected segment. * @return the list of translation matches. */ public List<TmMatch> getFuzzyMatches(List<SegmentAtom> currentSelection) { List<TmMatch> matches = null; try { matches = tmService.getFuzzyTermMatches(currentSelection); Collections.shuffle(matches); } catch (IOException e) { LOG.trace("Error while retrieving fuzzy matches.", e); } if (matches != null) { Collections.sort(matches, new TmMatchComparator()); } return matches; } /** * Gets the results of the Concordance Search. * * @param currentSelection * list of segment atoms containg the searched string. * @return the segments matching the concordance string. */ public List<TmMatch> getConcordanceMatches( List<SegmentAtom> currentSelection) { List<TmMatch> matches = null; try { matches = tmService.getConcordanceMatches(currentSelection); } catch (IOException e) { LOG.trace("Error while retrieving concordance search matches.", e); JOptionPane .showMessageDialog( concordancePanel.getAttachedComponent(), "An error has occured while finding concordance search matches.", "Concordance Search Error", JOptionPane.ERROR_MESSAGE); } return matches; } /** * Performs the concordance search for the string passed as parameter. * * @param text * the text to be searched. */ public void performConcordanceSearch(final String text) { concordancePanel.setTextAndPerformConcordanceSearch(text); } /** * Gets the concordance panel. * * @return the concordance panel. */ public Component getConcordancePanel() { if (concordancePanel == null) { concordancePanel = new ConcordanceSearchPanel(this); } return concordancePanel.getAttachedComponent(); } /** * Replaces the whole content of the target in the selected segment in * Ocelot main grid with the new target passed as parameter. * * @param newTarget * the new target. */ public void replaceTarget(final SegmentVariant newTarget) { if (currSelectedSegment != null) { SegmentVariant textContainerVariant = new TextContainerVariant( new TextContainer(newTarget.getDisplayText())); eventQueue.post(new SegmentTargetUpdateFromMatchEvent(xliff, currSelectedSegment, textContainerVariant)); } } /** * Invoked when a segment is selected in the Ocelot main grid. It stores the * selected segment in a class field and requests the translations matches * for it. * * @param selectedSegment * the selected segment in the Ocelot main grid. */ public void setSelectedSegment(OcelotSegment selectedSegment) { if (!selectedSegment.equals(currSelectedSegment)) { this.currSelectedSegment = selectedSegment; update(); } } /** * Updates the translation for a specific segment number. * * @param segmentNumber * the segment number */ public void update(int segmentNumber) { if (currSelectedSegment != null && currSelectedSegment.getSegmentNumber() == segmentNumber) { update(); } } /** * Updates the translations in the panel. */ private void update() { if (translationsPanel != null ) { selectTranslationsTab(); translationsPanel.setLoading(); List<TmMatch> translations = getFuzzyMatches(currSelectedSegment .getSource().getAtoms()); if (currSelectedSegment.getSource() instanceof BaseSegmentVariant) { TranslationEnrichment transEnrich = ((BaseSegmentVariant) currSelectedSegment .getSource()).getTranslationEnrichment(); if (transEnrich != null) { TmHit hit = new TmHit(); TranslationUnit tu = new TranslationUnit(); TextFragment fragment = new TextFragment( transEnrich.getTranslation()); TranslationUnitVariant tuVariant = new TranslationUnitVariant( new LocaleId(transEnrich.getLanguage()), fragment); tu.setTarget(tuVariant); tuVariant = new TranslationUnitVariant(null, new TextFragment(currSelectedSegment.getSource() .getDisplayText())); tu.setSource(tuVariant); hit.setTu(tu); hit.setScore(100f); TmMatch fremeMatch = new PensieveTmMatch( "FREME e-Translation", hit); if (translations == null) { translations = new ArrayList<TmMatch>(); } translations.add(0, fremeMatch); } } translationsPanel.setTranslationSearchResults(translations); } } /** * Gets the tabbed pane containing the translations panel and the * concordance search panel. * * @return the TM tabbed pane */ public Component getTmPanel() { if (tmPanel == null) { tmPanel = new JTabbedPane(); } if (translationsPanel == null) { translationsPanel = new TranslationsPanel(this); } tmPanel.add(translationsPanel.getAttachedComponent()); if (concordancePanel == null) { concordancePanel = new ConcordanceSearchPanel(this); } tmPanel.add(concordancePanel.getAttachedComponent()); tmPanel.addContainerListener(new ContainerListener() { /* * (non-Javadoc) * * @see * java.awt.event.ContainerListener#componentRemoved(java.awt.event * .ContainerEvent) */ @Override public void componentRemoved(ContainerEvent e) { if (tmPanel.getTabCount() == 0) { System.out.println("0 tabs"); tmPanelContainer = tmPanel.getParent(); tmPanelContainer.remove(tmPanel); tmPanelContainer.repaint(); } } /* * (non-Javadoc) * * @see * java.awt.event.ContainerListener#componentAdded(java.awt.event * .ContainerEvent) */ @Override public void componentAdded(ContainerEvent e) { if (tmPanel.getTabCount() == 1) { tmPanelContainer.add(tmPanel); tmPanelContainer.repaint(); tmPanelContainer = null; } } }); return tmPanel; } /** * Gets the tabbed panel. * * @return the tabbed panel */ public Component getTabbedContainer() { return tmPanel; } /** * Selects the concordance search tab. */ public void selectConcordanceTab() { try { tmPanel.setSelectedComponent(concordancePanel .getAttachedComponent()); } catch (IllegalArgumentException e) { // the translation panel has been detached. It's not contained an } } /** * Selects the translations panel tab. */ public void selectTranslationsTab() { try { tmPanel.setSelectedComponent(translationsPanel .getAttachedComponent()); } catch (IllegalArgumentException e) { // the translation panel has been detached. It's not contained an } } } /** * Comparator class for TmMatch objects. */ class TmMatchComparator implements Comparator<TmMatch> { @Override public int compare(TmMatch o1, TmMatch o2) { int comp = 0; if (o1.getMatchScore() > o2.getMatchScore()) { comp = -1; } else if (o1.getMatchScore() < o2.getMatchScore()) { comp = 1; } return comp; } }