package gate.alignment.gui; import java.util.*; import java.util.List; import java.util.Timer; import javax.swing.*; import javax.swing.border.TitledBorder; import javax.swing.event.MouseInputAdapter; //import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableModel; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.MouseEvent; import java.awt.geom.Line2D; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.OutputStreamWriter; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; import gate.*; import gate.alignment.*; import gate.alignment.gui.actions.impl.AlignAction; import gate.alignment.gui.actions.impl.RemoveAlignmentAction; import gate.alignment.gui.actions.impl.ResetAction; import gate.compound.CompoundDocument; import gate.compound.impl.AbstractCompoundDocument; import gate.creole.*; import gate.gui.MainFrame; import gate.swing.ColorGenerator; import gate.swing.XJTable; import gate.util.GateException; import gate.util.GateRuntimeException; /** * This class provides an editor for aligning texts in a compound * document. */ public class AlignmentEditor extends AbstractVisualResource implements ActionListener, AlignmentListener { private static final long serialVersionUID = -2867467022258265114L; /** * default actions config file. */ private static final String ACTIONS_CONFIG_FILE = "actions.conf"; /** * scrollpane that holds all the sourcePanel, targetPanel and the * linesCanvas */ private JScrollPane waScrollPane; /** * text field that allows users to input the class name for iterating * method */ private JTextField iteratingMethodTF; /** * panel with source document settings */ private JPanel sourceDocPanel; /** * panel with target document settings */ private JPanel targetDocPanel; /** * panel with iteration and alignment feature options */ private JPanel iteratingPanel; /** * panel with various buttons */ private JPanel populateButtonsPanel; /** * main split pane, that contains settings and the actual alignment * gui */ private JSplitPane mainPanel; /** * panel with settings related options */ private JPanel paramPanel; /** * panel with word alignment GUI components */ private JPanel waPanel; /** * properties panel that shows various options available to user when * aligning */ private JPanel propertiesPanel; /** * holds tabbed panes */ private JTabbedPane tableTabbedPane; /** * source panel that has labels for each individual alignment unit in * the source parent of alignment unit */ private JPanel sourcePanel; /** * target panel that has labels for each individual alignment unit in * the target parent of alignment unit */ private JPanel targetPanel; /** * list of available documentIDs - chosen one is selected as the * source document. */ private JComboBox sourceDocumentId; /** * list of available documentIDs - chosen one is selected as the * target document. */ private JComboBox targetDocumentId; /** * annotation set to used from the source document */ private JComboBox sourceASName; /** * annotation set to be used from the target document */ private JComboBox targetASName; /** * annotation type to be used as a unit to align in the source * document */ private JComboBox sourceUnitOfAlignment; /** * annotation type to be used as a unit to align in the target * document */ private JComboBox targetUnitOfAlignment; /** * annotation type to be used as parent of unit to align in the source * document */ private JComboBox sourceParentOfUnitOfAlignment; /** * annotation type to be used as parent of unit to align in the target * document */ private JComboBox targetParentOfUnitOfAlignment; /** * name of the feature used as a key in the document feature to hold * alignment mappings */ private JComboBox alignmentFeatureNames; /** * indicates if the links should be displayed */ private JToggleButton showLinks; /** * Buttons for different actions */ private JButton next, previous, loadActions, saveDocument; /** * Indicates if the alignment data should be populated */ private JToggleButton populate; /** * canvas used for drawing links between the alignment units */ private MappingsPanel linesCanvas; /** * The document, this alignment editor belongs to. */ private CompoundDocument document; /** * Alignment factory, that provides various methods to populate data * and iterate over alignment pairs. */ private AlignmentFactory alignFactory; /** * Alignment object, that is used for storing alignment informaiton */ private Alignment alignment; /** * mappings for annotations and their highlights */ private HashMap<Annotation, AnnotationHighlight> sourceHighlights; /** * mappings for annotations and their highlights */ private HashMap<Annotation, AnnotationHighlight> targetHighlights; /** * Remembers the selected annotations */ private List<Annotation> sourceLatestAnnotationsSelection; /** * Remembers the selected annotations */ private List<Annotation> targetLatestAnnotationsSelection; /** * a list of alignment actions available to the user */ private List<AlignmentAction> allActions; /** * A color that is being used for current highlighting */ private Color color; /** * used for generating random colors */ private ColorGenerator colorGenerator = new ColorGenerator(); /** * Default font-size */ public static final int TEXT_SIZE = 20; /** * mappings for menu item and associated alignment action */ private Map<JMenuItem, AlignmentAction> actions; /** * mappings for menu items and their captions */ private Map<String, JMenuItem> actionsMenuItemByCaption; /** * annotation highlight with the mouse on it */ private AnnotationHighlight currentAnnotationHightlight = null; /** * instance of the alignment editor with focus on it */ private AlignmentEditor thisInstance = null; /** * default align action - i.e. what happens when user clicks on the * align button */ private AlignAction alignAction = null; /** * mappings for alignment actions and its respective check box - which * if checked, indicates that the respective alignment action should * be executed. */ private HashMap<AlignmentAction, PropertyActionCB> actionsCBMap = null; /** * default unalign action - i.e. what happens when user clicks on the * unalign button */ private RemoveAlignmentAction removeAlignmentAction = null; /** * list of actions that should be executed before a pair is displayed * on the screen. */ private List<PreDisplayAction> preDisplayActions = null; /** * list of actions that should be executed after a user has indicated * that the alignment for the given pair is finished. */ private List<FinishedAlignmentAction> finishedAlignmentActions = null; private List<DataPublisherAction> dataPublisherActions = null; /* * (non-Javadoc) * * @see gate.Resource#init() */ public Resource init() throws ResourceInstantiationException { sourceHighlights = new HashMap<Annotation, AnnotationHighlight>(); targetHighlights = new HashMap<Annotation, AnnotationHighlight>(); actionsCBMap = new HashMap<AlignmentAction, PropertyActionCB>(); sourceLatestAnnotationsSelection = new ArrayList<Annotation>(); targetLatestAnnotationsSelection = new ArrayList<Annotation>(); actions = new HashMap<JMenuItem, AlignmentAction>(); actionsMenuItemByCaption = new HashMap<String, JMenuItem>(); allActions = new ArrayList<AlignmentAction>(); preDisplayActions = new ArrayList<PreDisplayAction>(); finishedAlignmentActions = new ArrayList<FinishedAlignmentAction>(); dataPublisherActions = new ArrayList<DataPublisherAction>(); ResourceData myResourceData = (ResourceData)Gate.getCreoleRegister().get( this.getClass().getName()); URL creoleXml = myResourceData.getXmlFileUrl(); URL alignmentHomeURL = null; File actionsConfFile = null; try { alignmentHomeURL = new URL(creoleXml, "."); // loading the default actions config file. actionsConfFile = new File(new File(new File(alignmentHomeURL.toURI()), "resources"), ACTIONS_CONFIG_FILE); } catch(MalformedURLException mue) { throw new GateRuntimeException(mue); } catch(URISyntaxException use) { throw new GateRuntimeException(use); } readAction(new ResetAction()); alignAction = new AlignAction(); readAction(alignAction); removeAlignmentAction = new RemoveAlignmentAction(); readAction(removeAlignmentAction); readActions(actionsConfFile); thisInstance = this; return this; } /** * Initialize the GUI */ private void initGui() { mainPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT); paramPanel = new JPanel(); paramPanel.setLayout(new BoxLayout(paramPanel, BoxLayout.Y_AXIS)); waPanel = new JPanel(new BorderLayout()); sourceDocumentId = new JComboBox(new DefaultComboBoxModel()); sourceDocumentId.setEditable(false); targetDocumentId = new JComboBox(new DefaultComboBoxModel()); targetDocumentId.setEditable(false); sourceDocumentId.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent ie) { populateAS((String)sourceDocumentId.getSelectedItem(), sourceASName); } }); targetDocumentId.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent ie) { populateAS((String)targetDocumentId.getSelectedItem(), targetASName); } }); sourceASName = new JComboBox(new DefaultComboBoxModel()); sourceASName.setPrototypeDisplayValue("AnnotationSetName"); sourceASName.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { populateParentOfUnitOfAlignment((String)sourceDocumentId .getSelectedItem(), sourceParentOfUnitOfAlignment); } }); targetASName = new JComboBox(new DefaultComboBoxModel()); targetASName.setPrototypeDisplayValue("AnnotationSetName"); targetASName.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { populateParentOfUnitOfAlignment((String)targetDocumentId .getSelectedItem(), targetParentOfUnitOfAlignment); } }); sourceParentOfUnitOfAlignment = new JComboBox(new DefaultComboBoxModel()); sourceParentOfUnitOfAlignment.setPrototypeDisplayValue("AnnotationSetName"); sourceParentOfUnitOfAlignment.setEditable(false); sourceParentOfUnitOfAlignment.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { populateUnitOfAlignment((String)sourceDocumentId.getSelectedItem(), sourceUnitOfAlignment); } }); targetParentOfUnitOfAlignment = new JComboBox(new DefaultComboBoxModel()); targetParentOfUnitOfAlignment.setPrototypeDisplayValue("AnnotationSetName"); targetParentOfUnitOfAlignment.setEditable(false); targetParentOfUnitOfAlignment.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { populateUnitOfAlignment((String)targetDocumentId.getSelectedItem(), targetUnitOfAlignment); } }); sourceUnitOfAlignment = new JComboBox(new DefaultComboBoxModel()); sourceUnitOfAlignment.setPrototypeDisplayValue("AnnotationSetName"); sourceUnitOfAlignment.setEditable(false); targetUnitOfAlignment = new JComboBox(new DefaultComboBoxModel()); targetUnitOfAlignment.setPrototypeDisplayValue("AnnotationSetName"); targetUnitOfAlignment.setEditable(false); alignmentFeatureNames = new JComboBox(new DefaultComboBoxModel()); ((DefaultComboBoxModel)alignmentFeatureNames.getModel()) .addElement(AlignmentFactory.ALIGNMENT_FEATURE_NAME); alignmentFeatureNames.setPrototypeDisplayValue("AnnotationSetName"); sourceDocPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); targetDocPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); iteratingPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); populateButtonsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); sourceDocPanel.add(new JLabel("sourceDoc:")); sourceDocPanel.add(sourceDocumentId); sourceDocPanel.add(new JLabel("annotationSet:")); sourceDocPanel.add(sourceASName); sourceDocPanel.add(new JLabel("parentOfAlignmentUnit:")); sourceDocPanel.add(sourceParentOfUnitOfAlignment); sourceDocPanel.add(new JLabel("unitOfAlignment:")); sourceDocPanel.add(sourceUnitOfAlignment); targetDocPanel.add(new JLabel("targetDoc:")); targetDocPanel.add(targetDocumentId); targetDocPanel.add(new JLabel("annotationSet:")); targetDocPanel.add(targetASName); targetDocPanel.add(new JLabel("parentOfAlignmentUnit:")); targetDocPanel.add(targetParentOfUnitOfAlignment); targetDocPanel.add(new JLabel("unitOfAlignment:")); targetDocPanel.add(targetUnitOfAlignment); iteratingPanel.add(new JLabel("iteratingMethodClassName:")); iteratingMethodTF = new JTextField( "gate.alignment.gui.DefaultIteratingMethod", 30); iteratingPanel.add(iteratingMethodTF); alignmentFeatureNames .setSelectedItem(AlignmentFactory.ALIGNMENT_FEATURE_NAME); alignmentFeatureNames.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { populateAlignmentFeatureNames(); } }); populate = new JToggleButton("Populate"); populate.addActionListener(this); previous = new JButton("< Previous"); previous.addActionListener(this); next = new JButton("Next >"); next.addActionListener(this); showLinks = new JToggleButton("Show Links"); showLinks.setSelected(true); showLinks.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { if(!showLinks.isSelected()) { sourcePanel.setLayout(new BoxLayout(sourcePanel, BoxLayout.Y_AXIS)); targetPanel.setLayout(new BoxLayout(targetPanel, BoxLayout.Y_AXIS)); waPanel.remove(sourcePanel); waPanel.remove(targetPanel); waPanel.setLayout(new GridLayout(1, 2)); waPanel.add(sourcePanel); waPanel.add(targetPanel); } else { sourcePanel.setLayout(new BoxLayout(sourcePanel, BoxLayout.X_AXIS)); targetPanel.setLayout(new BoxLayout(targetPanel, BoxLayout.X_AXIS)); waPanel.remove(sourcePanel); waPanel.remove(targetPanel); waPanel.setLayout(new BorderLayout()); waPanel.add(sourcePanel, BorderLayout.NORTH); waPanel.add(targetPanel, BorderLayout.SOUTH); } if(linesCanvas != null) { if(showLinks.isSelected()) { waPanel.add(linesCanvas, BorderLayout.CENTER); } else { waPanel.remove(linesCanvas); } waPanel.revalidate(); waPanel.updateUI(); } } }); saveDocument = new JButton(new SaveAsASingleXML()); loadActions = new JButton("Load Actions"); loadActions.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { try { JFileChooser fileChooser = Main.getMainFrame().getFileChooser(); int answer = fileChooser.showOpenDialog(MainFrame.getInstance()); if(answer == JFileChooser.APPROVE_OPTION) { File selectedFile = fileChooser.getSelectedFile(); if(selectedFile == null) { return; } else { readActions(selectedFile); } } } catch(GateException ge) { throw new GateRuntimeException(ge); } } }); iteratingPanel.add(new JLabel("alignmentFeatureName:")); iteratingPanel.add(alignmentFeatureNames); populateButtonsPanel.add(populate); populateButtonsPanel.add(previous); populateButtonsPanel.add(next); populateButtonsPanel.add(loadActions); populateButtonsPanel.add(showLinks); populateButtonsPanel.add(saveDocument); paramPanel.add(sourceDocPanel); paramPanel.add(targetDocPanel); paramPanel.add(iteratingPanel); paramPanel.add(populateButtonsPanel); paramPanel.setBorder(new TitledBorder("Settings")); mainPanel.add(new JScrollPane(paramPanel)/* , BorderLayout.NORTH */); sourcePanel = new JPanel(); sourcePanel.setLayout(new BoxLayout(sourcePanel, BoxLayout.X_AXIS)); sourcePanel.setBackground(Color.WHITE); targetPanel = new JPanel(); targetPanel.setLayout(new BoxLayout(targetPanel, BoxLayout.X_AXIS)); targetPanel.setBackground(Color.WHITE); linesCanvas = new MappingsPanel(); linesCanvas.setBackground(Color.WHITE); linesCanvas.setLayout(null); linesCanvas.setPreferredSize(new Dimension(200, 50)); linesCanvas.setOpaque(true); propertiesPanel = new JPanel(); propertiesPanel.setLayout(new BoxLayout(propertiesPanel, BoxLayout.Y_AXIS)); JScrollPane propertiesPane = new JScrollPane(propertiesPanel); propertiesPanel.add(new JLabel("Options")); propertiesPanel.add(Box.createGlue()); waPanel.add(sourcePanel, BorderLayout.NORTH); waPanel.add(targetPanel, BorderLayout.SOUTH); waPanel.add(linesCanvas, BorderLayout.CENTER); JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); JPanel waParentPanel = new JPanel(new BorderLayout()); waScrollPane = new JScrollPane(waPanel); waScrollPane.setPreferredSize(new Dimension(800, 200)); //JSplitPane verticalPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); waParentPanel.add(waScrollPane, BorderLayout.CENTER); splitPane.add(waParentPanel); //splitPane.add(verticalPane); splitPane.add(propertiesPane); mainPanel.add(splitPane/* , BorderLayout.CENTER */); // verticalPane.add(propertiesPane); // tableTabbedPane = new JTabbedPane(); // JScrollPane tableTabbedScroller = new JScrollPane(tableTabbedPane); // verticalPane.add(tableTabbedScroller); this.setLayout(new BorderLayout()); this.add(mainPanel, BorderLayout.CENTER); color = getColor(null); splitPane.setDividerLocation(0.8); splitPane.revalidate(); splitPane.updateUI(); // verticalPane.setDividerLocation(0.5); // verticalPane.revalidate(); // verticalPane.updateUI(); waPanel.setVisible(false); } /** * populates the annotation set combobox * * @param documentID * @param boxToPopulate */ private void populateAS(String documentID, JComboBox boxToPopulate) { Document doc = document.getDocument(documentID); Map<String, AnnotationSet> annotSets = doc.getNamedAnnotationSets(); if(annotSets == null) { annotSets = new HashMap<String, AnnotationSet>(); } HashSet<String> setNames = new HashSet<String>(annotSets.keySet()); setNames.add("<null>"); DefaultComboBoxModel dcbm = new DefaultComboBoxModel(setNames .toArray(new String[0])); boxToPopulate.setModel(dcbm); if(!setNames.isEmpty()) { boxToPopulate.setSelectedIndex(0); } } /** * populates the documentIds combobox * * @param documentID * @param boxToPopulate */ private void populateDocumentIds(JComboBox boxToPopulate, String[] documentIds) { if(documentIds == null) documentIds = new String[0]; DefaultComboBoxModel dcbm = new DefaultComboBoxModel(documentIds); boxToPopulate.setModel(dcbm); if(documentIds.length == 0) { boxToPopulate.setEnabled(false); } } /** * populates the documentIds combobox * * @param documentID * @param boxToPopulate */ private void populateAlignmentFeatureNames() { this.document .getAlignmentInformation(AlignmentFactory.ALIGNMENT_FEATURE_NAME); Set<String> alignmentFeatureNames = this.document .getAllAlignmentFeatureNames(); DefaultComboBoxModel dcbm = new DefaultComboBoxModel(alignmentFeatureNames .toArray(new String[0])); Object selectedItem = this.alignmentFeatureNames.getSelectedItem(); this.alignmentFeatureNames.setModel(dcbm); if(selectedItem != null) { this.alignmentFeatureNames.setSelectedItem(selectedItem); } selectedItem = this.alignmentFeatureNames.getSelectedItem(); alignment = this.document.getAlignmentInformation((String)selectedItem); if(alignment != null) { alignment.removeAlignmentListener(thisInstance); alignment.addAlignmentListener(thisInstance); refresh(); } } /** * populates the annotation set combobox * * @param documentID * @param boxToPopulate */ private void populateParentOfUnitOfAlignment(String documentID, JComboBox boxToPopulate) { Document doc = document.getDocument(documentID); String asName = null; if(boxToPopulate == sourceParentOfUnitOfAlignment) { asName = (String)sourceASName.getSelectedItem(); } else { asName = (String)targetASName.getSelectedItem(); } AnnotationSet srcAnnotSet = asName.equals("<null>") ? doc.getAnnotations() : doc.getAnnotations(asName); Set<String> annotTypes = srcAnnotSet.getAllTypes(); if(annotTypes == null) { annotTypes = new HashSet<String>(); } DefaultComboBoxModel dcbm = new DefaultComboBoxModel(annotTypes .toArray(new String[0])); boxToPopulate.setModel(dcbm); if(!annotTypes.isEmpty()) { if(dcbm.getIndexOf("Sentence") >= 0) { boxToPopulate.setSelectedIndex(dcbm.getIndexOf("Sentence")); } else { boxToPopulate.setSelectedIndex(0); } } } /** * populates the annotation set combobox * * @param documentID * @param boxToPopulate */ private void populateUnitOfAlignment(String documentID, JComboBox boxToPopulate) { Document doc = document.getDocument(documentID); String asName = null; if(boxToPopulate == sourceUnitOfAlignment) { asName = (String)sourceASName.getSelectedItem(); } else { asName = (String)targetASName.getSelectedItem(); } AnnotationSet srcAnnotSet = asName.equals("<null>") ? doc.getAnnotations() : doc.getAnnotations(asName); Set<String> annotTypes = srcAnnotSet.getAllTypes(); if(annotTypes == null) { annotTypes = new HashSet<String>(); } DefaultComboBoxModel dcbm = new DefaultComboBoxModel(annotTypes .toArray(new String[0])); boxToPopulate.setModel(dcbm); if(annotTypes.size() > 0) { if(dcbm.getIndexOf("Token") >= 0) { boxToPopulate.setSelectedIndex(dcbm.getIndexOf("Token")); } else { boxToPopulate.setSelectedIndex(0); } } } /* * (non-Javadoc) * * @see gate.VisualResource#setTarget(java.lang.Object) */ public void setTarget(Object target) { this.document = (CompoundDocument)target; thisInstance = this; List<String> documentIDs = new ArrayList<String>(this.document .getDocumentIDs()); initGui(); populateDocumentIds(sourceDocumentId, documentIDs.toArray(new String[0])); if(documentIDs.size() > 0) { sourceDocumentId.setSelectedIndex(0); } populateDocumentIds(targetDocumentId, documentIDs.toArray(new String[0])); if(documentIDs.size() > 1) { targetDocumentId.setSelectedIndex(1); } else if(documentIDs.size() > 0) { targetDocumentId.setSelectedIndex(0); } populateAlignmentFeatureNames(); } /** * This method clears up the latest annotation selection */ public void clearLatestAnnotationsSelection() { if(sourceLatestAnnotationsSelection != null && !sourceLatestAnnotationsSelection.isEmpty()) { for(Annotation annotation : sourceLatestAnnotationsSelection) { AnnotationHighlight ah = sourceHighlights.get(annotation); ah.setHighlighted(false, Color.WHITE); } sourceLatestAnnotationsSelection.clear(); } if(targetLatestAnnotationsSelection != null && !targetLatestAnnotationsSelection.isEmpty()) { for(Annotation annotation : targetLatestAnnotationsSelection) { AnnotationHighlight ah = targetHighlights.get(annotation); ah.setHighlighted(false, Color.WHITE); } targetLatestAnnotationsSelection.clear(); } } /** * Executes the given action. It uses the pair that is being currently * shown to collect the alignment information which is then used as * parameters to call the provided action. * * @param aa */ protected void executeAction(AlignmentAction aa) { // obtaining source and target documents Document srcDocument = document.getDocument(sourceDocumentId .getSelectedItem().toString()); Document tgtDocument = document.getDocument(targetDocumentId .getSelectedItem().toString()); // obtaining selected annotations Set<Annotation> srcSelectedAnnots = new HashSet<Annotation>( sourceLatestAnnotationsSelection); Set<Annotation> tgtSelectedAnnots = new HashSet<Annotation>( targetLatestAnnotationsSelection); if(currentAnnotationHightlight != null) { Set<Annotation> alignedAnnots = alignment .getAlignedAnnotations(currentAnnotationHightlight.annotation); if(alignedAnnots == null) alignedAnnots = new HashSet<Annotation>(); alignedAnnots.add(currentAnnotationHightlight.annotation); for(Annotation annot : alignedAnnots) { Document tempDoc = alignment.getDocument(annot); if(tempDoc == srcDocument) { srcSelectedAnnots.add(annot); } else if(tempDoc == tgtDocument) { tgtSelectedAnnots.add(annot); } } } try { color = Color.WHITE; aa.execute(this, this.document, srcDocument, getSourceAnnotationSetName(), srcSelectedAnnots, tgtDocument, getTargetAnnotationSetName(), tgtSelectedAnnots, currentAnnotationHightlight.annotation); if(aa == alignAction) { for(AlignmentAction a : allActions) { if(a.invokeWithAlignAction()) { JCheckBox cb = actionsCBMap.get(a); if((cb != null && cb.isSelected()) || cb == null) a .execute(this, this.document, srcDocument, getSourceAnnotationSetName(), srcSelectedAnnots, tgtDocument, getTargetAnnotationSetName(), tgtSelectedAnnots, currentAnnotationHightlight.annotation); } } } else if(aa == removeAlignmentAction) { for(AlignmentAction a : allActions) { if(a.invokeWithRemoveAction()) { JCheckBox cb = actionsCBMap.get(a); if((cb != null && cb.isSelected()) || cb == null) a .execute(this, this.document, srcDocument, getSourceAnnotationSetName(), srcSelectedAnnots, tgtDocument, getTargetAnnotationSetName(), tgtSelectedAnnots, currentAnnotationHightlight.annotation); } } } } catch(AlignmentException ae) { throw new GateRuntimeException(ae); } } /** * Get the alignment feature name * * @return */ public String getAlignmentFeatureName() { return this.alignmentFeatureNames.getSelectedItem().toString(); } /** * Using user selections, this method obtains pairs and shows the * first one in the GUI */ public void populate() { if(!populate.isSelected()) { if(!disableUserSelections) { paramPanel.remove(populateButtonsPanel); paramPanel.add(sourceDocPanel); paramPanel.add(targetDocPanel); paramPanel.add(iteratingPanel); paramPanel.add(populateButtonsPanel); paramPanel.revalidate(); next.setEnabled(false); previous.setEnabled(false); showLinks.setEnabled(false); waPanel.setVisible(false); } } else { if(!disableUserSelections) { paramPanel.remove(sourceDocPanel); paramPanel.remove(targetDocPanel); paramPanel.remove(iteratingPanel); paramPanel.revalidate(); next.setEnabled(true); previous.setEnabled(true); showLinks.setEnabled(true); waPanel.setVisible(true); } try { if(sourceUnitOfAlignment.getSelectedItem() == null) return; if(targetUnitOfAlignment.getSelectedItem() == null) return; if(sourceParentOfUnitOfAlignment.getSelectedItem() == null) return; if(targetParentOfUnitOfAlignment.getSelectedItem() == null) return; AlignmentFactory af = new AlignmentFactory(document, sourceDocumentId .getSelectedItem().toString(), targetDocumentId .getSelectedItem().toString(), sourceASName.getSelectedItem() .toString(), targetASName.getSelectedItem().toString(), sourceUnitOfAlignment.getSelectedItem().toString(), targetUnitOfAlignment.getSelectedItem().toString(), sourceParentOfUnitOfAlignment.getSelectedItem().toString(), targetParentOfUnitOfAlignment.getSelectedItem().toString(), iteratingMethodTF.getText().trim()); sourcePanel.setBorder(BorderFactory.createTitledBorder(sourceDocumentId .getSelectedItem().toString())); targetPanel.setBorder(BorderFactory.createTitledBorder(targetDocumentId .getSelectedItem().toString())); // if there were no errors alignFactory = af; nextAction(); } catch(Exception e) { e.printStackTrace(); } } } /** * handles vairous actions, such as populate, next, previous etc. */ public void actionPerformed(ActionEvent ae) { if(ae.getSource() == populate) { populate(); } else if(ae.getSource() == next) { if(alignFactory != null) { int answer = JOptionPane.showConfirmDialog(mainPanel, "Is alignment complete for this pair?"); if(answer == JOptionPane.YES_OPTION) { callFinishedAlignmentActions(); } else if(answer != JOptionPane.NO_OPTION) { return; } } nextAction(); } else if(ae.getSource() == previous) { if(alignFactory != null) { int answer = JOptionPane.showConfirmDialog(mainPanel, "Is alignment complete for this pair?"); if(answer == JOptionPane.YES_OPTION) { callFinishedAlignmentActions(); } else if(answer != JOptionPane.NO_OPTION) { return; } } previousAction(); } } /** * if user says that the pair is completely aligned, this method is * invoked, which retrieves a list of FinishedAlignmentActions and * calls them one by one. */ private void callFinishedAlignmentActions() { Pair pair = alignFactory.current(); Set<Annotation> srcAnnotations = null; Set<Annotation> tgtAnnotations = null; Document srcDocument = null; Document tgtDocument = null; tgtDocument = document.getDocument(pair.getTargetDocumentId()); srcDocument = document.getDocument(pair.getSourceDocumentId()); srcAnnotations = alignFactory.getUnderlyingAnnotations(pair .getSrcAnnotation(), pair.getSourceDocumentId(), sourceUnitOfAlignment.getSelectedItem().toString()); tgtAnnotations = alignFactory.getUnderlyingAnnotations(pair .getTgtAnnotation(), pair.getTargetDocumentId(), targetUnitOfAlignment.getSelectedItem().toString()); for(FinishedAlignmentAction faa : finishedAlignmentActions) { try { faa.execute(this, document, srcDocument, (String)sourceASName .getSelectedItem(), srcAnnotations, tgtDocument, (String)targetASName.getSelectedItem(), tgtAnnotations); } catch(AlignmentException ae) { throw new GateRuntimeException(ae); } } } /** * obtains the next available pair to show it in the editor */ private void nextAction() { if(alignFactory != null && alignFactory.hasNext()) { Pair next = alignFactory.next(); Document srcDocument = document.getDocument(next.getSourceDocumentId()); Document tgtDocument = document.getDocument(next.getTargetDocumentId()); // before showing, lets execute preDisplayActions for(PreDisplayAction pda : preDisplayActions) { try { pda.execute(this, document, srcDocument, getSourceAnnotationSetName(), next.getSrcAnnotation(), tgtDocument, getTargetAnnotationSetName(), next .getTgtAnnotation()); } catch(AlignmentException ae) { ae.printStackTrace(); } } updateGUI(next); } else { JOptionPane.showMessageDialog(mainPanel, "Reached End of the Document"); } } /** * simply refreshes the gui */ private void refresh() { if(alignFactory != null && alignFactory.current() != null) { updateGUI(alignFactory.current()); } } /** * This method updates the GUI. * * @param docIDsAndAnnots */ private void updateGUI(Pair pair) { // before refreshing, we remove all the highlights clearLatestAnnotationsSelection(); sourcePanel.removeAll(); sourcePanel.updateUI(); targetPanel.removeAll(); targetPanel.updateUI(); linesCanvas.removeAllEdges(); linesCanvas.repaint(); HashMap<String, Annotation> docIDsAndAnnots = new HashMap<String, Annotation>(); docIDsAndAnnots.put(pair.getSourceDocumentId(), pair.getSrcAnnotation()); docIDsAndAnnots.put(pair.getTargetDocumentId(), pair.getTgtAnnotation()); Annotation srcSentence = null; Annotation tgtSentence = null; String srcDocID = null; String tgtDocID = null; for(String docId : docIDsAndAnnots.keySet()) { JPanel panelToUse = sourcePanel; boolean isSourceDocument = true; if(docId.equals(targetDocumentId.getSelectedItem().toString())) { panelToUse = targetPanel; isSourceDocument = false; } // sentence annotation Annotation annot = docIDsAndAnnots.get(docId); if(isSourceDocument) { srcSentence = annot; srcDocID = docId; } else { tgtSentence = annot; tgtDocID = docId; } // we need to highlight the unit type AnnotationSet underlyingUnitAnnotationsSet = alignFactory .getUnderlyingAnnotations(annot, docId, isSourceDocument ? sourceUnitOfAlignment.getSelectedItem().toString() : targetUnitOfAlignment.getSelectedItem().toString()); // if there are not underlying annotations, just return if(underlyingUnitAnnotationsSet == null) { return; } ArrayList<Annotation> units = new ArrayList<Annotation>( underlyingUnitAnnotationsSet); Collections.sort(units, new gate.util.OffsetComparator()); // for each underlying unit of alignment, we create a default // annotation highlight. HashMap<Annotation, AnnotationHighlight> annotationHighlightsMap = new HashMap<Annotation, AnnotationHighlight>(); for(Annotation underlyingUnitAnnotation : units) { String text = alignFactory.getText(underlyingUnitAnnotation, docId); AnnotationHighlight ah = new AnnotationHighlight(text, Color.WHITE, underlyingUnitAnnotation, isSourceDocument); annotationHighlightsMap.put(underlyingUnitAnnotation, ah); panelToUse.add(ah); panelToUse.add(Box.createRigidArea(new Dimension(5, 0))); } if(isSourceDocument) { this.sourceHighlights = annotationHighlightsMap; } else { this.targetHighlights = annotationHighlightsMap; } panelToUse.revalidate(); panelToUse.updateUI(); } // now we need to highlight the aligned annotations if there are any Set<Annotation> setOfAlignedAnnotations = alignment.getAlignedAnnotations(); // we keep record of which annotations are already highlighted in // order to not highlight them again Set<Annotation> highlightedAnnotations = new HashSet<Annotation>(); // one annotation at a time for(Annotation srcAnnotation : setOfAlignedAnnotations) { // if already highlighted, don't do it again if(highlightedAnnotations.contains(srcAnnotation)) continue; // if the annotation doesn't belong to one of the source // or target annotations, just skip it if(!sourceHighlights.containsKey(srcAnnotation) && !targetHighlights.containsKey(srcAnnotation)) { continue; } // find out the language/id of the document String docId = alignment.getDocument(srcAnnotation).getName(); JPanel pane = null; boolean isSrcDocument = false; if(docId.equals(sourceDocumentId.getSelectedItem().toString())) { pane = sourcePanel; isSrcDocument = true; } else if(docId.equals(sourceDocumentId.getSelectedItem().toString())) { pane = targetPanel; isSrcDocument = false; } if(pane == null) continue; Set<Annotation> sourceAnnots = new HashSet<Annotation>(); Set<Annotation> targetAnnots = new HashSet<Annotation>(); if(isSrcDocument) { targetAnnots = alignment.getAlignedAnnotations(srcAnnotation); for(Annotation tgtAnnot : targetAnnots) { Set<Annotation> setOfAnnots = alignment .getAlignedAnnotations(tgtAnnot); for(Annotation sAnnot : setOfAnnots) { Set<Annotation> setOfTargetAnnots = alignment .getAlignedAnnotations(sAnnot); if(setOfTargetAnnots.size() == targetAnnots.size()) { if(setOfTargetAnnots.containsAll(targetAnnots)) { sourceAnnots.add(sAnnot); } } } } } else { sourceAnnots = alignment.getAlignedAnnotations(srcAnnotation); for(Annotation srcAnnot : sourceAnnots) { Set<Annotation> setOfAnnots = alignment .getAlignedAnnotations(srcAnnot); for(Annotation tAnnot : setOfAnnots) { Set<Annotation> setOfSourceAnnots = alignment .getAlignedAnnotations(tAnnot); if(setOfSourceAnnots.size() == sourceAnnots.size()) { if(setOfSourceAnnots.containsAll(sourceAnnots)) { targetAnnots.add(tAnnot); } } } } } Color newColor = getColor(null); boolean firstTime = true; Set<Annotation> toRemove = new HashSet<Annotation>(); for(Annotation tgtAnnot : targetAnnots) { AnnotationHighlight ah = targetHighlights.get(tgtAnnot); if(ah == null) { toRemove.add(tgtAnnot); } } targetAnnots.removeAll(toRemove); for(Annotation srcAnnot : sourceAnnots) { AnnotationHighlight sAh = sourceHighlights.get(srcAnnot); sAh.setHighlighted(true, newColor); for(Annotation tgtAnnot : targetAnnots) { AnnotationHighlight ah = targetHighlights.get(tgtAnnot); if(firstTime) { ah.setHighlighted(true, newColor); } Edge edge = new Edge(); edge.srcAH = sAh; edge.tgtAH = ah; linesCanvas.addEdge(edge); linesCanvas.repaint(); } firstTime = false; } } } /** * does the cleaning up job to free up memory occupied by this editor */ public void cleanup() { for(AlignmentAction a : allActions) { a.cleanup(); } for(PreDisplayAction pda : preDisplayActions) { pda.cleanup(); } for(FinishedAlignmentAction faa : finishedAlignmentActions) { faa.cleanup(); } for(DataPublisherAction dpa : dataPublisherActions) { dpa.cleanup(); } } /** * obtains the pair previous to the current one and shows it into the * alignment editor. */ private void previousAction() { if(alignFactory != null && alignFactory.hasPrevious()) { updateGUI(alignFactory.previous()); } else { JOptionPane.showMessageDialog(mainPanel, "Reached Start of the Document"); } } /** * indicates end of the process */ public void processFinished() { this.document.setCurrentDocument("null"); } public void progressChanged(int prgress) { } /** * Internal class - it represents an alignment unit. * * @author niraj * */ protected class AnnotationHighlight extends JLabel { /** * indicates if the annotation is highlighted or not */ boolean highlighted = false; /** * if the current highlight belongs to the source document */ boolean sourceDocument = false; /** * color of the highlight */ Color colorToUse = Color.WHITE; /** * annotation it refers to */ Annotation annotation; /** * constructor * * @param text - the underlying text of the annotation * @param color - color of the highlight * @param annot - annotation the current highlight refers to * @param sourceDocument - if the current annotation belongs to the * source document */ public AnnotationHighlight(String text, Color color, Annotation annot, boolean sourceDocument) { super(text); this.setOpaque(true); this.annotation = annot; this.sourceDocument = sourceDocument; this.colorToUse = color; setBackground(this.colorToUse); this.addMouseListener(new MouseActionListener()); setFont(new Font(getFont().getName(), Font.PLAIN, TEXT_SIZE)); } /** * sets the annotation highlighted/dehighlighted * * @param val * @param color */ public void setHighlighted(boolean val, Color color) { this.highlighted = val; this.colorToUse = color; this.setBackground(color); this.updateUI(); } public boolean isHighlighted() { return this.highlighted; } public void setHighlightColor(Color color) { this.colorToUse = color; this.setBackground(color); this.updateUI(); } public Color getHighlightColor() { return this.colorToUse; } /** * Implements various mouse events. E.g. what should happen when * someone clicks on an unhighlighted annotation etc. * * @author niraj * */ protected class MouseActionListener extends MouseInputAdapter { public void mouseClicked(MouseEvent me) { mouseExited(me); AnnotationHighlight ah = (AnnotationHighlight)me.getSource(); Point pt = me.getPoint(); currentAnnotationHightlight = ah; if(SwingUtilities.isRightMouseButton(me)) { if(alignment.isAnnotationAligned(ah.annotation)) { // lets clear the latest selection clearLatestAnnotationsSelection(); } // we should show the option menu here JPopupMenu optionsMenu = new JPopupMenu(); optionsMenu.setOpaque(true); optionsMenu.add(new JLabel("Options")); optionsMenu.addSeparator(); for(JMenuItem item : actions.keySet()) { AlignmentAction aa = actions.get(item); if(alignment.isAnnotationAligned(ah.annotation)) { if(aa.invokeForAlignedAnnotation()) { optionsMenu.add(item); } } else if(ah.highlighted) { if(aa.invokeForHighlightedUnalignedAnnotation()) { optionsMenu.add(item); } } else { if(aa.invokeForUnhighlightedUnalignedAnnotation()) { optionsMenu.add(item); } } } optionsMenu.show(ah, (int)pt.getX(), (int)pt.getY()); optionsMenu.setVisible(true); return; } // was this annotation highlighted? // if yes, remove the highlight if(ah.highlighted) { // we need to check if the ah is aligned // if so, we should prompt user to first reset the // alignment if(alignment.isAnnotationAligned(ah.annotation)) { JOptionPane.showMessageDialog(gate.gui.MainFrame.getInstance(), "To remove this annotation from the current" + " aligment, please use the 'Remove Alignment'" + " from the options menu on right click"); return; } // the annotation is not aligned but recently highlighted // so remove the highlight ah.setHighlighted(false, Color.WHITE); if(ah.isSourceDocument()) { if(sourceLatestAnnotationsSelection == null) { sourceLatestAnnotationsSelection = new ArrayList<Annotation>(); } sourceLatestAnnotationsSelection.remove(ah.annotation); } else { if(targetLatestAnnotationsSelection == null) { targetLatestAnnotationsSelection = new ArrayList<Annotation>(); } targetLatestAnnotationsSelection.remove(ah.annotation); } } else { if(color == Color.WHITE) color = getColor(null); ah.setHighlighted(true, color); if(ah.isSourceDocument()) { if(sourceLatestAnnotationsSelection == null) { sourceLatestAnnotationsSelection = new ArrayList<Annotation>(); } if(!sourceLatestAnnotationsSelection.contains(ah.annotation)) sourceLatestAnnotationsSelection.add(ah.annotation); } else { if(targetLatestAnnotationsSelection == null) { targetLatestAnnotationsSelection = new ArrayList<Annotation>(); } if(!targetLatestAnnotationsSelection.contains(ah.annotation)) targetLatestAnnotationsSelection.add(ah.annotation); } } } JPopupMenu menu = new JPopupMenu(); FeaturesModel model = new FeaturesModel(); JTable featuresTable = new JTable(model); Timer timer = new Timer(); TimerTask task; public void mouseEntered(final MouseEvent me) { final AnnotationHighlight ah = (AnnotationHighlight)me.getSource(); model.setAnnotation(ah.annotation); task = new TimerTask() { public void run() { menu.add(featuresTable); menu.show(ah, me.getX(), me.getY() + 10); menu.revalidate(); menu.updateUI(); } }; timer.schedule(task, 2000); } public void mouseExited(MouseEvent me) { if(task != null) { task.cancel(); } if(menu != null && menu.isVisible()) { menu.setVisible(false); } } } public boolean isSourceDocument() { return sourceDocument; } } /** * Introduces transparency to the given color. If c is null, a new * random color is generated using the color generater class. * * @param c * @return */ private Color getColor(Color c) { float components[] = null; if(c == null) components = colorGenerator.getNextColor().getComponents(null); else components = c.getComponents(null); Color colour = new Color(components[0], components[1], components[2], 0.5f); int rgb = colour.getRGB(); int alpha = colour.getAlpha(); int rgba = rgb | (alpha << 24); colour = new Color(rgba, true); return colour; } /** * listens to the annotationsAligned event and updates the GUI * accordingly. */ public void annotationsAligned(Annotation srcAnnotation, String srcAS, Document srcDocument, Annotation tgtAnnotation, String tgtAS, Document tgtDocument) { if(srcAnnotation == null || tgtAnnotation == null || srcDocument == null || tgtDocument == null) { System.err.println("One of the src/tgt annotation/document is null"); return; } if(!srcDocument.getName().equals(getSourceDocumentId())) { return; } if(!tgtDocument.getName().equals(getTargetDocumentId())) { return; } AnnotationHighlight srcAH = sourceHighlights.get(srcAnnotation); AnnotationHighlight tgtAH = targetHighlights.get(tgtAnnotation); if(srcAH == null || tgtAH == null) return; // if one of the two is already aligned Color toUse = null; if(srcAH.highlighted) toUse = srcAH.colorToUse; else if(tgtAH.highlighted) toUse = tgtAH.colorToUse; else toUse = getColor(null); if(!srcAH.highlighted) { srcAH.setHighlighted(true, toUse); } if(!tgtAH.highlighted) { tgtAH.setHighlighted(true, toUse); } refresh(); } /** * listens to the annotationsUnAligned event and updates the GUI * accordingly. */ public void annotationsUnaligned(Annotation srcAnnotation, String srcAS, Document srcDocument, Annotation tgtAnnotation, String tgtAS, Document tgtDocument) { if(srcAnnotation == null || tgtAnnotation == null || srcDocument == null || tgtDocument == null) { System.err.println("One of the src/tgt annotation/document is null"); return; } if(!srcDocument.getName().equals( sourceDocumentId.getSelectedItem().toString())) return; if(!tgtDocument.getName().equals( targetDocumentId.getSelectedItem().toString())) return; AnnotationHighlight srcAH = sourceHighlights.get(srcAnnotation); AnnotationHighlight tgtAH = targetHighlights.get(tgtAnnotation); if(srcAH == null || tgtAH == null) return; if(srcAH.highlighted) { srcAH.setHighlighted(false, Color.WHITE); } if(tgtAH.highlighted) { tgtAH.setHighlighted(false, Color.WHITE); } refresh(); } /** * This method reads the given action and decides whether it should be * added to the properties panel or not. It also adds it to the * appropriate local data structure in order to invoke them when * appropriate. * * @param action */ private void readAction(AlignmentAction action) { // indicates if this action should be added to the menu boolean addToMenu = true; if(action.invokeWithAlignAction()) { allActions.add(action); addToMenu = false; } if(action.invokeWithRemoveAction()) { if(!allActions.contains(action)) { allActions.add(action); } addToMenu = false; } String caption = action.getCaption(); Icon icon = action.getIcon(); if(addToMenu) { final JMenuItem menuItem; if(icon != null) { menuItem = new JMenuItem(caption, icon); JMenuItem actionItem = actionsMenuItemByCaption.get(action .getIconPath()); if(actionItem != null) { actions.remove(actionItem); actionsMenuItemByCaption.remove(action.getIconPath()); } actionsMenuItemByCaption.put(action.getIconPath(), menuItem); } else { menuItem = new JMenuItem(caption); JMenuItem actionItem = actionsMenuItemByCaption.get(caption); if(actionItem != null) { actions.remove(actionItem); actionsMenuItemByCaption.remove(caption); } actionsMenuItemByCaption.put(caption, menuItem); } if(menuItem != null) { menuItem.setToolTipText(action.getToolTip()); actions.put(menuItem, action); menuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { executeAction(actions.get(menuItem)); } }); } } } /** * Reads different actions from the actions configuration file. * * @param actionsConfFile */ private void readActions(File actionsConfFile) { if(actionsConfFile != null && actionsConfFile.exists()) { try { BufferedReader br = new BufferedReader(new FileReader(actionsConfFile)); String line = br.readLine(); String cName = ""; while(line != null) { // each line will have a class name try { if(line.trim().startsWith("#") || line.trim().length() == 0) { line = br.readLine(); continue; } int index = line.indexOf(","); cName = index < 0 ? line.trim() : line.substring(0, index); line = index < 0 ? "" : line.substring(index + 1); Class actionClass = Class.forName(cName, true, Gate .getClassLoader()); Object action = actionClass.newInstance(); String[] args = line.split("[,]"); if(action instanceof AlignmentAction) { loadAlignmentAction((AlignmentAction)action, args); } if(action instanceof PreDisplayAction) { loadPreDisplayAction((PreDisplayAction)action, args); } if(action instanceof FinishedAlignmentAction) { loadFinishedAlignmentAction((FinishedAlignmentAction)action, args); } if(action instanceof DataPublisherAction) { loadDataPublisherAction((DataPublisherAction)action, args); } } catch(ClassNotFoundException cnfe) { System.err.println("class " + cName + " not found!"); continue; } catch(IllegalAccessException ilae) { System.err.println("class " + cName + " threw the illegal access exception!"); continue; } catch(InstantiationException ie) { System.err.println("class " + cName + " could not be instantiated"); continue; } finally { line = br.readLine(); } } } catch(IOException ioe) { throw new GateRuntimeException(ioe); } } } private void loadAlignmentAction(AlignmentAction aa, String[] args) { try { aa.init(args); } catch(AlignmentActionInitializationException aaie) { throw new GateRuntimeException(aaie); } readAction(aa); if(aa.invokeWithAlignAction() || aa.invokeWithRemoveAction()) { String title = aa.getCaption(); if(title == null || title.trim().length() == 0) return; PropertyActionCB pab = new PropertyActionCB(title, false, aa); pab.setToolTipText(aa.getToolTip()); actionsCBMap.put(aa, pab); int count = propertiesPanel.getComponentCount(); propertiesPanel.add(pab, count - 1); propertiesPanel.validate(); propertiesPanel.updateUI(); } } /** * load a finished alignment action * * @param faa * @param args */ private void loadFinishedAlignmentAction(FinishedAlignmentAction faa, String[] args) { try { faa.init(args); finishedAlignmentActions.add(faa); } catch(AlignmentActionInitializationException aaie) { throw new GateRuntimeException(aaie); } } /** * load a data publishers action * * @param faa * @param args */ private void loadDataPublisherAction(final DataPublisherAction dpa, String[] args) { try { dpa.init(args); dataPublisherActions.add(dpa); SwingUtilities.invokeLater(new Runnable() { public void run() { DefaultDataModel ddm = new DefaultDataModel(dpa); tableTabbedPane.add(dpa.getTableTitle(), new XJTable( ddm)); dpa.setDataModel(ddm); } }); } catch(AlignmentActionInitializationException aaie) { throw new GateRuntimeException(aaie); } } /** * loads a pre-display action. * * @param pda * @param args */ private void loadPreDisplayAction(PreDisplayAction pda, String[] args) { try { pda.init(args); preDisplayActions.add(pda); } catch(AlignmentActionInitializationException aaie) { throw new GateRuntimeException(aaie); } } /** * internal class to represent link between the source and the target * alignment unit. * * @author gate * */ private class Edge { AnnotationHighlight srcAH; AnnotationHighlight tgtAH; } /** * If selected, the appropriate AlignmentAction is obtained from the * local data-structure and invoked. * * @author gate * */ private class PropertyActionCB extends JCheckBox { /** * Which action to call if the check box is selected */ AlignmentAction aa; /** * GUI component, that allows selecting, deselecting the action */ JCheckBox thisInstance; /** * caption */ String key; /** * Constructor * * @param propKey - caption * @param value - selected or deselected * @param action - to be called if selected */ public PropertyActionCB(String propKey, boolean value, AlignmentAction action) { super(propKey); setSelected(value); this.aa = action; thisInstance = this; key = propKey; } } /** * canvas that shows lines for every link present in the current pair * * @author gate * */ private class MappingsPanel extends JPanel { /** * edges to paint */ private Set<Edge> edges = new HashSet<Edge>(); /** * constructor */ public MappingsPanel() { // do nothing setOpaque(true); setBackground(Color.WHITE); } /** * clears the local cache */ public void removeAllEdges() { edges.clear(); } /** * adds a new edge to the panel * * @param edge */ public void addEdge(Edge edge) { if(edge != null) edges.add(edge); } /** * draws edges */ public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D)g; g2d.setBackground(Color.WHITE); g2d.clearRect(0, 0, this.getWidth(), this.getHeight()); // but only if showLinks is selected if(showLinks.isSelected()) { for(Edge e : edges) { int x = (int)(e.srcAH.getBounds().x + (double)((double)e.srcAH .getBounds().width / 2)); int y = 0; int x1 = (int)(e.tgtAH.getBounds().x + (double)((double)e.tgtAH .getBounds().width / 2)); int y1 = this.getBounds().height; Line2D line = new Line2D.Double(new Point((int)x, (int)y), new Point( (int)x1, (int)y1)); Stroke stroke = new BasicStroke(2.0f); g2d.setStroke(stroke); Color c = g2d.getColor(); g2d.setColor(e.srcAH.getBackground()); g2d.draw(line); g2d.setColor(c); } } } } /** * represents annotation features. This is used for displaying * features of the annotation currently being focused by the mouse * pointer. * * @author gate * */ public class FeaturesModel extends DefaultTableModel { // annotation whoes features need to be displayed Annotation toShow; /** * keys */ ArrayList<String> features; /** * values */ ArrayList<String> values; /** * constructor */ public FeaturesModel() { super(new String[] {"Feature", "Value"}, 0); } /** * sets the annotation whoes features need to be shown * * @param annot */ public void setAnnotation(Annotation annot) { features = new ArrayList<String>(); values = new ArrayList<String>(); for(Object key : annot.getFeatures().keySet()) { features.add(key.toString()); values.add(annot.getFeatures().get(key).toString()); } super.fireTableDataChanged(); } public Class getColumnClass(int column) { return String.class; } public int getRowCount() { return values == null ? 0 : values.size(); } public int getColumnCount() { return 2; } public String getColumnName(int column) { switch(column) { case 0: return "Feature"; default: return "Value"; } } public Object getValueAt(int row, int column) { switch(column) { case 0: return features.get(row); default: return values.get(row); } } } /** * sets the alignment feature name that should be used to store * alignment information * * @param alignmentFeatureName */ public void setAlignmentFeatureName(String alignmentFeatureName) { document.getAlignmentInformation(alignmentFeatureName); alignmentFeatureNames.setSelectedItem(alignmentFeatureName); if(!alignmentFeatureNames.getSelectedItem().equals(alignmentFeatureName)) { alignmentFeatureNames.setEditable(true); alignmentFeatureNames.addItem(alignmentFeatureNames); alignmentFeatureNames.setSelectedItem(alignmentFeatureName); alignmentFeatureNames.setEditable(false); } } // setter methods public void setSourceDocumentId(String docId) { sourceDocumentId.setSelectedItem(docId); } public void setTargetDocumentId(String docId) { targetDocumentId.setSelectedItem(docId); } public void setSourceAnnotationSetName(String annotSet) { if(annotSet == null) { sourceASName.setSelectedItem("<null>"); } else { sourceASName.setSelectedItem(annotSet); } } public void setTargetAnnotationSetName(String annotSet) { if(annotSet == null) { targetASName.setSelectedItem("<null>"); } else { targetASName.setSelectedItem(annotSet); } } public void setSourceUnitOfAlignment(String unit) { sourceUnitOfAlignment.setSelectedItem(unit); } public void setTargetUnitOfAlignment(String unit) { targetUnitOfAlignment.setSelectedItem(unit); } public void setSourceParentOfUnitOfAlignment(String unit) { sourceParentOfUnitOfAlignment.setSelectedItem(unit); } public void setTargetParentOfUnitOfAlignment(String unit) { targetParentOfUnitOfAlignment.setSelectedItem(unit); } public void disableUserSelections(boolean disableUserSelections) { this.disableUserSelections = disableUserSelections; if(!this.disableUserSelections) { populate.setEnabled(false); loadActions.setEnabled(false); saveDocument.setEnabled(false); sourceUnitOfAlignment.setEnabled(false); targetUnitOfAlignment.setEnabled(false); sourceParentOfUnitOfAlignment.setEnabled(false); targetParentOfUnitOfAlignment.setEnabled(false); sourceASName.setEnabled(false); targetASName.setEnabled(false); sourceDocumentId.setEnabled(false); targetDocumentId.setEnabled(false); alignmentFeatureNames.setEnabled(false); } else { populate.setEnabled(true); loadActions.setEnabled(true); saveDocument.setEnabled(true); alignmentFeatureNames.setEnabled(true); populate(); } } boolean disableUserSelections = false; /** * Saves the compound document in a single XML document. * * @author gate * */ public class SaveAsASingleXML extends AbstractAction { private static final long serialVersionUID = -1377052643002026640L; public SaveAsASingleXML() { super("Save"); } public void actionPerformed(ActionEvent ae) { CompoundDocument cd = (CompoundDocument)document; JFileChooser fileChooser = MainFrame.getFileChooser(); fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); try { fileChooser.showSaveDialog(Main.getMainFrame()); File fileToSaveIn = null; if((fileToSaveIn = fileChooser.getSelectedFile()) == null) { return; } String xml = AbstractCompoundDocument.toXmlAsASingleDocument(cd); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(fileToSaveIn), cd.getEncoding())); bw.write(xml); bw.flush(); bw.close(); } catch(Exception e) { e.printStackTrace(); } } } // getter methods public String getSourceParentOfUnitOfAlignment() { return sourceParentOfUnitOfAlignment.getSelectedItem().toString(); } public String getTargetParentOfUnitOfAlignment() { return targetParentOfUnitOfAlignment.getSelectedItem().toString(); } public String getSourceUnitOfAlignment() { return sourceUnitOfAlignment.getSelectedItem().toString(); } public String getTargetUnitOfAlignment() { return targetUnitOfAlignment.getSelectedItem().toString(); } public String getSourceDocumentId() { return sourceDocumentId.getSelectedItem().toString(); } public String getTargetDocumentId() { return targetDocumentId.getSelectedItem().toString(); } public String getSourceAnnotationSetName() { String as = sourceASName.getSelectedItem().toString(); return as.equals("<null>") ? null : as; } public String getTargetAnnotationSetName() { String as = targetASName.getSelectedItem().toString(); return as.equals("<null>") ? null : as; } }