gate.gui.ResourceParametersEditor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gate-core Show documentation
Show all versions of gate-core Show documentation
GATE - general achitecture for text engineering - is open source
software capable of solving almost any text processing problem. This
artifact enables you to embed the core GATE Embedded with its essential
dependencies. You will able to use the GATE Embedded API and load and
store GATE XML documents. This artifact is the perfect dependency for
CREOLE plugins or for applications that need to customize the GATE
dependencies due to confict with their own dependencies or for lower
footprint.
The newest version!
/*
* Copyright (c) 1995-2013, The University of Sheffield. See the file
* COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
*
* This file is part of GATE (see http://gate.ac.uk/), and is free
* software, licenced under the GNU Library General Public License,
* Version 2, June 1991 (in the distribution as file licence.html,
* and also available at http://gate.ac.uk/gate/licence.html).
*
* Valentin Tablan 03/10/2001
*
* $Id: ResourceParametersEditor.java 20054 2017-02-02 06:44:12Z markagreenwood $
*
*/
package gate.gui;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import gate.DocumentFormat;
import gate.Factory;
import gate.FeatureMap;
import gate.Gate;
import gate.Resource;
import gate.corpora.DocumentImpl;
import gate.creole.Parameter;
import gate.creole.ResourceData;
import gate.creole.ResourceInstantiationException;
import gate.event.CreoleEvent;
import gate.event.CreoleListener;
import gate.swing.ResourceReferenceChooser;
import gate.swing.XJFileChooser;
import gate.swing.XJTable;
import gate.util.Err;
import gate.util.ExtensionFileFilter;
import gate.util.GateException;
import gate.util.GateRuntimeException;
import gate.util.NameBearer;
/**
* Allows the editing of a set of parameters for a resource. It needs a
* pointer to the resource and a list of the parameter names for the
* parameters that should be displayed. The list of the parameters is
* actually a list of lists of strings representing parameter
* disjunctions.
*/
@SuppressWarnings({"serial","rawtypes","unchecked"})
public class ResourceParametersEditor extends XJTable implements CreoleListener {
public ResourceParametersEditor() {
initLocalData();
initGuiComponents();
initListeners();
setSortable(true);
setSortedColumn(0);
setComparator(0, new ParameterDisjunctionComparator());
setTabSkipUneditableCell(true);
setEditCellAsSoonAsFocus(true);
}
public void init(Resource resource, ResourceData resourceData, List> parameters) {
cleanup();
this.resource = resource;
this.resourceData = resourceData;
if(parameters != null) {
parameterDisjunctions = new ArrayList(parameters.size());
for(int i = 0; i < parameters.size(); i++) {
parameterDisjunctions.add(new ParameterDisjunction(resource,
parameters.get(i)));
}
}
else {
parameterDisjunctions = null;
}
tableModel.fireTableDataChanged();
fileChooser = MainFrame.getFileChooser();
resourceReferenceChooser = MainFrame.getResourceReferenceChooser();
// must be saved now as it will be reset when the file chooser is hidden
fileChooserResource = (resource != null) ?
resource.getClass().getName() : fileChooser.getResource();
}
/**
* Initialises this GUI component.
*
* @param resource the resource for which the parameters need to be
* set.
* @param parameters a list of lists of {@link Parameter} representing
* parameter disjunctions.
*/
public void init(Resource resource, List> parameters) {
init(resource, null, parameters);
}
protected void initLocalData() {
resource = null;
parameterDisjunctions = null;
resourceData = null;
}// protected void initLocalData()
protected void initGuiComponents() {
setModel(tableModel = new ParametersTableModel());
getColumnModel().getColumn(0).setCellRenderer(
new ParameterDisjunctionRenderer());
getColumnModel().getColumn(2).setCellRenderer(new DefaultTableCellRenderer());
getColumnModel().getColumn(2).setCellRenderer(new BooleanRenderer());
getColumnModel().getColumn(3).setCellRenderer(new ParameterValueRenderer());
getColumnModel().getColumn(0).setCellEditor(
new ParameterDisjunctionEditor());
getColumnModel().getColumn(3).setCellEditor(new ParameterValueEditor());
setAutoResizeMode(AUTO_RESIZE_LAST_COLUMN);
setSurrendersFocusOnKeystroke(true);
}// protected void initGuiComponents()
protected void initListeners() {
Gate.getCreoleRegister().addCreoleListener(this);
}
/**
* Cleans the internal data and prepares this object to be collected
*/
public void cleanup() {
Gate.getCreoleRegister().removeCreoleListener(this);
if(parameterDisjunctions != null && parameterDisjunctions.size() > 0) {
for(int i = 0; i < parameterDisjunctions.size(); i++) {
parameterDisjunctions.get(i).cleanup();
}
}
resource = null;
resourceData = null;
}
/**
* Sets the parameters for the resource to their new values as
* resulted from the user's edits.
*/
public void setParameters() throws ResourceInstantiationException {
if(resource == null || parameterDisjunctions == null) return;
// stop current edits
if(getEditingColumn() != -1 && getEditingRow() != -1) {
editingStopped(new ChangeEvent(getCellEditor(getEditingRow(),
getEditingColumn())));
}
// set the parameters
for(int i = 0; i < parameterDisjunctions.size(); i++) {
ParameterDisjunction pDisj = parameterDisjunctions
.get(i);
resource.setParameterValue(pDisj.getName(), pDisj.getValue());
}
}
/**
* Does this GUI component allow editing?
*/
public Resource getResource() {
return resource;
}
/**
* Gets the current values for the parameters.
*
* @return a {@link FeatureMap} containing the curent values for the
* currently selected parameters in each disjunction.
*/
public FeatureMap getParameterValues() {
// stop current edits
if(getEditingColumn() != -1 && getEditingRow() != -1) {
editingStopped(new ChangeEvent(getCellEditor(getEditingRow(),
getEditingColumn())));
}
// get the parameters
FeatureMap values = Factory.newFeatureMap();
if(parameterDisjunctions != null) {
for(int i = 0; i < parameterDisjunctions.size(); i++) {
ParameterDisjunction pDisj = parameterDisjunctions.get(i);
values.put(pDisj.getName(), pDisj.getValue());
}
}
return values;
}
@Override
public void resourceLoaded(CreoleEvent e) {
repaint();
}
@Override
public void resourceUnloaded(CreoleEvent e) {
repaint();
}
@Override
public void resourceRenamed(Resource resource, String oldName, String newName) {
repaint();
}
@Override
public void datastoreOpened(CreoleEvent e) {
}
@Override
public void datastoreCreated(CreoleEvent e) {
}
@Override
public void datastoreClosed(CreoleEvent e) {
}
public void setEditable(boolean editable) {
this.editable = editable;
}
public boolean isEditable() {
return editable;
}
/**
* Called by other GUI classes that use this as a subcomponent that
* doesn't need to update with the creole register changes.
*/
void removeCreoleListenerLink() {
// this component is only used as a viewer now; it doesn't need to
// update
// so we don't need to listen to creole events
Gate.getCreoleRegister().removeCreoleListener(this);
if(parameterDisjunctions != null && parameterDisjunctions.size() > 0) {
for(int i = 0; i < parameterDisjunctions.size(); i++) {
parameterDisjunctions.get(i).removeCreoleListenerLink();
}
}
}
ParametersTableModel tableModel;
Resource resource;
ResourceData resourceData;
/**
* A pointer to the filechooser from MainFrame.
*/
static XJFileChooser fileChooser;
/**
* A pointer to the RR chooser from MainFrame.
*/
static ResourceReferenceChooser resourceReferenceChooser;
String fileChooserResource;
/**
* A list of {@link ParameterDisjunction}
*/
protected List parameterDisjunctions;
protected boolean editable = true;
// inner classes
protected class ParametersTableModel extends AbstractTableModel {
@Override
public int getColumnCount() {
return 4;
}
@Override
public Class> getColumnClass(int columnIndex) {
switch(columnIndex) {
case 0:
return ParameterDisjunction.class;
case 1:
return String.class;
case 2:
return Boolean.class;
case 3:
return Object.class;
default:
return Object.class;
}
}// public Class getColumnClass(int columnIndex)
@Override
public String getColumnName(int columnIndex) {
switch(columnIndex) {
case 0:
return "Name";
case 1:
return "Type";
case 2:
return "Required";
case 3:
return "Value";
default:
return "?";
}
}// public String getColumnName(int columnIndex)
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
switch(columnIndex) {
case 0:
return parameterDisjunctions.get(rowIndex).size() > 1;
case 1:
return false;
case 2:
return false;
case 3:
return editable;
default:
return false;
}
}// public boolean isCellEditable
@Override
public int getRowCount() {
return (parameterDisjunctions == null) ? 0 : parameterDisjunctions.size();
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
ParameterDisjunction pDisj = parameterDisjunctions.get(rowIndex);
switch(columnIndex) {
case 0:
return pDisj;
case 1:
String paramType = pDisj.getType();
return paramType.substring(paramType.lastIndexOf('.') + 1);
case 2:
return pDisj.isRequired();
case 3:
return pDisj.getValue();
default:
return "?";
}
}// public Object getValueAt
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
ParameterDisjunction pDisj = parameterDisjunctions.get(rowIndex);
switch(columnIndex) {
case 0: {
if(aValue instanceof ParameterDisjunction){
//do nothing
} else if (aValue instanceof Integer){
pDisj.setSelectedIndex((Integer) aValue);
}
break;
}
case 1: {
break;
}
case 2: {
break;
}
case 3: {
Object oldValue = pDisj.getValue();
if (!Objects.equals(oldValue, aValue)) {
pDisj.setValue(aValue);
if (ResourceParametersEditor.this == null || ResourceParametersEditor.this.resource == null) break;
try {
ResourceParametersEditor.this.resource.setParameterValue(pDisj.getName(), pDisj.getValue());
} catch(ResourceInstantiationException e) {
e.printStackTrace();
}
}
break;
}
default: {
}
}
tableModel.fireTableCellUpdated(rowIndex, columnIndex);
}// public void setValueAt
}// /class FeaturesTableModel extends DefaultTableModel
class ParameterDisjunctionRenderer extends DefaultTableCellRenderer {
public ParameterDisjunctionRenderer() {
combo = new JComboBox();
class CustomRenderer extends JLabel implements ListCellRenderer {
@Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
setText(text);
setIcon(icon);
return this;
}
}
combo.setRenderer(new CustomRenderer());
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (table == null || value == null) {
// for some reason we have a null value (unlikely a table) which causes an NPE if
// we don't check for it. Problem is what do we do if we have no value?
// current solution is to return whatever the renderer was last time, which may
// or may not be correct. In practice it seems to work okay.
// this was intended as a fix for
// https://github.com/GateNLP/gate-core/issues/98
return this;
}
ParameterDisjunction pDisj = (ParameterDisjunction)value;
text = pDisj.getName();
String type = pDisj.getType();
//iconName = "param";
if(Gate.isGateType(type)) {
ResourceData rData = Gate.getCreoleRegister().get(type);
if(rData != null) icon = MainFrame.getIcon(rData.getIcon(),rData.getResourceClassLoader());
}
if(pDisj.size() > 1) {
combo.setModel(new DefaultComboBoxModel(new Object[] {text}));
return combo;
}
// prepare the renderer
super.getTableCellRendererComponent(table, text, isSelected,
hasFocus, row, column);
if (icon == null) {
icon = MainFrame.getIcon("param");
}
setIcon(icon);
return this;
}// public Component getTableCellRendererComponent
// combobox used for OR parameters
JComboBox combo;
//String iconName;
Icon icon = null;
String text;
}// class ParameterDisjunctionRenderer
/**
* A renderer that displays a File Open button next to a text field.
* Used for setting URLs from files.
*/
class ParameterValueRenderer extends DefaultTableCellRenderer {
public ParameterValueRenderer() {
fileButton = new JButton(MainFrame.getIcon("open-file"));
fileButton.setToolTipText("Browse the file system");
listButton = new JButton(MainFrame.getIcon("edit-list"));
listButton.setToolTipText("Edit the list");
fmButton = new JButton(MainFrame.getIcon("edit-list"));
fmButton.setToolTipText("Edit the feature map");
textField = new JTextField(){
@Override
public Dimension getMinimumSize() {
//we don't want to be squashed!
Dimension size = getPreferredSize();
if(size.width < 300) {
size.width = 300;
}
// we should not be larger than the screen
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
if(size.width > 0.95 * screenSize.width) {
size.width = (int)0.95 * screenSize.width;
}
return size;
}
};
textButtonBox = new JPanel();
textButtonBox.setLayout(new BoxLayout(textButtonBox, BoxLayout.X_AXIS));
textButtonBox.setOpaque(false);
combo = new JComboBox();
combo.setRenderer(new ResourceRenderer());
}// CustomObjectRenderer()
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
ParameterDisjunction pDisj = (ParameterDisjunction)table
.getValueAt(row, convertColumnIndexToView(0));
String type = pDisj.getType();
// set the tooltip
combo.setToolTipText(pDisj.getComment());
textField.setToolTipText(pDisj.getComment());
textButtonBox.setToolTipText(pDisj.getComment());
if(Gate.isGateType(type)) {
// Gate type
if(ResourceParametersEditor.this.isEditable()) {
combo.setModel(new DefaultComboBoxModel(new Object[] {value == null
? ""
: value}));
return combo;
}
else {
// not editable; we'll just use the text field
// prepare the renderer
String text = value == null ? "" : value.toString();
// super.getTableCellRendererComponent(table, text,
// isSelected,
// hasFocus, row, column);
textField.setText(text);
return textField;
}
}
else {
Class> typeClass = null;
try {
// load type class through GATE classloader
typeClass = Class.forName(type, true, Gate.getClassLoader());
}
catch(ClassNotFoundException cnfe) {
cnfe.printStackTrace();
}
// non Gate type -> we'll use the text field
String text = (value == null)
? ""
: value.toString();
// prepare the renderer
textField.setText(text);
// super.getTableCellRendererComponent(table, text, isSelected,
// hasFocus, row, column);
if(type.equals("java.net.URL") || type.equals("gate.creole.ResourceReference")) {
if(ResourceParametersEditor.this.isEditable()) {
textButtonBox.removeAll();
textField.setText(text);
// textButtonBox.add(this);
textButtonBox.add(textField);
// this.setMaximumSize(new Dimension(Integer.MAX_VALUE,
// getPreferredSize().height));
textButtonBox.add(Box.createHorizontalStrut(5));
textButtonBox.add(fileButton);
return textButtonBox;
}
else {
// return this;
return textField;
}
}
else if(typeClass != null
&& Collection.class.isAssignableFrom(typeClass)) {
// List value
// setText(textForList((List)value));
textField.setText(textForList((Collection>)value));
if(ResourceParametersEditor.this.isEditable()) {
textButtonBox.removeAll();
// textButtonBox.add(this);
textButtonBox.add(textField);
// this.setMaximumSize(new Dimension(Integer.MAX_VALUE,
// getPreferredSize().height));
textButtonBox.add(Box.createHorizontalStrut(5));
textButtonBox.add(listButton);
return textButtonBox;
}
}
else if(typeClass != null
&& FeatureMap.class.isAssignableFrom(typeClass)) {
textField.setText(textForFeatureMap((FeatureMap)value));
if(ResourceParametersEditor.this.isEditable()) {
textButtonBox.removeAll();
textButtonBox.add(textField);
textButtonBox.add(Box.createHorizontalStrut(5));
textButtonBox.add(fmButton);
return textButtonBox;
}
}
else if(typeClass != null && typeClass.isEnum()) {
if(ResourceParametersEditor.this.isEditable()) {
combo.setModel(new DefaultComboBoxModel(new Object[] {value == null
? ""
: value}));
return combo;
}
else {
return textField;
}
}
else {
// return this;
return textField;
}
// not actually reachable, but keeps the compiler happy
return textField;
}
}// public Component getTableCellRendererComponent
JButton fileButton;
JButton listButton;
JButton fmButton;
JComboBox combo;
JPanel textButtonBox;
JTextField textField;
}// class ObjectRenderer extends DefaultTableCellRenderer
class ParameterDisjunctionComparator implements Comparator {
@Override
public int compare(ParameterDisjunction pDisj1, ParameterDisjunction pDisj2) {
return pDisj1.getName().compareTo(pDisj2.getName());
}
}
class ParameterDisjunctionEditor extends DefaultCellEditor {
public ParameterDisjunctionEditor() {
super(new JComboBox());
combo = (JComboBox)super.getComponent();
class CustomRenderer extends JLabel implements ListCellRenderer {
public CustomRenderer() {
setOpaque(true);
}
@Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
if(isSelected) {
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
}
else {
setBackground(list.getBackground());
setForeground(list.getForeground());
}
setFont(list.getFont());
setText((String)value);
setIcon(MainFrame.getIcon("param"));
Parameter[] params = pDisj.getParameters();
for(int i = 0; i < params.length; i++) {
Parameter param = params[i];
if(param.getName().equals(value)) {
String type = param.getTypeName();
if(Gate.getCreoleRegister().containsKey(type)) {
ResourceData rData = Gate.getCreoleRegister()
.get(type);
if(rData != null)
setIcon(MainFrame.getIcon(rData.getIcon(),
rData.getResourceClassLoader()));
}
break;
}// if(params[i].getName().equals(value))
}// for(int i = 0; params.length; i++)
return this;
}
} // class CustomRenderer extends JLabel implements
// ListCellRenderer
combo.setRenderer(new CustomRenderer());
combo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
pDisj.setSelectedIndex(combo.getSelectedIndex());
stopCellEditing();
}
});
}// public ParameterDisjunctionEditor()
@Override
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
pDisj = (ParameterDisjunction)value;
DefaultComboBoxModel comboModel = new DefaultComboBoxModel(pDisj.getNames());
combo.setModel(comboModel);
combo.setSelectedIndex(pDisj.getSelectedIndex());
return combo;
}// public Component getTableCellEditorComponent
@Override
public Object getCellEditorValue() {
pDisj.setSelectedIndex(combo.getSelectedIndex());
// return combo.getSelectedIndex();
return pDisj;
}
@Override
public boolean stopCellEditing() {
combo.hidePopup();
return super.stopCellEditing();
}
JComboBox combo;
ParameterDisjunction pDisj;
}// class ParameterDisjunctionEditor extends DefaultCellEditor
class ParameterValueEditor extends AbstractCellEditor implements
TableCellEditor {
ParameterValueEditor() {
combo = new JComboBox();
combo.setRenderer(new ResourceRenderer());
combo.setEditable(false);
textField = new JTextField(20);
fileButton = new JButton(MainFrame.getIcon("open-file"));
fileButton.setToolTipText("Browse the file system");
fileButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
fileChooser.setDialogTitle("Select a file");
fileChooser.setResource(fileChooserResource);
int res = fileChooser.showOpenDialog(ResourceParametersEditor.this);
if(res == JFileChooser.APPROVE_OPTION) {
try {
textField.setText(fileChooser.getSelectedFile().toURI().toURL()
.toExternalForm());
}
catch(IOException ioe) {
ioe.printStackTrace();
}
fireEditingStopped();
}
else {
fireEditingCanceled();
}
}
});
rrButton = new JButton(MainFrame.getIcon("open-file"));
rrButton.setToolTipText("Browse the file system and plugins");
rrButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
resourceReferenceChooser.setResource(fileChooserResource);
String uri = textField.getText();
if(uri != null && !"".equals(uri)) {
resourceReferenceChooser.setSelectedResource(uri);
}
uri = resourceReferenceChooser.showDialog(
findWindow(ResourceParametersEditor.this),
"Select a file");
if(uri != null) {
textField.setText(uri);
fireEditingStopped();
}
else {
fireEditingCanceled();
}
}
});
listButton = new JButton(MainFrame.getIcon("edit-list"));
listButton.setToolTipText("Edit the list");
listButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
List> returnedList = listEditor.showDialog();
if(returnedList != null) {
listValue = returnedList;
fireEditingStopped();
}
else {
fireEditingCanceled();
}
}
});
fmButton = new JButton(MainFrame.getIcon("edit-list"));
fmButton.setToolTipText("Edit the feature map");
fmButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
FeatureMap returnedFM = fmEditor.showDialog();
if(returnedFM != null) {
fmValue = returnedFM;
fireEditingStopped();
}
else {
fireEditingCanceled();
}
}
});
textButtonBox = new JPanel();
textButtonBox.setLayout(new BoxLayout(textButtonBox, BoxLayout.X_AXIS));
textButtonBox.setOpaque(false);
textFieldBoolean = new JTextField();
textFieldBoolean.setEditable(false);
textFieldBoolean.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
Boolean value = Boolean.valueOf(textFieldBoolean.getText());
value = !value;
textFieldBoolean.setText(value.toString());
}
});
textFieldBoolean.addKeyListener(new KeyAdapter() {
@Override
public void keyTyped(KeyEvent e) {
Boolean value = Boolean.valueOf(textFieldBoolean.getText());
value = !value;
textFieldBoolean.setText(value.toString());
}
});
textButtonBox.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent e) {
if(!comboUsed) {
// needed because the focus would otherwise stay
// on the textButtonBox panel
textField.requestFocusInWindow();
}
}
});
// select the opposite element when tab key is pressed
textField.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
JTextField textField = (JTextField) e.getSource();
if((e.getKeyCode() == KeyEvent.VK_TAB)
&& textField.getParent().getComponentCount() == 3) {
textField.getParent().getComponent(2).requestFocusInWindow();
e.consume();
}
}
});
}// ParameterValueEditor()
@Override
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
comboUsed = false;
listUsed = false;
fmUsed = false;
ParameterDisjunction pDisj = (ParameterDisjunction)table
.getValueAt(row, convertColumnIndexToView(0));
type = pDisj.getType();
// set the tooltip
combo.setToolTipText(pDisj.getComment());
textField.setToolTipText(pDisj.getComment());
textFieldBoolean.setToolTipText(pDisj.getComment());
if(Gate.isGateType(type)) {
// Gate type
comboUsed = true;
ArrayList