| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package org.apache.uima.taeconfigurator.editors.ui; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Comparator; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.TreeMap; |
| |
| import org.apache.uima.analysis_engine.TypeOrFeature; |
| import org.apache.uima.analysis_engine.impl.TypeOrFeature_impl; |
| import org.apache.uima.analysis_engine.metadata.SofaMapping; |
| import org.apache.uima.cas.Type; |
| import org.apache.uima.resource.metadata.Capability; |
| import org.apache.uima.taeconfigurator.InternalErrorCDE; |
| import org.apache.uima.taeconfigurator.editors.MultiPageEditor; |
| import org.apache.uima.taeconfigurator.editors.ui.dialogs.AddCapabilityFeatureDialog; |
| import org.apache.uima.taeconfigurator.editors.ui.dialogs.AddCapabilityTypeDialog; |
| import org.apache.uima.taeconfigurator.editors.ui.dialogs.AddSofaDialog; |
| import org.apache.uima.taeconfigurator.editors.ui.dialogs.CommonInputDialog; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jface.window.Window; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.TableTree; |
| import org.eclipse.swt.custom.TableTreeItem; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Event; |
| import org.eclipse.swt.widgets.Table; |
| import org.eclipse.swt.widgets.TableColumn; |
| import org.eclipse.ui.forms.IManagedForm; |
| |
| public class CapabilitySection extends AbstractSection { |
| |
| private final static String CAPABILITY_SET = "Set"; |
| |
| private final static String INPUT = "Input"; |
| |
| private final static String OUTPUT = "Output"; |
| |
| public final static String ALL_FEATURES = "<all features>"; |
| |
| private final static String TYPE_TITLE = "Type:"; |
| |
| private final static String FEAT_TITLE = "F:"; // not shown, in data field |
| |
| private final static String NAME_TITLE = "Name "; |
| |
| private final static String NAMESPACE_TITLE = "Name Space"; |
| |
| private final static String LANGS_TITLE = "Languages"; |
| |
| private final static String LANG_TITLE = "L:"; // not shown, in datafield |
| |
| private final static String SOFAS_TITLE = "Sofas"; |
| |
| private final static String SOFA_TITLE = "S:"; // not shown, in data field |
| |
| private final static int CS = 1; |
| |
| private final static int TYPE = 1 << 1; |
| |
| private final static int FEAT = 1 << 2; |
| |
| private final static int LANG = 1 << 3; |
| |
| private final static int LANG_ITEM = 1 << 4; |
| |
| private final static int SOFA = 1 << 5; |
| |
| private final static int SOFA_ITEM = 1 << 6; |
| |
| public final static int TITLE_COL = 0; |
| |
| public final static int NAME_COL = 1; |
| |
| public final static int INPUT_COL = 2; |
| |
| public final static int OUTPUT_COL = 3; |
| |
| public final static int NAMESPACE_COL = 4; |
| |
| TableTree tt; // for inner class access |
| |
| private Button addCapabilityButton; |
| |
| private Button addLangButton; |
| |
| private Button addTypeButton; |
| |
| private Button addSofaButton; |
| |
| private Button addEditFeatureButton; |
| |
| private Button editButton; |
| |
| private Button removeButton; |
| |
| private Map typeInfo; |
| |
| private SofaMapSection sofaMapSection; |
| |
| public CapabilitySection(MultiPageEditor aEditor, Composite parent) { |
| super( |
| aEditor, |
| parent, |
| "Component Capabilities", |
| "This section describes the languages handled, and the inputs needed and outputs provided in terms of the Types and Features."); |
| } |
| |
| public void initialize(IManagedForm form) { |
| super.initialize(form); |
| |
| Composite sectionClient = new2ColumnComposite(getSection()); |
| enableBorders(sectionClient); |
| toolkit.paintBordersFor(sectionClient); |
| |
| tt = newTableTree(sectionClient, SWT.V_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION); |
| Table table = tt.getTable(); |
| |
| // work around for bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=65865 |
| new TableColumn(table, SWT.NONE).setText(" "); |
| |
| newTableColumn(table, SWT.NONE).setText(NAME_TITLE); // type or feat name |
| newTableColumn(table, SWT.NONE).setText(INPUT); |
| newTableColumn(table, SWT.NONE).setText(OUTPUT); |
| newTableColumn(table, SWT.NONE).setText(NAMESPACE_TITLE); // rest of typename |
| table.setHeaderVisible(true); |
| table.setLinesVisible(true); |
| tt.addListener(SWT.MouseHover, this); // to show description |
| |
| final Composite buttonContainer = newButtonContainer(sectionClient); |
| addCapabilityButton = newPushButton( |
| buttonContainer, |
| "Add Capability Set", |
| "Analysis Engines can have one or more sets of capabilities; each one describes a set of outputs that are produced, given a particular set of inputs. Click here to add a capability set."); |
| addLangButton = newPushButton(buttonContainer, "Add Language", |
| "Click here to add a Language Capability to the selected set."); |
| addTypeButton = newPushButton(buttonContainer, "Add Type", |
| "Click here to add a Type to the selected capability set."); |
| addSofaButton = newPushButton(buttonContainer, "Add Sofa", |
| "Click here to add a Subject of Analysis (Sofa) to the selected capability set."); |
| addEditFeatureButton = newPushButton(buttonContainer, "Add/Edit Features", |
| "Click here to specify the features of a selected type as input or output"); |
| editButton = newPushButton(buttonContainer, S_EDIT, |
| "Edit the selected item. You can also double-click the item to edit it."); |
| removeButton = newPushButton(buttonContainer, "Remove", |
| "Remove the selected item. You can also press the Delete key to remove an item."); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ui.forms.IFormPart#refresh() |
| */ |
| public void refresh() { |
| super.refresh(); |
| sofaMapSection = editor.getCapabilityPage().getSofaMapSection(); |
| tt.getParent().setRedraw(false); |
| tt.removeAll(); |
| |
| Capability[] cs = getCapabilities(); |
| if (null != cs) { |
| for (int i = 0; i < cs.length; i++) { |
| TableTreeItem item = new TableTreeItem(tt, SWT.NONE); |
| item.setText(TITLE_COL, CAPABILITY_SET); |
| item.setData(cs[i]); |
| tt.setSelection(new TableTreeItem[] { item }); // set default selection |
| fillCapability(item, cs[i]); |
| // if (0 == i) { |
| item.setExpanded(true); |
| TableTreeItem[] types = item.getItems(); |
| if (types != null) |
| for (int j = 0; j < types.length; j++) { |
| types[j].setExpanded(true); |
| } |
| // } |
| } |
| } |
| packTable(tt.getTable()); |
| enable(); |
| tt.getParent().setRedraw(true); |
| } |
| |
| /** |
| * value of hash table keyed on type name |
| */ |
| private static class TypeCapability { |
| boolean isInputType; // true if mentioned in <type> |
| |
| boolean isOutputType; // true if mentioned in <type> |
| |
| Map features = new TreeMap(); |
| } |
| |
| private static class FeatureCapability { |
| boolean isInputFeature = false; |
| |
| boolean isOutputType = false; |
| |
| boolean isOutputUpdate = false; |
| } |
| |
| private TableTreeItem createLanguageHeaderGui(TableTreeItem parent) { |
| TableTreeItem langHdr = new TableTreeItem(parent, SWT.NONE); |
| langHdr.setText(TITLE_COL, LANGS_TITLE); |
| langHdr.setData(LANGS_TITLE); |
| return langHdr; |
| } |
| |
| private TableTreeItem createSofaHeaderGui(TableTreeItem parent) { |
| TableTreeItem sofaHdr = new TableTreeItem(parent, SWT.NONE); |
| sofaHdr.setText(TITLE_COL, SOFAS_TITLE); |
| sofaHdr.setData(SOFAS_TITLE); |
| return sofaHdr; |
| } |
| |
| private void fillCapability(TableTreeItem parent, Capability c) { |
| // first output language capabilities |
| TableTreeItem langHdr = createLanguageHeaderGui(parent); |
| String[] languages = c.getLanguagesSupported(); |
| if (null != languages) { |
| for (int i = 0; i < languages.length; i++) { |
| TableTreeItem lItem = new TableTreeItem(langHdr, SWT.NONE); |
| lItem.setData(LANG_TITLE); |
| lItem.setText(NAME_COL, languages[i]); |
| } |
| } |
| |
| // second, output Sofas |
| TableTreeItem sofaHdr = createSofaHeaderGui(parent); |
| String[] inputSofaNames = c.getInputSofas(); |
| String[] outputSofaNames = c.getOutputSofas(); |
| Arrays.sort(inputSofaNames); |
| Arrays.sort(outputSofaNames); |
| for (int i = 0; i < inputSofaNames.length; i++) { |
| TableTreeItem item = new TableTreeItem(sofaHdr, SWT.NONE); |
| setGuiSofaName(item, inputSofaNames[i], true); |
| } |
| for (int i = 0; i < outputSofaNames.length; i++) { |
| TableTreeItem item = new TableTreeItem(sofaHdr, SWT.NONE); |
| setGuiSofaName(item, outputSofaNames[i], false); |
| } |
| |
| // scan capability, collecting for each type: |
| // inputs, outputs, updatesToInputs(features) |
| // (updatesToInputs are output features without corresponding output type) |
| // <noFeatures>, or <allFeatures> or feature set |
| // For each item, generate minimal number of Type items: |
| |
| TypeCapability tc = null; |
| FeatureCapability fc; |
| TypeOrFeature[] inputs = c.getInputs(); |
| TypeOrFeature[] outputs = c.getOutputs(); |
| typeInfo = new TreeMap(); |
| |
| if (null != inputs) { |
| for (int i = 0; i < inputs.length; i++) { |
| String name = inputs[i].getName(); |
| if (inputs[i].isType()) { |
| tc = getTypeCapability(name); |
| tc.isInputType = true; |
| if (inputs[i].isAllAnnotatorFeatures()) { |
| fc = getFeatureCapability(tc, ALL_FEATURES); |
| fc.isInputFeature = true; |
| } |
| } else { |
| tc = getTypeCapability(getTypeNameFromFullFeatureName(name)); // create a typecapability |
| // if one doesn't exist |
| fc = getFeatureCapability(tc, getShortFeatureName(name)); |
| fc.isInputFeature = true; |
| } |
| } |
| } |
| |
| if (null != outputs) { |
| for (int i = 0; i < outputs.length; i++) { |
| String name = outputs[i].getName(); |
| if (outputs[i].isType()) { |
| tc = getTypeCapability(name); |
| tc.isOutputType = true; |
| if (outputs[i].isAllAnnotatorFeatures()) { |
| fc = getFeatureCapability(tc, ALL_FEATURES); |
| fc.isOutputType = true; |
| } |
| } else { |
| tc = getTypeCapability(getTypeNameFromFullFeatureName(name)); |
| fc = getFeatureCapability(tc, getShortFeatureName(name)); |
| fc.isOutputUpdate = true; |
| } |
| } |
| } |
| |
| for (Iterator it = typeInfo.entrySet().iterator(); it.hasNext();) { |
| Map.Entry entry = (Map.Entry) it.next(); |
| String typeName = (String) entry.getKey(); |
| tc = (TypeCapability) entry.getValue(); |
| |
| TableTreeItem item = new TableTreeItem(parent, SWT.NONE); |
| setGuiTypeName(item, typeName); |
| if (tc.isInputType) |
| item.setText(INPUT_COL, INPUT); |
| if (tc.isOutputType) |
| item.setText(OUTPUT_COL, OUTPUT); |
| |
| for (Iterator fit = tc.features.entrySet().iterator(); fit.hasNext();) { |
| Map.Entry fEntry = (Map.Entry) fit.next(); |
| String featName = (String) fEntry.getKey(); |
| fc = (FeatureCapability) fEntry.getValue(); |
| |
| TableTreeItem fItem = new TableTreeItem(item, SWT.NONE); |
| fItem.setData(FEAT_TITLE); |
| fItem.setText(NAME_COL, featName); |
| if (fc.isInputFeature) |
| fItem.setText(INPUT_COL, INPUT); |
| if (fc.isOutputUpdate || fc.isOutputType) { |
| fItem.setText(OUTPUT_COL, OUTPUT); |
| } |
| } |
| } |
| } |
| |
| private void setGuiTypeName(TableTreeItem item, String typeName) { |
| item.setText(TITLE_COL, TYPE_TITLE); |
| item.setText(NAME_COL, getShortName(typeName)); |
| item.setText(NAMESPACE_COL, getNameSpace(typeName)); |
| } |
| |
| private void setGuiSofaName(TableTreeItem item, String sofaName, boolean isInput) { |
| item.setData(SOFA_TITLE); |
| item.setText(NAME_COL, sofaName); |
| if (isInput) { |
| item.setText(INPUT_COL, INPUT); |
| item.setText(OUTPUT_COL, ""); |
| } else { |
| item.setText(OUTPUT_COL, OUTPUT); |
| item.setText(INPUT_COL, ""); |
| } |
| } |
| |
| private TypeCapability getTypeCapability(String typeName) { |
| TypeCapability typeCapability = (TypeCapability) typeInfo.get(typeName); |
| if (null == typeCapability) { |
| typeInfo.put(typeName, typeCapability = new TypeCapability()); |
| } |
| return typeCapability; |
| } |
| |
| private FeatureCapability getFeatureCapability(TypeCapability tc, String featureShortName) { |
| FeatureCapability fc = (FeatureCapability) tc.features.get(featureShortName); |
| if (null == fc) { |
| tc.features.put(featureShortName, fc = new FeatureCapability()); |
| } |
| return fc; |
| } |
| |
| public String getTypeNameFromFullFeatureName(String name) { |
| return (name.substring(0, name.indexOf(":"))); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.uima.taeconfigurator.editors.ui.AbstractTableSection#handleEvent(org.eclipse.swt.widgets.Event) |
| */ |
| public void handleEvent(Event event) { |
| if (event.type == SWT.Expand || event.type == SWT.Collapse) { |
| pack04(); |
| return; |
| } |
| if (event.widget == addCapabilityButton) { |
| handleAddCapability(); |
| enable(); |
| return; |
| } |
| |
| TableTreeItem selItem = tt.getSelection()[0]; |
| int itemKind = getItemKind(selItem); |
| |
| if (event.widget == addLangButton) { |
| handleAddLang(selItem, itemKind); |
| } else if (event.widget == addTypeButton) { |
| handleAddType(selItem, itemKind); |
| } else if (event.widget == addSofaButton) { |
| handleAddSofa(selItem, itemKind); |
| } else if (event.widget == addEditFeatureButton) { |
| handleAddEditFeature(selItem, itemKind); |
| } else if (event.widget == editButton || event.type == SWT.MouseDoubleClick) { |
| handleEdit(selItem, itemKind); |
| } else if (event.widget == removeButton |
| || (event.widget == tt.getTable() && event.type == SWT.KeyUp && event.character == SWT.DEL)) { |
| handleRemove(selItem, itemKind); |
| } |
| |
| enable(); |
| } |
| |
| private void handleAddCapability() { |
| Capability newCset = addCapabilitySet(); |
| |
| // update the GUI |
| TableTreeItem item = new TableTreeItem(tt, SWT.NONE); |
| item.setText(CAPABILITY_SET); |
| item.setData(newCset); |
| createLanguageHeaderGui(item); |
| createSofaHeaderGui(item); |
| |
| item.setExpanded(true); |
| tt.setSelection(new TableTreeItem[] { item }); |
| if (tt.getItemCount() == 1) |
| tt.getTable().getColumn(TITLE_COL).pack(); |
| finishAction(); |
| } |
| |
| private void getOrCreateAllFeatItem(TableTreeItem editItem, int column, String inOrOut) { |
| TableTreeItem allFeatItem = getAllFeatItem(editItem); |
| if (null == allFeatItem) { |
| allFeatItem = new TableTreeItem(editItem, SWT.NONE, 0); |
| allFeatItem.setData(FEAT_TITLE); |
| allFeatItem.setText(NAME_COL, ALL_FEATURES); |
| } |
| allFeatItem.setText(column, inOrOut); |
| } |
| |
| private TableTreeItem getAllFeatItem(TableTreeItem editItem) { |
| TableTreeItem[] subItems = editItem.getItems(); |
| if (null == subItems || subItems.length == 0) |
| return null; |
| TableTreeItem item = subItems[0]; |
| if (ALL_FEATURES.equals(item.getText(NAME_COL))) |
| return item; |
| return null; |
| } |
| |
| private void removeAllFeatItemGui(TableTreeItem editItem, int column) { |
| TableTreeItem allFeatItem = getAllFeatItem(editItem); |
| if (null == allFeatItem) |
| // throw new InternalErrorCDE("invalid state"); |
| return; // happens when no allfeat is set |
| allFeatItem.setText(column, ""); |
| String otherCol = allFeatItem.getText((column == INPUT_COL) ? OUTPUT_COL : INPUT_COL); |
| if (null == otherCol || "".equals(otherCol)) |
| allFeatItem.dispose(); |
| } |
| |
| private void handleEdit(TableTreeItem editItem, int itemKind) { |
| Capability c = getCapability(editItem); |
| switch (itemKind) { |
| case SOFA_ITEM: { |
| boolean existingIsInput = INPUT.equals(editItem.getText(INPUT_COL)); |
| String existingSofaName = editItem.getText(NAME_COL); |
| AddSofaDialog dialog = new AddSofaDialog(this, c, existingSofaName, existingIsInput); |
| if (dialog.open() == Window.CANCEL) |
| return; |
| |
| if (dialog.isInput == existingIsInput && dialog.sofaName.equals(existingSofaName)) |
| return; |
| |
| // MODEL UPDATING |
| // if rename, |
| // update entry or remove / add entry |
| // DO FOR ALL INSTANCES IN ALL CAPABILITY SETS. |
| // change name in all mappings |
| // if switch from input to output, delete from one array, add to other, |
| // mappings: no change (maybe the user switches the other items too). |
| if (Window.CANCEL == Utility |
| .popOkCancel( |
| "Confirm Change to all Capability Sets", |
| "This edit operation will change the Sofa in all Capability Sets in which it is defined. Please confirm.", |
| MessageDialog.WARNING)) |
| return; |
| final Capability[] cSets = getCapabilities(); |
| for (int i = 0; i < cSets.length; i++) { |
| boolean wasRemoved; |
| String[] prevSofas; |
| if (existingIsInput) { |
| cSets[i].setInputSofas((String[]) Utility.removeElementsFromArray(prevSofas = cSets[i] |
| .getInputSofas(), existingSofaName, String.class)); |
| wasRemoved = prevSofas != cSets[i].getInputSofas(); |
| } else { |
| cSets[i].setOutputSofas((String[]) Utility.removeElementsFromArray(prevSofas = cSets[i] |
| .getOutputSofas(), existingSofaName, String.class)); |
| wasRemoved = prevSofas != cSets[i].getOutputSofas(); |
| } |
| if (wasRemoved) { |
| if (dialog.isInput) { |
| cSets[i].setInputSofas(stringArrayAdd(cSets[i].getInputSofas(), dialog.sofaName)); |
| } else { |
| cSets[i].setOutputSofas(stringArrayAdd(cSets[i].getOutputSofas(), dialog.sofaName)); |
| } |
| } |
| } |
| if (!dialog.sofaName.equals(existingSofaName)) { |
| // rename in mappings |
| SofaMapping[] mappings = getSofaMappings(); |
| for (int i = 0; i < mappings.length; i++) { |
| if (existingSofaName.equals(mappings[i].getAggregateSofaName())) { |
| mappings[i].setAggregateSofaName(dialog.sofaName); |
| } |
| } |
| } |
| |
| // GUI updating: |
| // setGuiSofaName(editItem, dialog.sofaName, dialog.isInput); |
| refresh(); // because multiple capability sets may have changed |
| sofaMapSection.markStale(); |
| finishAction(); |
| pack04(); |
| break; |
| } |
| case TYPE: { |
| AddCapabilityTypeDialog dialog = new AddCapabilityTypeDialog(this, c, editItem); |
| if (dialog.open() == Window.CANCEL) |
| return; |
| |
| TypeOrFeature typeInput = getTypeOrFeature(c.getInputs(), getFullyQualifiedName(editItem)); |
| |
| if (dialog.inputs[0]) { |
| if (null == typeInput) { |
| c.addInputType(dialog.types[0], true); |
| // add all-features |
| getOrCreateAllFeatItem(editItem, INPUT_COL, INPUT); |
| } |
| } else if (null != typeInput) { // check for any input features done in dialog |
| c.setInputs(typeOrFeatureArrayRemove(c.getInputs(), typeInput)); |
| removeAllFeatItemGui(editItem, INPUT_COL); |
| } |
| |
| TypeOrFeature typeOutput = getTypeOrFeature(c.getOutputs(), getFullyQualifiedName(editItem)); |
| |
| if (dialog.outputs[0]) { |
| if (null == typeOutput) { |
| c.addOutputType(dialog.types[0], true); |
| getOrCreateAllFeatItem(editItem, OUTPUT_COL, OUTPUT); |
| } |
| } else if (null != typeOutput) { |
| c.setOutputs(typeOrFeatureArrayRemove(c.getOutputs(), typeOutput)); |
| removeAllFeatItemGui(editItem, OUTPUT_COL); |
| } |
| |
| if (dialog.inputs[0] || dialog.outputs[0]) { |
| editItem.setText(INPUT_COL, dialog.inputs[0] ? INPUT : ""); |
| editItem.setText(OUTPUT_COL, dialog.outputs[0] ? OUTPUT : ""); |
| } else { |
| editItem.dispose(); |
| pack04(); |
| } |
| finishAction(); |
| break; |
| } |
| case LANG_ITEM: { |
| CommonInputDialog dialog = new CommonInputDialog( |
| this, |
| "Edit Language", |
| "Enter a two letter ISO-639 language code, followed optionally by a two-letter ISO-3166 country code (Examples: fr or fr-CA)", |
| CommonInputDialog.LANGUAGE, editItem.getText(NAME_COL)); |
| if (dialogForLanguage(c, dialog) == Window.CANCEL) |
| return; |
| c.getLanguagesSupported()[getIndex(editItem)] = dialog.getValue(); |
| // update GUI |
| editItem.setText(NAME_COL, dialog.getValue()); |
| finishAction(); |
| break; |
| } |
| |
| case FEAT: { |
| TableTreeItem typeItem = editItem.getParentItem(); |
| String typeName = getFullyQualifiedName(typeItem); |
| |
| // using the CAS to get all the inherited features |
| Type type = editor.getCurrentView().getTypeSystem().getType(typeName); |
| |
| AddCapabilityFeatureDialog dialog = new AddCapabilityFeatureDialog(this, type, c); |
| if (dialog.open() == Window.CANCEL) |
| return; |
| |
| addOrEditFeature(dialog, typeName, typeItem, c); |
| break; |
| } |
| default: |
| break; // happens when mouse double click on non-editable item - ignore |
| } |
| } |
| |
| private boolean anyCapabilitySetDeclaresSofa(String name, boolean isInput) { |
| final Capability[] cSets = getAnalysisEngineMetaData().getCapabilities(); |
| for (int i = 0; i < cSets.length; i++) { |
| final String[] sofaNames = isInput ? cSets[i].getInputSofas() : cSets[i].getOutputSofas(); |
| for (int j = 0; j < sofaNames.length; j++) { |
| if (name.equals(sofaNames[j])) |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| private void handleRemove(TableTreeItem removeItem, int itemKind) { |
| Table table = tt.getTable(); |
| int previousSelection = table.getSelectionIndex() - 1; |
| Capability c = getCapability(removeItem); |
| switch (itemKind) { |
| case CS: { |
| if (Window.CANCEL == Utility.popOkCancel("Confirm Remove", |
| "This action will remove an entire capability set. Please confirm.", |
| MessageDialog.WARNING)) { |
| table.setSelection(table.getSelectionIndex() + 1); |
| return; |
| } |
| removeCapabilitySet(c); |
| removeItem.dispose(); |
| break; |
| } |
| case LANG_ITEM: { |
| c.setLanguagesSupported(stringArrayRemove(c.getLanguagesSupported(), removeItem |
| .getText(NAME_COL))); |
| removeItem.dispose(); |
| break; |
| } |
| case SOFA_ITEM: { |
| if (Window.CANCEL == Utility |
| .popOkCancel( |
| "Confirm Removal of Sofa", |
| "This action will remove this Sofa as a capability, and delete its mappings if no other capability set declares this Sofa." |
| + " Please confirm.", MessageDialog.WARNING)) { |
| table.setSelection(table.getSelectionIndex() + 1); |
| return; |
| } |
| String sofaName = removeItem.getText(NAME_COL); |
| boolean isInput = INPUT.equals(removeItem.getText(INPUT_COL)); |
| if (isInput) |
| c.setInputSofas((String[]) Utility.removeElementFromArray(c.getInputSofas(), sofaName, |
| String.class)); |
| else |
| c.setOutputSofas((String[]) Utility.removeElementFromArray(c.getOutputSofas(), sofaName, |
| String.class)); |
| removeItem.dispose(); |
| |
| if (!anyCapabilitySetDeclaresSofa(sofaName, isInput)) { |
| Comparator comparator = new Comparator() { |
| public int compare(Object o1, Object o2) { |
| String name = (String) o1; |
| SofaMapping sofaMapping = (SofaMapping) o2; |
| if (name.equals(sofaMapping.getAggregateSofaName())) |
| return 0; |
| return 1; |
| } |
| }; |
| editor.getAeDescription().setSofaMappings( |
| (SofaMapping[]) Utility.removeElementsFromArray(getSofaMappings(), sofaName, |
| SofaMapping.class, comparator)); |
| |
| sofaMapSection.markStale(); |
| } |
| break; |
| } |
| case TYPE: { |
| if (Window.CANCEL == Utility.popOkCancel("Confirm Removal of Type", |
| "This action will remove this type as a capability. Please confirm.", |
| MessageDialog.WARNING)) { |
| table.setSelection(table.getSelectionIndex() + 1); |
| return; |
| } |
| TableTreeItem[] features = removeItem.getItems(); |
| if (null != features) |
| for (int i = 0; i < features.length; i++) { |
| removeFeature(c, features[i]); |
| } |
| String typeNameToRemove = getFullyQualifiedName(removeItem); |
| if (isInput(removeItem)) |
| c.setInputs(typeOrFeatureArrayRemove(c.getInputs(), typeNameToRemove)); |
| if (isOutput(removeItem) /* || isUpdate(removeItem) */) |
| c.setOutputs(typeOrFeatureArrayRemove(c.getOutputs(), typeNameToRemove)); |
| |
| removeItem.dispose(); |
| break; |
| } |
| case FEAT: { |
| removeFeature(c, removeItem); |
| break; |
| } |
| default: |
| throw new InternalErrorCDE("invalid state"); |
| } |
| |
| table.setSelection(previousSelection); |
| finishAction(); |
| } |
| |
| private void removeCapabilitySet(Capability c) { |
| Capability[] cs = getAnalysisEngineMetaData().getCapabilities(); |
| Capability[] newCs = new Capability[cs.length - 1]; |
| for (int i = 0, j = 0; i < newCs.length; i++) { |
| if (cs[i] != c) |
| newCs[j++] = cs[i]; |
| } |
| getAnalysisEngineMetaData().setCapabilities(newCs); |
| } |
| |
| private boolean isInput(TableTreeItem item) { |
| return INPUT.equals(item.getText(INPUT_COL)); // works if getText() returns null |
| } |
| |
| private boolean isOutput(TableTreeItem item) { |
| return OUTPUT.equals(item.getText(OUTPUT_COL)); |
| } |
| |
| public static boolean isInput(String fullFeatureName, Capability c) { |
| return null != getTypeOrFeature(c.getInputs(), fullFeatureName); |
| } |
| |
| public static boolean isOutput(String fullFeatureName, Capability c) { |
| return null != getTypeOrFeature(c.getOutputs(), fullFeatureName); |
| } |
| |
| private void removeFeature(Capability c, TableTreeItem removeItem) { |
| String shortFeatureName = removeItem.getText(NAME_COL); |
| if (shortFeatureName.equals(ALL_FEATURES)) { |
| if (isInput(removeItem)) { |
| TypeOrFeature tfItem = getTypeOrFeature(c.getInputs(), getFullyQualifiedName(removeItem |
| .getParentItem())); |
| tfItem.setAllAnnotatorFeatures(false); |
| } |
| if (isOutput(removeItem) /* || isUpdate(removeItem) */) { |
| TypeOrFeature tfItem = getTypeOrFeature(c.getOutputs(), getFullyQualifiedName(removeItem |
| .getParentItem())); |
| tfItem.setAllAnnotatorFeatures(false); |
| } |
| } else { |
| String featureNameToRemove = getFullyQualifiedName(removeItem.getParentItem()) + ":" |
| + removeItem.getText(NAME_COL); |
| if (isInput(removeItem)) |
| c.setInputs(typeOrFeatureArrayRemove(c.getInputs(), featureNameToRemove)); |
| if (isOutput(removeItem) /* || isUpdate(removeItem) */) |
| c.setOutputs(typeOrFeatureArrayRemove(c.getOutputs(), featureNameToRemove)); |
| } |
| removeItem.dispose(); |
| } |
| |
| public Capability getCapabilityFromTableTreeItem(TableTreeItem item) { |
| return (Capability) item.getData(); |
| } |
| |
| private void handleAddLang(TableTreeItem selItem, int itemKind) { |
| if (itemKind == CS) |
| selItem = selItem.getItems()[0]; // lang is 1st item in capability set |
| else if (itemKind == LANG_ITEM) |
| selItem = selItem.getParentItem(); |
| else if (itemKind == TYPE || itemKind == SOFA) |
| selItem = selItem.getParentItem().getItems()[0]; |
| else if (itemKind == FEAT || itemKind == SOFA_ITEM) |
| selItem = selItem.getParentItem().getParentItem().getItems()[0]; |
| Capability c = getCapabilityFromTableTreeItem(selItem.getParentItem()); |
| CommonInputDialog dialog = new CommonInputDialog( |
| this, |
| "Add Language", |
| "Enter a two letter ISO-639 language code, followed optionally by a two-letter ISO-3166 country code (Examples: fr or fr-CA)", |
| CommonInputDialog.LANGUAGE); |
| if (dialogForLanguage(c, dialog) == Window.CANCEL) |
| return; |
| |
| c.setLanguagesSupported(stringArrayAdd(c.getLanguagesSupported(), dialog.getValue())); |
| |
| // update GUI |
| TableTreeItem lItem = new TableTreeItem(selItem, SWT.NONE); |
| lItem.setData(LANG_TITLE); |
| lItem.setText(NAME_COL, dialog.getValue()); |
| selItem.setExpanded(true); |
| pack04(); |
| finishAction(); |
| } |
| |
| private void handleAddType(TableTreeItem selItem, int itemKind) { |
| if (itemKind == LANG || itemKind == TYPE || itemKind == SOFA) |
| selItem = selItem.getParentItem(); |
| else if (itemKind == LANG_ITEM || itemKind == FEAT || itemKind == SOFA_ITEM) |
| selItem = selItem.getParentItem().getParentItem(); |
| Capability c = getCapabilityFromTableTreeItem(selItem); |
| AddCapabilityTypeDialog dialog = new AddCapabilityTypeDialog(this, c); |
| if (dialog.open() == Window.CANCEL) |
| return; |
| |
| for (int i = 0; i < dialog.types.length; i++) { |
| |
| if (dialog.inputs[i]) |
| c.addInputType(dialog.types[i], dialog.inputs[i]); |
| |
| if (dialog.outputs[i]) |
| c.addOutputType(dialog.types[i], dialog.outputs[i]); |
| |
| TableTreeItem item = new TableTreeItem(selItem, SWT.NONE); |
| setGuiTypeName(item, dialog.types[i]); |
| item.setText(INPUT_COL, dialog.inputs[i] ? INPUT : ""); |
| item.setText(OUTPUT_COL, dialog.outputs[i] ? OUTPUT : ""); |
| |
| TableTreeItem fItem = new TableTreeItem(item, SWT.NONE); |
| fItem.setData(FEAT_TITLE); |
| fItem.setText(NAME_COL, ALL_FEATURES); |
| fItem.setText(INPUT_COL, dialog.inputs[i] ? INPUT : ""); |
| fItem.setText(OUTPUT_COL, dialog.outputs[i] ? OUTPUT : ""); |
| |
| item.setExpanded(true); |
| } |
| pack04(); |
| selItem.setExpanded(true); |
| finishAction(); |
| } |
| |
| private void handleAddSofa(TableTreeItem selItem, int itemKind) { |
| if (itemKind == CS) |
| selItem = selItem.getItems()[1]; |
| else if (itemKind == LANG || itemKind == TYPE) |
| selItem = selItem.getParentItem().getItems()[1]; |
| else if (itemKind == LANG_ITEM || itemKind == FEAT || itemKind == SOFA_ITEM) |
| selItem = selItem.getParentItem().getParentItem().getItems()[1]; |
| |
| Capability c = getCapabilityFromTableTreeItem(selItem.getParentItem()); |
| AddSofaDialog dialog = new AddSofaDialog(this, c); |
| if (dialog.open() == Window.CANCEL) |
| return; |
| |
| // dialog.isInput, dialog.sofaName |
| if (dialog.isInput) |
| c.setInputSofas(stringArrayAdd(c.getInputSofas(), dialog.sofaName)); |
| else |
| c.setOutputSofas(stringArrayAdd(c.getOutputSofas(), dialog.sofaName)); |
| |
| TableTreeItem item = new TableTreeItem(selItem, SWT.NONE); |
| setGuiSofaName(item, dialog.sofaName, dialog.isInput); |
| selItem.setExpanded(true); |
| pack04(); |
| |
| sofaMapSection.markStale(); |
| finishAction(); |
| } |
| |
| private void handleAddEditFeature(TableTreeItem selItem, int itemKind) { |
| if (itemKind == FEAT) |
| selItem = selItem.getParentItem(); |
| |
| Capability c = getCapabilityFromTableTreeItem(selItem.getParentItem()); |
| String typeName = getFullyQualifiedName(selItem); |
| |
| // using the CAS to get all the inherited features |
| Type type = editor.getCurrentView().getTypeSystem().getType(typeName); |
| |
| AddCapabilityFeatureDialog dialog = new AddCapabilityFeatureDialog(this, type, c); |
| if (dialog.open() == Window.CANCEL) |
| return; |
| |
| addOrEditFeature(dialog, typeName, selItem, c); |
| } |
| |
| private void addOrEditFeature(AddCapabilityFeatureDialog dialog, String typeName, // fully |
| // qualified |
| TableTreeItem parentItem, Capability c) { |
| // set the <all features> flag on the type in the model, for input and output |
| c.setInputs(setAllFeatures(c.getInputs(), typeName, dialog.allFeaturesInput)); |
| // The logic for output features is complicated. Output features are always listed in the |
| // outputs section of the capability. |
| // Their type must be in either the output section or the input section. |
| // When a feature is added here as an output, and the input section has a type, |
| // we don't require that there be a type capability with output marked. |
| // If the user wants to have an output type, |
| // they can add one explicitly. |
| // There must be either an input or an output Type in order for a feature to be added. |
| // |
| // For the "all features" case, we can't set an output state for all features on an input type. |
| if (dialog.allFeaturesOutput && (null == getTypeOrFeature(c.getOutputs(), typeName))) { |
| Utility |
| .popMessage( |
| "Unable to set AllFeatures", |
| "Skipping setting of <All Features> for output, because you must have the type specified itself" |
| + " as an output in order to set the <All Features>. You can individually set all the features, instead.", |
| MessageDialog.WARNING); |
| dialog.allFeaturesOutput = false; |
| } else |
| c.setOutputs(setAllFeatures(c.getOutputs(), typeName, dialog.allFeaturesOutput)); |
| |
| TableTreeItem[] prevFeatGUI = parentItem.getItems(); |
| for (int i = 0; i < prevFeatGUI.length; i++) { |
| prevFeatGUI[i].dispose(); |
| } |
| |
| // update GUI for <all features> - add element if needed |
| if (dialog.allFeaturesInput || dialog.allFeaturesOutput) { |
| TableTreeItem item = new TableTreeItem(parentItem, SWT.NONE); |
| item.setData(FEAT_TITLE); |
| item.setText(NAME_COL, ALL_FEATURES); |
| item.setText(INPUT_COL, dialog.allFeaturesInput ? INPUT : ""); |
| item.setText(OUTPUT_COL, dialog.allFeaturesOutput ? OUTPUT : ""); |
| } |
| |
| List inputsL = new ArrayList(); |
| List outputsL = new ArrayList(); |
| |
| for (int i = 0; i < dialog.features.length; i++) { |
| String fullName = typeName + ":" + dialog.features[i]; |
| if (dialog.inputs[i]) |
| inputsL.add(newFeature(fullName)); |
| if (dialog.outputs[i]) |
| outputsL.add(newFeature(fullName)); |
| // update the GUI |
| TableTreeItem item = new TableTreeItem(parentItem, SWT.NONE); |
| item.setData(FEAT_TITLE); |
| item.setText(NAME_COL, dialog.features[i]); |
| item.setText(INPUT_COL, dialog.inputs[i] ? INPUT : ""); |
| item.setText(OUTPUT_COL, dialog.outputs[i] ? OUTPUT : ""); |
| } |
| parentItem.setExpanded(true); |
| tt.getTable().getColumn(NAME_COL).pack(); |
| tt.setSelection(new TableTreeItem[] { parentItem }); |
| |
| c.setInputs(replaceFeaturesKeepingTypes(c.getInputs(), typeName, inputsL)); |
| c.setOutputs(replaceFeaturesKeepingTypes(c.getOutputs(), typeName, outputsL)); |
| |
| finishAction(); |
| } |
| |
| private TypeOrFeature newFeature(String name) { |
| TypeOrFeature result = new TypeOrFeature_impl(); |
| result.setType(false); |
| result.setName(name); |
| return result; |
| } |
| |
| public String getFullyQualifiedName(TableTreeItem item) { |
| String namespace = item.getText(NAMESPACE_COL); |
| String name = item.getText(NAME_COL); |
| return "".equals(namespace) ? name : namespace + "." + name; |
| } |
| |
| // used by dialog table -has different columns |
| public String getFullyQualifiedName(String namespace, String name) { |
| return (null == namespace || "".equals(namespace)) ? name : namespace + "." + name; |
| } |
| |
| /** |
| * Given a current list of inputs/ outputs, made up of "Types" and "features", make a new list |
| * keeping all the types, and keeping all the features that belong to other types, and adding the |
| * features that are passed in for one particular type in the "features" parameter |
| * |
| * @param items |
| * @param type |
| * A string representing the fully qualified type name |
| * @param features - |
| * associated with the type |
| * @return |
| */ |
| private TypeOrFeature[] replaceFeaturesKeepingTypes(TypeOrFeature[] items, String typeName, |
| List features) { |
| List newItems = new ArrayList(); |
| typeName = typeName + ':'; |
| if (null != items) |
| for (int i = 0; i < items.length; i++) { |
| if (items[i].isType() || !items[i].getName().startsWith(typeName)) |
| newItems.add(items[i]); |
| } |
| |
| for (Iterator it = features.iterator(); it.hasNext();) { |
| newItems.add(it.next()); |
| } |
| return (TypeOrFeature[]) newItems.toArray(new TypeOrFeature[newItems.size()]); |
| } |
| |
| /** |
| * |
| * @param items |
| * Existing array of TypeOrFeature items (input or output) |
| * @param typeName |
| * @param isAllFeatures |
| * AllFeatures value |
| * @return |
| */ |
| private TypeOrFeature[] setAllFeatures(TypeOrFeature[] items, String typeName, |
| boolean isAllFeatures) { |
| |
| TypeOrFeature type = getTypeOrFeature(items, typeName); |
| |
| if (null != type) { |
| type.setAllAnnotatorFeatures(isAllFeatures); |
| return items; |
| } |
| |
| // If get here, case = Type declared as Output(input) or not at all while all Features |
| // declared as Input (output) |
| // Need to add the Type and set the all annotator features value |
| if (isAllFeatures) |
| throw new InternalErrorCDE("invalid state"); |
| return items; |
| } |
| |
| private void finishAction() { |
| setFileDirty(); |
| } |
| |
| private void pack04() { |
| tt.getTable().getColumn(TITLE_COL).pack(); |
| tt.getTable().getColumn(NAME_COL).pack(); |
| tt.getTable().getColumn(NAMESPACE_COL).pack(); |
| } |
| |
| private int getItemKind(TableTreeItem item) { |
| String itemID = item.getText(TITLE_COL); |
| |
| if (CAPABILITY_SET.equals(itemID)) |
| return CS; |
| if (TYPE_TITLE.equals(itemID)) |
| return TYPE; |
| itemID = (String) item.getData(); |
| if (LANGS_TITLE.equals(itemID)) |
| return LANG; |
| if (FEAT_TITLE.equals(itemID)) |
| return FEAT; |
| if (LANG_TITLE.equals(itemID)) |
| return LANG_ITEM; |
| if (SOFAS_TITLE.equals(itemID)) |
| return SOFA; |
| if (SOFA_TITLE.equals(itemID)) |
| return SOFA_ITEM; |
| throw new InternalErrorCDE("invalid state"); |
| } |
| |
| public void enable() { |
| addCapabilityButton.setEnabled(true); |
| |
| boolean selectOK = tt.getSelectionCount() == 1; |
| TableTreeItem item = selectOK ? tt.getSelection()[0] : null; |
| int kind = selectOK ? getItemKind(item) : 0; |
| |
| addLangButton.setEnabled(selectOK); |
| addTypeButton.setEnabled(selectOK); |
| addSofaButton.setEnabled(selectOK); |
| addEditFeatureButton.setEnabled((kind & (FEAT + TYPE)) > 0); |
| editButton.setEnabled((kind & (SOFA_ITEM + LANG_ITEM + FEAT + TYPE)) > 0); |
| removeButton.setEnabled((kind & (CS + SOFA_ITEM + LANG_ITEM + FEAT + TYPE)) > 0); |
| } |
| |
| private int dialogForLanguage(Capability c, CommonInputDialog dialog) { |
| for (;;) { |
| if (dialog.open() == Window.CANCEL) |
| return Window.CANCEL; |
| |
| String[] languages = c.getLanguagesSupported(); |
| boolean alreadySpecified = false; |
| for (int i = 0; i < languages.length; i++) { |
| if (languages[i].equals(dialog.getValue())) { |
| Utility |
| .popMessage( |
| "Language spec already defined", |
| "The language specification you entered is already specified.\nPlease enter a different specification, or Cancel this operation." |
| + "\n\nLanguage: " + dialog.getValue(), MessageDialog.ERROR); |
| alreadySpecified = true; |
| break; |
| } |
| } |
| if (!alreadySpecified) |
| break; |
| } |
| return Window.OK; |
| } |
| |
| private Capability getCapability(TableTreeItem item) { |
| while (null != item.getParentItem()) |
| item = item.getParentItem(); |
| return getCapabilityFromTableTreeItem(item); |
| } |
| |
| } |