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;
}
}