use of gate.Document in project gate-core by GateNLP.
the class LuceneDataStoreSearchGUI method initGui.
/**
* Initialize the GUI.
*/
protected void initGui() {
// see the global layout schema at the end
setLayout(new BorderLayout());
stringCollator = java.text.Collator.getInstance();
stringCollator.setStrength(java.text.Collator.TERTIARY);
Comparator<String> lastWordComparator = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
if (o1 == null || o2 == null) {
return 0;
}
return stringCollator.compare(o1.substring(o1.trim().lastIndexOf(' ') + 1), o2.substring(o2.trim().lastIndexOf(' ') + 1));
}
};
integerComparator = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
if (o1 == null || o2 == null) {
return 0;
}
return o1.compareTo(o2);
}
};
/**
********************************
* Stack view configuration frame *
*********************************
*/
configureStackViewFrame = new ConfigureStackViewFrame("Stack view configuration");
configureStackViewFrame.setIconImage(((ImageIcon) MainFrame.getIcon("WindowNew")).getImage());
configureStackViewFrame.setLocationRelativeTo(LuceneDataStoreSearchGUI.this);
configureStackViewFrame.getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("ESCAPE"), "close row manager");
configureStackViewFrame.getRootPane().getActionMap().put("close row manager", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
configureStackViewFrame.setVisible(false);
}
});
configureStackViewFrame.validate();
configureStackViewFrame.setSize(200, 300);
configureStackViewFrame.pack();
// called when Gate is exited, in case the user doesn't close the
// datastore
MainFrame.getInstance().addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
// no parent so need to be disposed explicitly
configureStackViewFrame.dispose();
}
});
/**
***********
* Top panel *
************
*/
JPanel topPanel = new JPanel(new GridBagLayout());
topPanel.setOpaque(false);
topPanel.setBorder(BorderFactory.createEmptyBorder(3, 3, 0, 3));
GridBagConstraints gbc = new GridBagConstraints();
// first column, three rows span
queryTextArea = new QueryTextArea();
queryTextArea.setToolTipText("<html>Enter a query to search the datastore." + "<br><small>'{' or '.' activate auto-completion." + "<br>Ctrl+Enter add a new line.</small></html>");
queryTextArea.setLineWrap(true);
gbc.gridheight = 3;
gbc.weightx = 1;
gbc.weighty = 1;
gbc.fill = GridBagConstraints.BOTH;
gbc.insets = new Insets(0, 0, 0, 4);
topPanel.add(new JScrollPane(queryTextArea), gbc);
gbc.gridheight = 1;
gbc.weightx = 0;
gbc.weighty = 0;
gbc.insets = new Insets(0, 0, 0, 0);
// second column, first row
gbc.gridx = GridBagConstraints.RELATIVE;
topPanel.add(new JLabel("Corpus: "), gbc);
corpusToSearchIn = new JComboBox<String>();
corpusToSearchIn.addItem(Constants.ENTIRE_DATASTORE);
corpusToSearchIn.setPrototypeDisplayValue(Constants.ENTIRE_DATASTORE);
corpusToSearchIn.setToolTipText("Select the corpus to search in.");
if (target == null || target instanceof Searcher) {
corpusToSearchIn.setEnabled(false);
}
corpusToSearchIn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ie) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
updateAnnotationSetsList();
}
});
}
});
topPanel.add(corpusToSearchIn, gbc);
topPanel.add(Box.createHorizontalStrut(4), gbc);
topPanel.add(new JLabel("Annotation set: "), gbc);
annotationSetsToSearchIn = new JComboBox<String>();
annotationSetsToSearchIn.setPrototypeDisplayValue(Constants.COMBINED_SET);
annotationSetsToSearchIn.setToolTipText("Select the annotation set to search in.");
annotationSetsToSearchIn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ie) {
updateAnnotationTypesList();
}
});
topPanel.add(annotationSetsToSearchIn, gbc);
// refresh button
topPanel.add(Box.createHorizontalStrut(4), gbc);
RefreshAnnotationSetsAndFeaturesAction refreshAction = new RefreshAnnotationSetsAndFeaturesAction();
JButton refreshTF = new ButtonBorder(new Color(240, 240, 240), new Insets(4, 2, 4, 3), false);
refreshTF.setAction(refreshAction);
topPanel.add(refreshTF, gbc);
// second column, second row
gbc.gridy = 1;
JLabel noOfResultsLabel = new JLabel("Results: ");
topPanel.add(noOfResultsLabel, gbc);
numberOfResultsSlider = new JSlider(1, 1100, 50);
numberOfResultsSlider.setToolTipText("50 results per page");
numberOfResultsSlider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
if (numberOfResultsSlider.getValue() > (numberOfResultsSlider.getMaximum() - 100)) {
numberOfResultsSlider.setToolTipText("Retrieve all results.");
nextResults.setText("Retrieve all results.");
nextResultsAction.setEnabled(false);
} else {
numberOfResultsSlider.setToolTipText("Retrieve " + numberOfResultsSlider.getValue() + " results per page.");
nextResults.setText("Next page of " + numberOfResultsSlider.getValue() + " results");
if (searcher.getHits().length == noOfResults) {
nextResultsAction.setEnabled(true);
}
}
// show the tooltip each time the value change
ToolTipManager.sharedInstance().mouseMoved(new MouseEvent(numberOfResultsSlider, MouseEvent.MOUSE_MOVED, 0, 0, 0, 0, 0, false));
}
});
// always show the tooltip for this component
numberOfResultsSlider.addMouseListener(new MouseAdapter() {
ToolTipManager toolTipManager = ToolTipManager.sharedInstance();
int initialDelay, reshowDelay, dismissDelay;
boolean enabled;
@Override
public void mouseEntered(MouseEvent e) {
initialDelay = toolTipManager.getInitialDelay();
reshowDelay = toolTipManager.getReshowDelay();
dismissDelay = toolTipManager.getDismissDelay();
enabled = toolTipManager.isEnabled();
toolTipManager.setInitialDelay(0);
toolTipManager.setReshowDelay(0);
toolTipManager.setDismissDelay(Integer.MAX_VALUE);
toolTipManager.setEnabled(true);
}
@Override
public void mouseExited(MouseEvent e) {
toolTipManager.setInitialDelay(initialDelay);
toolTipManager.setReshowDelay(reshowDelay);
toolTipManager.setDismissDelay(dismissDelay);
toolTipManager.setEnabled(enabled);
}
});
gbc.insets = new Insets(5, 0, 0, 0);
topPanel.add(numberOfResultsSlider, gbc);
gbc.insets = new Insets(0, 0, 0, 0);
topPanel.add(Box.createHorizontalStrut(4), gbc);
JLabel contextWindowLabel = new JLabel("Context size: ");
topPanel.add(contextWindowLabel, gbc);
contextSizeSlider = new JSlider(1, 50, 5);
contextSizeSlider.setToolTipText("Display 5 tokens of context in the results.");
contextSizeSlider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
contextSizeSlider.setToolTipText("Display " + contextSizeSlider.getValue() + " tokens of context in the results.");
ToolTipManager.sharedInstance().mouseMoved(new MouseEvent(contextSizeSlider, MouseEvent.MOUSE_MOVED, 0, 0, 0, 0, 0, false));
}
});
// always show the tooltip for this component
contextSizeSlider.addMouseListener(new MouseAdapter() {
ToolTipManager toolTipManager = ToolTipManager.sharedInstance();
int initialDelay, reshowDelay, dismissDelay;
boolean enabled;
@Override
public void mouseEntered(MouseEvent e) {
initialDelay = toolTipManager.getInitialDelay();
reshowDelay = toolTipManager.getReshowDelay();
dismissDelay = toolTipManager.getDismissDelay();
enabled = toolTipManager.isEnabled();
toolTipManager.setInitialDelay(0);
toolTipManager.setReshowDelay(0);
toolTipManager.setDismissDelay(Integer.MAX_VALUE);
toolTipManager.setEnabled(true);
}
@Override
public void mouseExited(MouseEvent e) {
toolTipManager.setInitialDelay(initialDelay);
toolTipManager.setReshowDelay(reshowDelay);
toolTipManager.setDismissDelay(dismissDelay);
toolTipManager.setEnabled(enabled);
}
});
gbc.insets = new Insets(5, 0, 0, 0);
topPanel.add(contextSizeSlider, gbc);
gbc.insets = new Insets(0, 0, 0, 0);
// second column, third row
gbc.gridy = 2;
JPanel panel = new JPanel();
panel.setBorder(new EmptyBorder(new Insets(0, 0, 0, 0)));
executeQueryAction = new ExecuteQueryAction();
JButton executeQuery = new ButtonBorder(new Color(240, 240, 240), new Insets(0, 2, 0, 3), false);
executeQuery.setAction(executeQueryAction);
panel.add(executeQuery);
ClearQueryAction clearQueryAction = new ClearQueryAction();
JButton clearQueryTF = new ButtonBorder(new Color(240, 240, 240), new Insets(4, 2, 4, 3), false);
clearQueryTF.setAction(clearQueryAction);
panel.add(Box.createHorizontalStrut(5));
panel.add(clearQueryTF);
nextResultsAction = new NextResultsAction();
nextResultsAction.setEnabled(false);
nextResults = new ButtonBorder(new Color(240, 240, 240), new Insets(0, 0, 0, 3), false);
nextResults.setAction(nextResultsAction);
panel.add(Box.createHorizontalStrut(5));
panel.add(nextResults);
gbc.fill = GridBagConstraints.NONE;
gbc.anchor = GridBagConstraints.WEST;
gbc.gridwidth = GridBagConstraints.REMAINDER;
topPanel.add(panel, gbc);
// will be added to the GUI via a split panel
/**
**************
* Center panel *
***************
*/
// these components will be used in updateStackView()
centerPanel = new AnnotationStack(150, 30);
configureStackViewButton = new ButtonBorder(new Color(250, 250, 250), new Insets(0, 0, 0, 3), true);
configureStackViewButton.setHorizontalAlignment(SwingConstants.LEFT);
configureStackViewButton.setAction(new ConfigureStackViewAction());
// will be added to the GUI via a split panel
/**
*******************
* Bottom left panel *
********************
*/
JPanel bottomLeftPanel = new JPanel(new GridBagLayout());
bottomLeftPanel.setOpaque(false);
gbc = new GridBagConstraints();
// title of the table, results options, export and next results
// button
gbc.gridy = 0;
panel = new JPanel();
panel.setBorder(new EmptyBorder(new Insets(0, 0, 0, 0)));
titleResults = new JLabel("Results");
titleResults.setBorder(new EmptyBorder(new Insets(0, 0, 0, 0)));
panel.add(titleResults);
panel.add(Box.createHorizontalStrut(5), gbc);
exportResultsAction = new ExportResultsAction();
exportResultsAction.setEnabled(false);
JButton exportToHTML = new ButtonBorder(new Color(240, 240, 240), new Insets(0, 0, 0, 3), false);
exportToHTML.setAction(exportResultsAction);
panel.add(exportToHTML, gbc);
bottomLeftPanel.add(panel, gbc);
// table of results
resultTableModel = new ResultTableModel();
resultTable = new XJTable(resultTableModel);
resultTable.setDefaultRenderer(String.class, new ResultTableCellRenderer());
resultTable.setEnableHidingColumns(true);
resultTable.addMouseListener(new MouseAdapter() {
private JPopupMenu mousePopup;
JMenuItem menuItem;
@Override
public void mousePressed(MouseEvent e) {
int row = resultTable.rowAtPoint(e.getPoint());
if (e.isPopupTrigger() && !resultTable.isRowSelected(row)) {
// if right click outside the selection then reset selection
resultTable.getSelectionModel().setSelectionInterval(row, row);
}
if (e.isPopupTrigger()) {
createPopup();
mousePopup.show(e.getComponent(), e.getX(), e.getY());
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
createPopup();
mousePopup.show(e.getComponent(), e.getX(), e.getY());
}
}
private void createPopup() {
mousePopup = new JPopupMenu();
menuItem = new JMenuItem("Remove the selected result" + (resultTable.getSelectedRowCount() > 1 ? "s" : ""));
mousePopup.add(menuItem);
menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
int[] rows = resultTable.getSelectedRows();
for (int i = 0; i < rows.length; i++) {
rows[i] = resultTable.rowViewToModel(rows[i]);
}
Arrays.sort(rows);
for (int i = rows.length - 1; i >= 0; i--) {
results.remove(rows[i]);
}
resultTable.clearSelection();
resultTableModel.fireTableDataChanged();
mousePopup.setVisible(false);
}
});
if (target instanceof LuceneDataStoreImpl && SwingUtilities.getRoot(LuceneDataStoreSearchGUI.this) instanceof MainFrame) {
menuItem = new JMenuItem("Open the selected document" + (resultTable.getSelectedRowCount() > 1 ? "s" : ""));
menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
Set<Pattern> patterns = new HashSet<Pattern>();
Set<String> documentIds = new HashSet<String>();
for (int rowView : resultTable.getSelectedRows()) {
// create and display the document for this result
int rowModel = resultTable.rowViewToModel(rowView);
Pattern pattern = (Pattern) results.get(rowModel);
if (!documentIds.contains(pattern.getDocumentID())) {
patterns.add(pattern);
documentIds.add(pattern.getDocumentID());
}
}
if (patterns.size() > 10) {
Object[] possibleValues = { "Open the " + patterns.size() + " documents", "Don't open" };
int selectedValue = JOptionPane.showOptionDialog(LuceneDataStoreSearchGUI.this, "Do you want to open " + patterns.size() + " documents in the central tabbed pane ?", "Warning", JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, possibleValues, possibleValues[1]);
if (selectedValue == 1 || selectedValue == JOptionPane.CLOSED_OPTION) {
return;
}
}
for (final Pattern pattern : patterns) {
// create and display the document for this result
FeatureMap features = Factory.newFeatureMap();
features.put(DataStore.DATASTORE_FEATURE_NAME, target);
features.put(DataStore.LR_ID_FEATURE_NAME, pattern.getDocumentID());
final Document doc;
try {
doc = (Document) Factory.createResource("gate.corpora.DocumentImpl", features);
} catch (gate.util.GateException e) {
e.printStackTrace();
return;
}
// show the expression in the document
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
MainFrame.getInstance().select(doc);
}
});
if (patterns.size() == 1) {
// wait some time for the document to be displayed
Date timeToRun = new Date(System.currentTimeMillis() + 2000);
Timer timer = new Timer("Annic show document timer", true);
timer.schedule(new TimerTask() {
@Override
public void run() {
showResultInDocument(doc, pattern);
}
}, timeToRun);
}
}
}
});
mousePopup.add(menuItem);
}
}
});
// resultTable.addMouseListener
// when selection change in the result table
// update the stack view and export button
resultTable.getSelectionModel().addListSelectionListener(new javax.swing.event.ListSelectionListener() {
@Override
public void valueChanged(javax.swing.event.ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
updateStackView();
}
}
});
resultTable.setColumnSelectionAllowed(false);
resultTable.setRowSelectionAllowed(true);
resultTable.setSortable(true);
resultTable.setComparator(ResultTableModel.LEFT_CONTEXT_COLUMN, lastWordComparator);
resultTable.setComparator(ResultTableModel.RESULT_COLUMN, stringCollator);
resultTable.setComparator(ResultTableModel.RIGHT_CONTEXT_COLUMN, stringCollator);
JScrollPane tableScrollPane = new JScrollPane(resultTable, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
gbc.fill = GridBagConstraints.BOTH;
gbc.anchor = GridBagConstraints.NORTH;
gbc.gridy = 1;
gbc.gridx = 0;
gbc.insets = new Insets(0, 0, 0, 0);
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.gridheight = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.weighty = 1;
bottomLeftPanel.add(tableScrollPane, gbc);
/**
************************
* Statistics tabbed pane *
*************************
*/
statisticsTabbedPane = new JTabbedPane();
globalStatisticsTable = new XJTable() {
@Override
public boolean isCellEditable(int rowIndex, int vColIndex) {
return false;
}
};
globalStatisticsTableModel = new DefaultTableModel(new Object[] { "Annotation Type", "Count" }, 0);
globalStatisticsTable.setModel(globalStatisticsTableModel);
globalStatisticsTable.setComparator(0, stringCollator);
globalStatisticsTable.setComparator(1, integerComparator);
globalStatisticsTable.setSortedColumn(1);
globalStatisticsTable.setAscending(false);
globalStatisticsTable.addMouseListener(new MouseInputAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) {
updateQuery();
}
}
private void updateQuery() {
int caretPosition = queryTextArea.getCaretPosition();
String query = queryTextArea.getText();
String type = (String) globalStatisticsTable.getValueAt(globalStatisticsTable.getSelectedRow(), globalStatisticsTable.convertColumnIndexToView(0));
String queryMiddle = "{" + type + "}";
String queryLeft = (queryTextArea.getSelectionStart() == queryTextArea.getSelectionEnd()) ? query.substring(0, caretPosition) : query.substring(0, queryTextArea.getSelectionStart());
String queryRight = (queryTextArea.getSelectionStart() == queryTextArea.getSelectionEnd()) ? query.substring(caretPosition, query.length()) : query.substring(queryTextArea.getSelectionEnd(), query.length());
queryTextArea.setText(queryLeft + queryMiddle + queryRight);
}
});
statisticsTabbedPane.addTab("Global", null, new JScrollPane(globalStatisticsTable), "Global statistics on the Corpus and Annotation Set selected.");
statisticsTabbedPane.addMouseListener(new MouseAdapter() {
private JPopupMenu mousePopup;
JMenuItem menuItem;
@Override
public void mousePressed(MouseEvent e) {
int tabIndex = statisticsTabbedPane.indexAtLocation(e.getX(), e.getY());
if (e.isPopupTrigger() && tabIndex > 0) {
createPopup(tabIndex);
mousePopup.show(e.getComponent(), e.getX(), e.getY());
}
}
@Override
public void mouseReleased(MouseEvent e) {
int tabIndex = statisticsTabbedPane.indexAtLocation(e.getX(), e.getY());
if (e.isPopupTrigger() && tabIndex > 0) {
createPopup(tabIndex);
mousePopup.show(e.getComponent(), e.getX(), e.getY());
}
}
private void createPopup(final int tabIndex) {
mousePopup = new JPopupMenu();
if (tabIndex == 1) {
menuItem = new JMenuItem("Clear table");
menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ie) {
oneRowStatisticsTableModel.setRowCount(0);
}
});
} else {
menuItem = new JMenuItem("Close tab");
menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ie) {
statisticsTabbedPane.remove(tabIndex);
}
});
}
mousePopup.add(menuItem);
}
});
class RemoveCellEditorRenderer extends AbstractCellEditor implements TableCellRenderer, TableCellEditor, ActionListener {
private JButton button;
public RemoveCellEditorRenderer() {
button = new JButton();
button.setHorizontalAlignment(SwingConstants.CENTER);
button.setIcon(MainFrame.getIcon("Delete"));
button.setToolTipText("Remove this row.");
button.setContentAreaFilled(false);
button.setBorderPainted(false);
button.setMargin(new Insets(0, 0, 0, 0));
button.addActionListener(this);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object color, boolean isSelected, boolean hasFocus, int row, int col) {
button.setSelected(isSelected);
return button;
}
@Override
public boolean shouldSelectCell(EventObject anEvent) {
return false;
}
@Override
public void actionPerformed(ActionEvent e) {
int editingRow = oneRowStatisticsTable.getEditingRow();
fireEditingStopped();
oneRowStatisticsTableModel.removeRow(oneRowStatisticsTable.rowViewToModel(editingRow));
}
@Override
public Object getCellEditorValue() {
return null;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int col) {
button.setSelected(isSelected);
return button;
}
}
oneRowStatisticsTable = new XJTable() {
@Override
public boolean isCellEditable(int rowIndex, int vColIndex) {
return vColIndex == 2;
}
@Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int col) {
Component c = super.prepareRenderer(renderer, row, col);
if (c instanceof JComponent && col != 2) {
// display a custom tooltip saved when adding statistics
((JComponent) c).setToolTipText("<html>" + oneRowStatisticsTableToolTips.get(rowViewToModel(row)) + "</html>");
}
return c;
}
};
oneRowStatisticsTableModel = new DefaultTableModel(new Object[] { "Annotation Type/Feature", "Count", "" }, 0);
oneRowStatisticsTable.setModel(oneRowStatisticsTableModel);
oneRowStatisticsTable.getColumnModel().getColumn(2).setCellEditor(new RemoveCellEditorRenderer());
oneRowStatisticsTable.getColumnModel().getColumn(2).setCellRenderer(new RemoveCellEditorRenderer());
oneRowStatisticsTable.setComparator(0, stringCollator);
oneRowStatisticsTable.setComparator(1, integerComparator);
statisticsTabbedPane.addTab("One item", null, new JScrollPane(oneRowStatisticsTable), "<html>One item statistics.<br>" + "Right-click on an annotation<br>" + "to add statistics here.");
oneRowStatisticsTableToolTips = new Vector<String>();
// will be added to the GUI via a split panel
/**
************************************************************
* Vertical splits between top, center panel and bottom panel *
*************************************************************
*/
/**
* ________________________________________
* | topPanel |
* |__________________3_____________________|
* | |
* | centerPanel |
* |________2________ __________2___________|
* | | |
* | bottomLeftPanel 1 statisticsTabbedPane |
* |_________________|______________________|
*
* 1 bottomSplitPane 2 centerBottomSplitPane 3 topBottomSplitPane
*/
bottomSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
Dimension minimumSize = new Dimension(0, 0);
bottomLeftPanel.setMinimumSize(minimumSize);
statisticsTabbedPane.setMinimumSize(minimumSize);
bottomSplitPane.add(bottomLeftPanel);
bottomSplitPane.add(statisticsTabbedPane);
bottomSplitPane.setOneTouchExpandable(true);
bottomSplitPane.setResizeWeight(0.75);
bottomSplitPane.setContinuousLayout(true);
JSplitPane centerBottomSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
centerBottomSplitPane.add(new JScrollPane(centerPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));
centerBottomSplitPane.add(bottomSplitPane);
centerBottomSplitPane.setResizeWeight(0.5);
centerBottomSplitPane.setContinuousLayout(true);
JSplitPane topBottomSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
topBottomSplitPane.add(topPanel);
topBottomSplitPane.add(centerBottomSplitPane);
topBottomSplitPane.setContinuousLayout(true);
add(topBottomSplitPane, BorderLayout.CENTER);
}
use of gate.Document in project gate-core by GateNLP.
the class AnnotationDiffGUI method initListeners.
protected void initListeners() {
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
new CloseAction().actionPerformed(null);
}
});
addWindowFocusListener(new WindowAdapter() {
@Override
public void windowGainedFocus(WindowEvent e) {
populateGUI();
}
});
keyDocCombo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
int keyDocSelectedIndex = keyDocCombo.getSelectedIndex();
if (keyDocSelectedIndex == -1) {
return;
}
Document newDoc = (Document) documents.get(keyDocSelectedIndex);
if (keyDoc == newDoc) {
return;
}
pairings.clear();
diffTableModel.fireTableDataChanged();
copyToTargetSetAction.setEnabled(false);
keyDoc = newDoc;
keySets = new ArrayList<AnnotationSet>();
List<String> keySetNames = new ArrayList<String>();
keySets.add(keyDoc.getAnnotations());
keySetNames.add("[Default set]");
if (keyDoc.getNamedAnnotationSets() != null) {
for (Object o : keyDoc.getNamedAnnotationSets().keySet()) {
String name = (String) o;
keySetNames.add(name);
keySets.add(keyDoc.getAnnotations(name));
}
}
keySetCombo.setModel(new DefaultComboBoxModel<String>(keySetNames.toArray(new String[keySetNames.size()])));
if (!keySetNames.isEmpty()) {
keySetCombo.setSelectedIndex(0);
if (resSetCombo.getItemCount() > 0) {
// find first annotation set with annotation type in common
for (int res = 0; res < resSetCombo.getItemCount(); res++) {
resSetCombo.setSelectedIndex(res);
for (int key = 0; key < keySetCombo.getItemCount(); key++) {
if (keyDoc.equals(resDoc) && resSetCombo.getItemAt(res).equals(keySetCombo.getItemAt(key))) {
// same document, skip it
continue;
}
keySetCombo.setSelectedIndex(key);
if (annTypeCombo.getSelectedItem() != null) {
break;
}
}
if (annTypeCombo.getSelectedItem() != null) {
break;
}
}
if (annTypeCombo.getSelectedItem() == null) {
statusLabel.setText("There is no annotation type in common.");
statusLabel.setForeground(Color.RED);
} else if (statusLabel.getText().equals("There is no annotation type in common.")) {
statusLabel.setText("The first annotation sets with" + " annotation type in common have been automatically selected.");
statusLabel.setForeground(Color.BLACK);
}
}
}
}
});
resDocCombo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
int resDocSelectedIndex = resDocCombo.getSelectedIndex();
if (resDocSelectedIndex == -1) {
return;
}
Document newDoc = (Document) documents.get(resDocSelectedIndex);
if (resDoc == newDoc) {
return;
}
resDoc = newDoc;
pairings.clear();
diffTableModel.fireTableDataChanged();
copyToTargetSetAction.setEnabled(false);
resSets = new ArrayList<AnnotationSet>();
List<String> resSetNames = new ArrayList<String>();
resSets.add(resDoc.getAnnotations());
resSetNames.add("[Default set]");
if (resDoc.getNamedAnnotationSets() != null) {
for (Object o : resDoc.getNamedAnnotationSets().keySet()) {
String name = (String) o;
resSetNames.add(name);
resSets.add(resDoc.getAnnotations(name));
}
}
resSetCombo.setModel(new DefaultComboBoxModel<String>(resSetNames.toArray(new String[resSetNames.size()])));
if (!resSetNames.isEmpty()) {
resSetCombo.setSelectedIndex(0);
if (keySetCombo.getItemCount() > 0) {
// find annotation sets with annotations in common
for (int res = 0; res < resSetCombo.getItemCount(); res++) {
resSetCombo.setSelectedIndex(res);
for (int key = 0; key < keySetCombo.getItemCount(); key++) {
if (keyDoc.equals(resDoc) && resSetCombo.getItemAt(res).equals(keySetCombo.getItemAt(key))) {
continue;
}
keySetCombo.setSelectedIndex(key);
if (annTypeCombo.getSelectedItem() != null) {
break;
}
}
if (annTypeCombo.getSelectedItem() != null) {
break;
}
}
if (annTypeCombo.getSelectedItem() == null) {
statusLabel.setText("There is no annotations in common.");
statusLabel.setForeground(Color.RED);
} else if (statusLabel.getText().equals("There is no annotations in common.")) {
statusLabel.setText("The first annotation sets with" + " annotations in common have been selected.");
statusLabel.setForeground(Color.BLACK);
}
}
}
}
});
/**
* This populates the types combo when set selection changes
*/
ActionListener setComboActionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
keySet = keySets == null || keySets.isEmpty() ? null : keySets.get(keySetCombo.getSelectedIndex());
resSet = resSets == null || resSets.isEmpty() ? null : resSets.get(resSetCombo.getSelectedIndex());
Set<String> keyTypes = (keySet == null || keySet.isEmpty()) ? new HashSet<String>() : keySet.getAllTypes();
Set<String> resTypes = (resSet == null || resSet.isEmpty()) ? new HashSet<String>() : resSet.getAllTypes();
Set<String> types = new HashSet<String>(keyTypes);
types.retainAll(resTypes);
List<String> typesList = new ArrayList<String>(types);
Collections.sort(typesList);
annTypeCombo.setModel(new DefaultComboBoxModel<String>(typesList.toArray(new String[typesList.size()])));
if (typesList.size() > 0) {
annTypeCombo.setSelectedIndex(0);
diffAction.setEnabled(true);
doDiffBtn.setForeground((Color) UIManager.getDefaults().get("Button.foreground"));
doDiffBtn.setToolTipText((String) diffAction.getValue(Action.SHORT_DESCRIPTION));
} else {
diffAction.setEnabled(false);
doDiffBtn.setForeground((Color) UIManager.getDefaults().get("Button.disabledText"));
doDiffBtn.setToolTipText("Choose two annotation sets " + "that have at least one annotation type in common.");
}
}
};
keySetCombo.addActionListener(setComboActionListener);
resSetCombo.addActionListener(setComboActionListener);
someFeaturesBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
if (someFeaturesBtn.isSelected()) {
if (keySet == null || keySet.isEmpty() || annTypeCombo.getSelectedItem() == null)
return;
Iterator<Annotation> annIter = keySet.get((String) annTypeCombo.getSelectedItem()).iterator();
Set<String> featureSet = new HashSet<String>();
while (annIter.hasNext()) {
Annotation ann = annIter.next();
Map<Object, Object> someFeatures = ann.getFeatures();
if (someFeatures == null) {
continue;
}
for (Object feature : someFeatures.keySet()) {
featureSet.add((String) feature);
}
}
List<String> featureList = new ArrayList<String>(featureSet);
Collections.sort(featureList);
featureslistModel.clear();
Iterator<String> featIter = featureList.iterator();
int index = 0;
while (featIter.hasNext()) {
String aFeature = featIter.next();
featureslistModel.addElement(aFeature);
if (significantFeatures.contains(aFeature))
featuresList.addSelectionInterval(index, index);
index++;
}
int ret = JOptionPane.showConfirmDialog(AnnotationDiffGUI.this, new JScrollPane(featuresList), "Select features", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
if (ret == JOptionPane.OK_OPTION) {
significantFeatures.clear();
int[] selIdxs = featuresList.getSelectedIndices();
for (int selIdx : selIdxs) {
significantFeatures.add(featureslistModel.get(selIdx));
}
}
}
}
});
// enable/disable buttons according to the table state
diffTableModel.addTableModelListener(new TableModelListener() {
@Override
public void tableChanged(javax.swing.event.TableModelEvent e) {
if (diffTableModel.getRowCount() > 0) {
htmlExportAction.setEnabled(true);
htmlExportBtn.setToolTipText((String) htmlExportAction.getValue(Action.SHORT_DESCRIPTION));
showDocumentAction.setEnabled(true);
showDocumentBtn.setToolTipText((String) showDocumentAction.getValue(Action.SHORT_DESCRIPTION));
} else {
htmlExportAction.setEnabled(false);
htmlExportBtn.setToolTipText("Use first the \"Compare\" button.");
showDocumentAction.setEnabled(false);
showDocumentBtn.setToolTipText("Use first the \"Compare\"" + " button then select an annotation in the table.");
}
}
});
// enable/disable buttons according to the table selection
diffTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
int row = diffTable.rowViewToModel(diffTable.getSelectedRow());
if (row == -1) {
showDocumentAction.setEnabled(false);
return;
}
AnnotationDiffer.Pairing pairing = pairings.get(row);
Annotation key = pairing.getKey();
Annotation response = pairing.getResponse();
int column = diffTable.convertColumnIndexToModel(diffTable.getSelectedColumn());
boolean enabled;
switch(column) {
case DiffTableModel.COL_KEY_START:
case DiffTableModel.COL_KEY_END:
case DiffTableModel.COL_KEY_STRING:
case DiffTableModel.COL_KEY_FEATURES:
enabled = (key != null);
break;
case DiffTableModel.COL_RES_START:
case DiffTableModel.COL_RES_END:
case DiffTableModel.COL_RES_STRING:
case DiffTableModel.COL_RES_FEATURES:
enabled = (response != null);
break;
default:
enabled = false;
}
showDocumentAction.setEnabled(enabled);
}
});
// enable/disable buttons according to the table selection
diffTable.getColumnModel().addColumnModelListener(new TableColumnModelListener() {
@Override
public void columnAdded(TableColumnModelEvent e) {
/* do nothing */
}
@Override
public void columnRemoved(TableColumnModelEvent e) {
/* do nothing */
}
@Override
public void columnMoved(TableColumnModelEvent e) {
/* do nothing */
}
@Override
public void columnMarginChanged(ChangeEvent e) {
/* do nothing */
}
@Override
public void columnSelectionChanged(ListSelectionEvent e) {
int row = diffTable.rowViewToModel(diffTable.getSelectedRow());
if (row == -1) {
showDocumentAction.setEnabled(false);
return;
}
AnnotationDiffer.Pairing pairing = pairings.get(row);
Annotation key = pairing.getKey();
Annotation response = pairing.getResponse();
int column = diffTable.convertColumnIndexToModel(diffTable.getSelectedColumn());
boolean enabled;
switch(column) {
case DiffTableModel.COL_KEY_START:
case DiffTableModel.COL_KEY_END:
case DiffTableModel.COL_KEY_STRING:
case DiffTableModel.COL_KEY_FEATURES:
enabled = (key != null);
break;
case DiffTableModel.COL_RES_START:
case DiffTableModel.COL_RES_END:
case DiffTableModel.COL_RES_STRING:
case DiffTableModel.COL_RES_FEATURES:
enabled = (response != null);
break;
default:
enabled = false;
}
showDocumentAction.setEnabled(enabled);
}
});
// inverse state of selected checkboxes when Space key is pressed
diffTable.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() != KeyEvent.VK_SPACE || !(diffTable.isColumnSelected(DiffTableModel.COL_KEY_COPY) || diffTable.isColumnSelected(DiffTableModel.COL_RES_COPY))) {
return;
}
// disable normal behavior of Space key in a table
e.consume();
int[] cols = { DiffTableModel.COL_KEY_COPY, DiffTableModel.COL_RES_COPY };
for (int col : cols) {
for (int row : diffTable.getSelectedRows()) {
if (diffTable.isCellSelected(row, col) && diffTable.isCellEditable(row, col)) {
diffTable.setValueAt(!(Boolean) diffTable.getValueAt(row, col), row, col);
diffTableModel.fireTableCellUpdated(row, col);
}
}
}
}
});
// context menu for the check boxes to easily change their state
diffTable.addMouseListener(new MouseAdapter() {
private JPopupMenu mousePopup;
JMenuItem menuItem;
@Override
public void mousePressed(MouseEvent e) {
showContextMenu(e);
}
@Override
public void mouseReleased(MouseEvent e) {
showContextMenu(e);
}
private void showContextMenu(MouseEvent e) {
int col = diffTable.convertColumnIndexToModel(diffTable.columnAtPoint(e.getPoint()));
if (!e.isPopupTrigger() || (col != DiffTableModel.COL_KEY_COPY && col != DiffTableModel.COL_RES_COPY)) {
return;
}
mousePopup = new JPopupMenu();
for (final String tick : new String[] { "Tick", "Untick" }) {
menuItem = new JMenuItem(tick + " selected check boxes");
menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
int keyCol = diffTable.convertColumnIndexToView(DiffTableModel.COL_KEY_COPY);
int responseCol = diffTable.convertColumnIndexToView(DiffTableModel.COL_RES_COPY);
for (int row = 0; row < diffTable.getRowCount(); row++) {
int rowModel = diffTable.rowViewToModel(row);
AnnotationDiffer.Pairing pairing = pairings.get(rowModel);
if (diffTable.isCellSelected(row, keyCol) && pairing.getKey() != null) {
diffTable.setValueAt(tick.equals("Tick"), row, keyCol);
}
if (diffTable.isCellSelected(row, responseCol) && pairing.getResponse() != null) {
diffTable.setValueAt(tick.equals("Tick"), row, responseCol);
}
}
diffTableModel.fireTableDataChanged();
}
});
mousePopup.add(menuItem);
}
mousePopup.addSeparator();
String[] types = new String[] { "correct", "partially correct", "missing", "false positives", "mismatch" };
String[] symbols = new String[] { "=", "~", "-?", "?-", "<>" };
for (int i = 0; i < types.length; i++) {
menuItem = new JMenuItem("Tick " + types[i] + " annotations");
final String symbol = symbols[i];
menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
int matchCol = diffTable.convertColumnIndexToView(DiffTableModel.COL_MATCH);
for (int row = 0; row < diffTable.getRowCount(); row++) {
int rowModel = diffTable.rowViewToModel(row);
AnnotationDiffer.Pairing pairing = pairings.get(rowModel);
if (diffTable.getValueAt(row, matchCol).equals(symbol) && pairing.getKey() != null) {
keyCopyValueRows.set(diffTable.rowViewToModel(row), true);
} else if (diffTable.getValueAt(row, matchCol).equals(symbol) && pairing.getResponse() != null) {
resCopyValueRows.set(diffTable.rowViewToModel(row), true);
}
}
diffTableModel.fireTableDataChanged();
}
});
mousePopup.add(menuItem);
}
mousePopup.show(e.getComponent(), e.getX(), e.getY());
}
});
// revert to default name if the field is empty and lost focus
consensusASTextField.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
String target = consensusASTextField.getText().trim();
if (target.length() == 0) {
consensusASTextField.setText("consensus");
}
if (keyDoc != null && keyDoc.getAnnotationSetNames().contains(target)) {
statusLabel.setText("Be careful, the annotation set " + target + " already exists.");
statusLabel.setForeground(Color.RED);
}
}
});
bottomTabbedPane.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
if (bottomTabbedPane.getSelectedIndex() == 0) {
diffTable.hideColumn(DiffTableModel.COL_KEY_COPY);
diffTable.hideColumn(DiffTableModel.COL_RES_COPY);
} else {
int middleIndex = Math.round(diffTable.getColumnCount() / 2);
diffTable.showColumn(DiffTableModel.COL_KEY_COPY, middleIndex);
diffTable.showColumn(DiffTableModel.COL_RES_COPY, middleIndex + 2);
diffTable.getColumnModel().getColumn(DiffTableModel.COL_KEY_COPY).setPreferredWidth(10);
diffTable.getColumnModel().getColumn(DiffTableModel.COL_RES_COPY).setPreferredWidth(10);
diffTable.doLayout();
}
}
});
// define keystrokes action bindings at the level of the main window
InputMap inputMap = ((JComponent) this.getContentPane()).getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = ((JComponent) this.getContentPane()).getActionMap();
inputMap.put(KeyStroke.getKeyStroke("F1"), "Help");
actionMap.put("Help", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
new HelpAction().actionPerformed(null);
}
});
}
use of gate.Document in project gate-core by GateNLP.
the class CorpusBenchmarkTool method generateCorpus.
// setStartDirectory
protected void generateCorpus(File fileDir, File outputDir) {
// 1. check if we have input files
if (fileDir == null)
return;
// 2. create the output directory or clean it up if needed
File outDir = outputDir;
if (outputDir == null) {
outDir = new File(currDir, PROCESSED_DIR_NAME);
} else {
// get rid of the directory, coz datastore wants it clean
if (!Files.rmdir(outDir))
Out.prln("cannot delete old output directory: " + outDir);
}
outDir.mkdir();
// create the datastore and process each document
try {
SerialDataStore sds = new SerialDataStore(outDir.toURI().toURL().toString());
sds.create();
sds.open();
File[] files = fileDir.listFiles();
for (int i = 0; i < files.length; i++) {
if (!files[i].isFile())
continue;
// create a document
Out.prln("Processing and storing document: " + files[i].toURI().toURL() + "<P>");
FeatureMap params = Factory.newFeatureMap();
params.put(Document.DOCUMENT_URL_PARAMETER_NAME, files[i].toURI().toURL());
params.put(Document.DOCUMENT_ENCODING_PARAMETER_NAME, documentEncoding);
FeatureMap features = Factory.newFeatureMap();
// Gate.setHiddenAttribute(features, true);
// create the document
final Document doc = (Document) Factory.createResource("gate.corpora.DocumentImpl", params, features);
doc.setName(files[i].getName());
processDocument(doc);
final LanguageResource lr = sds.adopt(doc);
sds.sync(lr);
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Factory.deleteResource(doc);
Factory.deleteResource(lr);
}
});
}
// for
sds.close();
} catch (java.net.MalformedURLException ex) {
throw (GateRuntimeException) new GateRuntimeException("CorpusBenchmark: " + ex.getMessage()).initCause(ex);
} catch (PersistenceException ex1) {
throw (GateRuntimeException) new GateRuntimeException("CorpusBenchmark: " + ex1.getMessage()).initCause(ex1);
} catch (ResourceInstantiationException ex2) {
throw (GateRuntimeException) new GateRuntimeException("CorpusBenchmark: " + ex2.getMessage()).initCause(ex2);
}
}
use of gate.Document in project gate-core by GateNLP.
the class CorpusBenchmarkTool method evaluateMarkedStored.
// evaluateCorpus
protected void evaluateMarkedStored(File markedDir, File storedDir, File errDir) {
Document persDoc = null;
Document cleanDoc = null;
Document markedDoc = null;
// open the datastore and process each document
try {
// open the data store
DataStore sds = Factory.openDataStore("gate.persist.SerialDataStore", storedDir.toURI().toURL().toExternalForm());
List<String> lrIDs = sds.getLrIds("gate.corpora.DocumentImpl");
for (int i = 0; i < lrIDs.size(); i++) {
String docID = lrIDs.get(i);
// read the stored document
FeatureMap features = Factory.newFeatureMap();
features.put(DataStore.DATASTORE_FEATURE_NAME, sds);
features.put(DataStore.LR_ID_FEATURE_NAME, docID);
FeatureMap hparams = Factory.newFeatureMap();
// Gate.setHiddenAttribute(hparams, true);
persDoc = (Document) Factory.createResource("gate.corpora.DocumentImpl", features, hparams);
if (isMoreInfoMode) {
StringBuffer errName = new StringBuffer(persDoc.getName());
errName.replace(persDoc.getName().lastIndexOf("."), persDoc.getName().length(), ".err");
Out.prln("<H2>" + "<a href=\"err/" + errName.toString() + "\">" + persDoc.getName() + "</a>" + "</H2>");
} else
Out.prln("<H2>" + persDoc.getName() + "</H2>");
if (!this.isMarkedDS) {
// try finding the marked document as file
StringBuffer docName = new StringBuffer(persDoc.getName());
docName.replace(persDoc.getName().lastIndexOf("."), docName.length(), ".xml");
File markedDocFile = new File(markedDir, docName.toString());
if (!markedDocFile.exists()) {
Out.prln("Warning: Cannot find human-annotated document " + markedDocFile + " in " + markedDir);
} else {
FeatureMap params = Factory.newFeatureMap();
params.put(Document.DOCUMENT_URL_PARAMETER_NAME, markedDocFile.toURI().toURL());
params.put(Document.DOCUMENT_ENCODING_PARAMETER_NAME, documentEncoding);
// create the document
markedDoc = (Document) Factory.createResource("gate.corpora.DocumentImpl", params, hparams);
markedDoc.setName(persDoc.getName());
}
// find marked as file
} else {
try {
// open marked from a DS
// open the data store
DataStore sds1 = Factory.openDataStore("gate.persist.SerialDataStore", markedDir.toURI().toURL().toExternalForm());
List<String> lrIDs1 = sds1.getLrIds("gate.corpora.DocumentImpl");
boolean found = false;
int k = 0;
// search for the marked doc with the same name
while (k < lrIDs1.size() && !found) {
String docID1 = lrIDs1.get(k);
// read the stored document
FeatureMap features1 = Factory.newFeatureMap();
features1.put(DataStore.DATASTORE_FEATURE_NAME, sds1);
features1.put(DataStore.LR_ID_FEATURE_NAME, docID1);
Document tempDoc = (Document) Factory.createResource("gate.corpora.DocumentImpl", features1, hparams);
// check whether this is our doc
if (((String) tempDoc.getFeatures().get("gate.SourceURL")).endsWith(persDoc.getName())) {
found = true;
markedDoc = tempDoc;
} else
k++;
}
} catch (java.net.MalformedURLException ex) {
Out.prln("Error finding marked directory " + markedDir.getAbsolutePath());
} catch (gate.persist.PersistenceException ex1) {
Out.prln("Error opening marked as a datastore (-marked_ds specified)");
} catch (gate.creole.ResourceInstantiationException ex2) {
Out.prln("Error opening marked as a datastore (-marked_ds specified)");
}
}
evaluateDocuments(persDoc, cleanDoc, markedDoc, errDir);
if (persDoc != null) {
final gate.Document pd = persDoc;
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Factory.deleteResource(pd);
}
});
}
if (markedDoc != null) {
final gate.Document md = markedDoc;
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Factory.deleteResource(md);
}
});
}
}
// for loop through saved docs
sds.close();
} catch (java.net.MalformedURLException ex) {
throw (GateRuntimeException) new GateRuntimeException("CorpusBenchmark: " + ex.getMessage()).initCause(ex);
} catch (PersistenceException ex1) {
throw (GateRuntimeException) new GateRuntimeException("CorpusBenchmark: " + ex1.getMessage()).initCause(ex1);
} catch (ResourceInstantiationException ex2) {
throw (GateRuntimeException) new GateRuntimeException("CorpusBenchmark: " + ex2.getMessage()).initCause(ex2);
}
}
use of gate.Document in project gate-core by GateNLP.
the class SerialCorpusImpl method resourceUnloaded.
@Override
public void resourceUnloaded(CreoleEvent e) {
Resource res = e.getResource();
if (res instanceof Document) {
Document doc = (Document) res;
if (DEBUG)
Out.prln("resource Unloaded called ");
// remove from the corpus too, if a transient one
if (doc.getDataStore() != this.getDataStore()) {
this.remove(doc);
} else {
// unload all occurences
int index = indexOf(res);
if (index < 0)
return;
documents.set(index, null);
if (DEBUG)
Out.prln("corpus: document " + index + " unloaded and set to null");
}
// if
}
}
Aggregations