//============================================================================ // // Copyright (C) 2002-2016 David Schneider, Lars Ködderitzsch // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // //============================================================================ package net.sf.eclipsecs.ui.config; import com.google.common.base.Strings; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.regex.Pattern; import net.sf.eclipsecs.core.config.CheckConfigurationWorkingCopy; import net.sf.eclipsecs.core.config.Module; import net.sf.eclipsecs.core.config.Severity; import net.sf.eclipsecs.core.config.meta.MetadataFactory; import net.sf.eclipsecs.core.config.meta.RuleGroupMetadata; import net.sf.eclipsecs.core.config.meta.RuleMetadata; import net.sf.eclipsecs.core.util.CheckstyleLog; import net.sf.eclipsecs.core.util.CheckstylePluginException; import net.sf.eclipsecs.ui.CheckstyleUIPlugin; import net.sf.eclipsecs.ui.CheckstyleUIPluginImages; import net.sf.eclipsecs.ui.CheckstyleUIPluginPrefs; import net.sf.eclipsecs.ui.Messages; import net.sf.eclipsecs.ui.util.SWTUtil; import net.sf.eclipsecs.ui.util.table.EnhancedCheckBoxTableViewer; import net.sf.eclipsecs.ui.util.table.ITableComparableProvider; import net.sf.eclipsecs.ui.util.table.ITableSettingsProvider; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.TitleAreaDialog; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.ColumnWeightData; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.ICheckStateListener; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableLayout; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.jface.window.Window; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.Text; import org.osgi.service.prefs.BackingStoreException; /** * Enhanced checkstyle configuration editor. * * @author Lars Ködderitzsch */ public class CheckConfigurationConfigureDialog extends TitleAreaDialog { /** The current check configuration. */ private final CheckConfigurationWorkingCopy mConfiguration; /** Flags if the Check configuration can be modified. */ private boolean mConfigurable; /** Text field used to filter the module tree. */ private Text mTxtTreeFilter; /** TreeViewer showing the known modules from the meta data. */ private TreeViewer mTreeViewer; /** Button to add a module. */ private Button mAddButton; /** The table viewer showing the configured modules. */ private EnhancedCheckBoxTableViewer mTableViewer; /** Button to remove a module. */ private Button mRemoveButton; /** Button to remove a module. */ private Button mEditButton; /** Group containing the table viewer. */ private Group mConfiguredModulesGroup; private Browser mBrowserDescription; /** Checkbox handling if the module editor is opened on add action. */ private Button mBtnOpenModuleOnAdd; /** Filter for the table viewer to show only element of the selected group. */ private final RuleGroupModuleFilter mGroupFilter = new RuleGroupModuleFilter(); /** Controller for this Dialog. */ private final PageController mController = new PageController(); /** the list of modules. */ private List<Module> mModules; /** Flags if the check configuration was changed. */ private boolean mIsDirty; /** The default text for the filter text field. */ private final String mDefaultFilterText = Messages.CheckConfigurationConfigureDialog_defaultFilterText; /** The tree filter. */ private final TreeFilter mTreeFilter = new TreeFilter(); // // constructors // /** * Creates the configuration dialog. * * @param parentShell * the parent shell * @param config * the check configuration */ public CheckConfigurationConfigureDialog(Shell parentShell, CheckConfigurationWorkingCopy config) { super(parentShell); setShellStyle(getShellStyle() | SWT.RESIZE | SWT.MAX); mConfiguration = config; } // // methods // /** * Creates the dialogs main contents. * * @param parent * the parent composite */ @Override protected Control createDialogArea(Composite parent) { Composite composite = (Composite) super.createDialogArea(parent); Composite contents = new Composite(composite, SWT.NULL); contents.setLayoutData(new GridData(GridData.FILL_BOTH)); contents.setLayout(new GridLayout()); SashForm sashForm = new SashForm(contents, SWT.NULL); GridData gd = new GridData(GridData.FILL_BOTH); gd.widthHint = 700; gd.heightHint = 400; sashForm.setLayoutData(gd); sashForm.setLayout(new GridLayout()); Control treeControl = createTreeViewer(sashForm); treeControl.setLayoutData(new GridData(GridData.FILL_BOTH)); Control tableControl = createTableViewer(sashForm); tableControl.setLayoutData(new GridData(GridData.FILL_BOTH)); sashForm.setWeights(new int[] { 30, 70 }); Label lblDescription = new Label(contents, SWT.NULL); lblDescription.setText(Messages.CheckConfigurationConfigureDialog_lblDescription); lblDescription.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); mBrowserDescription = new Browser(contents, SWT.BORDER); gd = new GridData(GridData.FILL_BOTH); gd.heightHint = 100; mBrowserDescription.setLayoutData(gd); // initialize the data initialize(); return contents; } /** * @see org.eclipse.jface.window.Window#create() */ @Override public void create() { super.create(); SWTUtil.addResizeSupport(this, CheckstyleUIPlugin.getDefault().getDialogSettings(), CheckConfigurationConfigureDialog.class.getName()); } /** * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell) */ @Override protected void configureShell(Shell newShell) { super.configureShell(newShell); newShell.setText(Messages.CheckConfigurationConfigureDialog_titleCheckConfigurationDialog); } /** * @see org.eclipse.jface.dialogs.Dialog#okPressed() */ @Override protected void okPressed() { try { // only write the modules back if the config is configurable // and was actually changed if (mConfigurable && mIsDirty) { mConfiguration.setModules(mModules); } } catch (CheckstylePluginException e) { CheckstyleUIPlugin.errorDialog(getShell(), e, true); } super.okPressed(); } private Control createTreeViewer(Composite parent) { Group knownModules = new Group(parent, SWT.NULL); knownModules.setLayout(new GridLayout()); knownModules.setText(Messages.CheckConfigurationConfigureDialog_lblKnownModules); mTxtTreeFilter = new Text(knownModules, SWT.SINGLE | SWT.BORDER); mTxtTreeFilter.setText(mDefaultFilterText); mTxtTreeFilter.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); mTxtTreeFilter.addModifyListener(mController); mTxtTreeFilter.addKeyListener(mController); // select all of the default text on focus gain mTxtTreeFilter.addFocusListener(new FocusListener() { @Override public void focusGained(FocusEvent e) { if (mDefaultFilterText.equals(mTxtTreeFilter.getText())) { getShell().getDisplay().asyncExec(new Runnable() { @Override public void run() { mTxtTreeFilter.selectAll(); } }); } } @Override public void focusLost(FocusEvent e) { } }); mTreeViewer = new TreeViewer(knownModules, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); mTreeViewer.getControl().setLayoutData(new GridData(GridData.FILL_BOTH)); mTreeViewer.setContentProvider(new MetaDataContentProvider()); mTreeViewer.setLabelProvider(new MetaDataLabelProvider()); mTreeViewer.addSelectionChangedListener(mController); mTreeViewer.addDoubleClickListener(mController); mTreeViewer.getTree().addKeyListener(mController); // filter hidden elements mTreeViewer.addFilter(new ViewerFilter() { @Override public boolean select(Viewer viewer, Object parentElement, Object element) { boolean passes = true; if (element instanceof RuleGroupMetadata) { passes = !((RuleGroupMetadata) element).isHidden(); } else if (element instanceof RuleMetadata) { passes = !((RuleMetadata) element).isHidden(); } return passes; } }); mAddButton = new Button(knownModules, SWT.PUSH); mAddButton.setText((Messages.CheckConfigurationConfigureDialog_btnAdd)); GridData gd = new GridData(); gd.horizontalAlignment = GridData.END; mAddButton.setLayoutData(gd); mAddButton.addSelectionListener(mController); return knownModules; } private Control createTableViewer(Composite parent) { mConfiguredModulesGroup = new Group(parent, SWT.NULL); mConfiguredModulesGroup.setLayout(new GridLayout()); mConfiguredModulesGroup.setText("\0"); //$NON-NLS-1$ Table table = new Table(mConfiguredModulesGroup, SWT.CHECK | SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION); table.setLayoutData(new GridData(GridData.FILL_BOTH)); table.setHeaderVisible(true); table.setLinesVisible(true); TableLayout tableLayout = new TableLayout(); table.setLayout(tableLayout); TableColumn column1 = new TableColumn(table, SWT.NULL); column1.setAlignment(SWT.CENTER); column1.setText(Messages.CheckConfigurationConfigureDialog_colEnabled); tableLayout.addColumnData(new ColumnWeightData(15)); TableColumn column2 = new TableColumn(table, SWT.NULL); column2.setText(Messages.CheckConfigurationConfigureDialog_colModule); tableLayout.addColumnData(new ColumnWeightData(30)); TableColumn column3 = new TableColumn(table, SWT.NULL); column3.setText(Messages.CheckConfigurationConfigureDialog_colSeverity); tableLayout.addColumnData(new ColumnWeightData(20)); TableColumn column4 = new TableColumn(table, SWT.NULL); column4.setText(Messages.CheckConfigurationConfigureDialog_colComment); tableLayout.addColumnData(new ColumnWeightData(35)); mTableViewer = new EnhancedCheckBoxTableViewer(table); ModuleLabelProvider multiProvider = new ModuleLabelProvider(); mTableViewer.setLabelProvider(multiProvider); mTableViewer.setTableComparableProvider(multiProvider); mTableViewer.setTableSettingsProvider(multiProvider); mTableViewer.setContentProvider(new ArrayContentProvider()); mTableViewer.addFilter(mGroupFilter); mTableViewer.installEnhancements(); mTableViewer.addDoubleClickListener(mController); mTableViewer.addSelectionChangedListener(mController); mTableViewer.addCheckStateListener(mController); mTableViewer.getTable().addKeyListener(mController); Composite buttons = new Composite(mConfiguredModulesGroup, SWT.NULL); GridLayout layout = new GridLayout(2, true); layout.marginHeight = 0; layout.marginWidth = 0; buttons.setLayout(layout); buttons.setLayoutData(new GridData()); mRemoveButton = new Button(buttons, SWT.PUSH); mRemoveButton.setText((Messages.CheckConfigurationConfigureDialog_btnRemove)); mRemoveButton.setLayoutData(new GridData()); mRemoveButton.addSelectionListener(mController); mEditButton = new Button(buttons, SWT.PUSH); mEditButton.setText((Messages.CheckConfigurationConfigureDialog_btnOpen)); mEditButton.setLayoutData(new GridData()); mEditButton.addSelectionListener(mController); return mConfiguredModulesGroup; } @Override protected Control createButtonBar(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(2, false); layout.marginHeight = 0; layout.marginWidth = 0; composite.setLayout(layout); composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); mBtnOpenModuleOnAdd = new Button(composite, SWT.CHECK); mBtnOpenModuleOnAdd.setText(Messages.CheckConfigurationConfigureDialog_btnOpenModuleOnAdd); GridData gd = new GridData(); gd.horizontalAlignment = GridData.BEGINNING; gd.horizontalIndent = 5; mBtnOpenModuleOnAdd.setLayoutData(gd); // Init the translate tokens preference mBtnOpenModuleOnAdd.setSelection( CheckstyleUIPluginPrefs.getBoolean(CheckstyleUIPluginPrefs.PREF_OPEN_MODULE_EDITOR)); mBtnOpenModuleOnAdd.addSelectionListener(new SelectionListener() { @Override public void widgetSelected(SelectionEvent e) { // store translation preference try { CheckstyleUIPluginPrefs.setBoolean(CheckstyleUIPluginPrefs.PREF_OPEN_MODULE_EDITOR, ((Button) e.widget).getSelection()); } catch (BackingStoreException e1) { CheckstyleLog.log(e1); } } @Override public void widgetDefaultSelected(SelectionEvent e) { // NOOP } }); Control buttonBar = super.createButtonBar(composite); gd = new GridData(GridData.FILL_HORIZONTAL); gd.horizontalAlignment = GridData.END; buttonBar.setLayoutData(gd); return composite; } /** * Initialize the dialogs controls with the data. */ private void initialize() { mConfigurable = mConfiguration.isConfigurable(); try { mModules = mConfiguration.getModules(); } catch (CheckstylePluginException e) { mModules = new ArrayList<>(); CheckstyleUIPlugin.errorDialog(getShell(), e, true); } mTableViewer.setInput(mModules); this.setTitle(NLS.bind(Messages.CheckConfigurationConfigureDialog_titleMessageArea, mConfiguration.getType().getName(), mConfiguration.getName())); if (mConfigurable) { this.setMessage(Messages.CheckConfigurationConfigureDialog_msgEditConfig); } else { this.setMessage(Messages.CheckConfigurationConfigureDialog_msgReadonlyConfig); } // set the logo this.setTitleImage(CheckstyleUIPluginImages.getImage(CheckstyleUIPluginImages.PLUGIN_LOGO)); mAddButton.setEnabled(mConfigurable); mRemoveButton.setEnabled(mConfigurable); mTreeViewer.setInput(MetadataFactory.getRuleGroupMetadata()); List<RuleGroupMetadata> checkGroups = MetadataFactory.getRuleGroupMetadata(); if (!checkGroups.isEmpty()) { ISelection initialSelection = new StructuredSelection(checkGroups.get(0)); mTreeViewer.setSelection(initialSelection); } } /** * Controller for this page. * * @author Lars Ködderitzsch */ private class PageController implements ISelectionChangedListener, ICheckStateListener, IDoubleClickListener, SelectionListener, KeyListener, ModifyListener { /** * @see IDoubleClickListener#doubleClick(org.eclipse.jface.viewers.DoubleClickEvent) */ @Override public void doubleClick(DoubleClickEvent event) { if (event.getViewer() == mTableViewer) { openModule(event.getSelection()); } else if (event.getViewer() == mTreeViewer) { IStructuredSelection selection = (IStructuredSelection) event.getSelection(); Object element = selection.getFirstElement(); if (element instanceof RuleGroupMetadata) { mTreeViewer.setExpandedState(element, !mTreeViewer.getExpandedState(element)); } else { newModule(event.getSelection()); } } } /** * @see SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent) */ @Override public void widgetSelected(SelectionEvent e) { if (mEditButton == e.widget) { openModule(mTableViewer.getSelection()); } else if (mAddButton == e.widget) { newModule(mTreeViewer.getSelection()); } else if (mRemoveButton == e.widget) { removeModule(mTableViewer.getSelection()); } } /** * @see org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent) */ @Override public void keyReleased(KeyEvent e) { if (e.widget == mTableViewer.getTable()) { if (e.character == SWT.DEL || e.keyCode == SWT.ARROW_LEFT) { removeModule(mTableViewer.getSelection()); } } else if (e.widget == mTreeViewer.getTree()) { if (e.keyCode == SWT.ARROW_RIGHT || e.character == ' ') { IStructuredSelection selection = (IStructuredSelection) mTreeViewer.getSelection(); Object element = selection.getFirstElement(); if (element instanceof RuleMetadata) { newModule(mTreeViewer.getSelection()); } } } else if (e.widget == mTxtTreeFilter && e.keyCode == SWT.ARROW_DOWN) { mTreeViewer.getTree().forceFocus(); } } /** * {@inheritDoc} */ @Override public void modifyText(ModifyEvent e) { mTreeViewer.getControl().setRedraw(false); try { if (!mDefaultFilterText.equals(mTxtTreeFilter.getText()) && !Strings.isNullOrEmpty(mTxtTreeFilter.getText())) { if (!Arrays.asList(mTableViewer.getFilters()).contains(mTreeFilter)) { mTreeViewer.addFilter(mTreeFilter); } mTreeViewer.refresh(); mTreeViewer.expandAll(); } else { mTreeViewer.removeFilter(mTreeFilter); mTreeViewer.refresh(); } } finally { mTreeViewer.getControl().setRedraw(true); } } /** * @see SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent) */ @Override public void widgetDefaultSelected(SelectionEvent e) { // NOOP } @Override public void keyPressed(KeyEvent e) { // NOOP } @Override public void checkStateChanged(CheckStateChangedEvent event) { if (mConfigurable) { Module module = (Module) event.getElement(); if (event.getChecked()) { // restore last severity before setting to ignore Severity lastEnabled = module.getLastEnabledSeverity(); if (lastEnabled != null) { module.setSeverity(lastEnabled); } else { module.setSeverity(module.getMetaData().getDefaultSeverityLevel()); } } else { module.setSeverity(Severity.ignore); } mIsDirty = true; mTableViewer.refresh(module, true); } refreshTableViewerState(); } @Override public void selectionChanged(SelectionChangedEvent event) { IStructuredSelection selection = (IStructuredSelection) event.getSelection(); Object element = selection.getFirstElement(); String description = null; if (element instanceof RuleGroupMetadata) { RuleGroupMetadata group = (RuleGroupMetadata) element; description = group.getDescription(); mGroupFilter.setCurrentGroup(group); mConfiguredModulesGroup .setText(NLS.bind(Messages.CheckConfigurationConfigureDialog_lblConfiguredModules, group.getGroupName())); mTableViewer.refresh(); refreshTableViewerState(); } else if (element instanceof RuleMetadata) { RuleMetadata rule = (RuleMetadata) element; description = rule.getDescription(); mGroupFilter.setCurrentGroup(rule.getGroup()); mConfiguredModulesGroup .setText(NLS.bind(Messages.CheckConfigurationConfigureDialog_lblConfiguredModules, rule.getGroup().getGroupName())); mTableViewer.refresh(); refreshTableViewerState(); } else if (element instanceof Module) { RuleMetadata meta = ((Module) element).getMetaData(); if (meta != null) { description = meta.getDescription(); } } String buf = getDescriptionHtml(description); mBrowserDescription.setText(buf); } /** * Opens the module editor for the current selection. * * @param selection * the selection */ private void openModule(ISelection selection) { Module m = (Module) ((IStructuredSelection) selection).getFirstElement(); if (m != null) { Module workingCopy = m.clone(); RuleConfigurationEditDialog dialog = new RuleConfigurationEditDialog(getShell(), workingCopy, !mConfigurable, Messages.CheckConfigurationConfigureDialog_titleModuleConfigEditor); if (Window.OK == dialog.open() && mConfigurable) { mModules.set(mModules.indexOf(m), workingCopy); mIsDirty = true; mTableViewer.refresh(true); refreshTableViewerState(); } } } /** * Creates a module editor for the current selection. * * @param selection * the selection */ private void newModule(ISelection selection) { if (mConfigurable) { boolean openOnAdd = CheckstyleUIPluginPrefs .getBoolean(CheckstyleUIPluginPrefs.PREF_OPEN_MODULE_EDITOR); Iterator<?> it = ((IStructuredSelection) selection).iterator(); while (it.hasNext()) { Object selectedElement = it.next(); if (selectedElement instanceof RuleGroupMetadata) { // if group is selected add all modules from this group List<RuleMetadata> rules = ((RuleGroupMetadata) selectedElement).getRuleMetadata(); IStructuredSelection allRulesOfGroupSelection = new StructuredSelection(rules); newModule(allRulesOfGroupSelection); } else if (selectedElement instanceof RuleMetadata) { RuleMetadata metadata = (RuleMetadata) selectedElement; // check if the module is a singleton and already // configured if (metadata.isSingleton() && isAlreadyConfigured(metadata)) { return; } Module workingCopy = new Module(metadata, false); if (openOnAdd) { RuleConfigurationEditDialog dialog = new RuleConfigurationEditDialog(getShell(), workingCopy, !mConfigurable, Messages.CheckConfigurationConfigureDialog_titleNewModule); if (Window.OK == dialog.open() && mConfigurable) { mModules.add(workingCopy); mIsDirty = true; mTableViewer.refresh(true); refreshTableViewerState(); mTreeViewer.refresh(); mTreeViewer.getTree().forceFocus(); } } else { mModules.add(workingCopy); mIsDirty = true; mTableViewer.refresh(true); refreshTableViewerState(); mTreeViewer.refresh(); } } } } } /** * Creates a module editor for the current selection. * * @param selection * the selection */ private void removeModule(ISelection selection) { if (!selection.isEmpty() && mConfigurable) { if (MessageDialog.openConfirm(getShell(), Messages.CheckConfigurationConfigureDialog_titleRemoveModules, Messages.CheckConfigurationConfigureDialog_msgRemoveModules)) { @SuppressWarnings("unchecked") Iterator<Module> it = ((IStructuredSelection) selection).iterator(); while (it.hasNext()) { Module m = it.next(); if (m.getMetaData().isDeletable()) { mModules.remove(m); mIsDirty = true; mTableViewer.refresh(true); refreshTableViewerState(); mTreeViewer.refresh(); } } } } } /** * Restores the checked state of the table items. */ private void refreshTableViewerState() { // set selected modules (Modules where severity is not Ignore). int size = mModules != null ? mModules.size() : 0; for (int i = 0; i < size; i++) { Module module = mModules.get(i); if (mConfigurable) { mTableViewer.setChecked(module, !Severity.ignore.equals(module.getSeverity()) || !module.getMetaData().hasSeverity()); } else { mTableViewer.setChecked(module, !Severity.ignore.equals(module.getSeverity()) || !module.getMetaData().hasSeverity()); mTableViewer.setGrayed(module, !Severity.ignore.equals(module.getSeverity())); } } } /** * Checks if a certain module is already contained in the configuration. */ private boolean isAlreadyConfigured(RuleMetadata metadata) { String internalName = metadata.getInternalName(); boolean containsModule = false; for (int i = 0, size = mModules.size(); i < size; i++) { Module module = mModules.get(i); if (internalName.equals(module.getMetaData().getInternalName())) { containsModule = true; break; } } return containsModule; } } /** * TreeContentProvider that provides the structure of the rule metadata. * * @author Lars Ködderitzsch */ private class MetaDataContentProvider implements ITreeContentProvider { /** * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) */ @Override public Object[] getElements(Object inputElement) { Object[] ruleGroups = null; if (inputElement instanceof List) { ruleGroups = ((List<?>) inputElement).toArray(); } return ruleGroups; } /** * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object) */ @Override public Object[] getChildren(Object parentElement) { Object[] children = null; if (parentElement instanceof List) { children = getElements(parentElement); } else if (parentElement instanceof RuleGroupMetadata) { children = ((RuleGroupMetadata) parentElement).getRuleMetadata().toArray(); } return children; } /** * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object) */ @Override public Object getParent(Object element) { Object parent = null; if (element instanceof RuleMetadata) { parent = ((RuleMetadata) element).getGroup(); } return parent; } /** * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object) */ @Override public boolean hasChildren(Object element) { boolean hasChildren = false; if (element instanceof RuleGroupMetadata) { hasChildren = ((RuleGroupMetadata) element).getRuleMetadata().size() > 0; } else if (element instanceof RuleMetadata) { hasChildren = false; } return hasChildren; } /** * @see org.eclipse.jface.viewers.IContentProvider#dispose() */ @Override public void dispose() { // NOOP } /** * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(Viewer, Object, Object) */ @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { // NOOP } } /** * Label-provider for meta data information. * * @author Lars Ködderitzsch */ private class MetaDataLabelProvider extends LabelProvider { /** * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object) */ @Override public String getText(Object element) { String text = null; if (element instanceof RuleGroupMetadata) { text = ((RuleGroupMetadata) element).getGroupName(); } else if (element instanceof RuleMetadata) { text = ((RuleMetadata) element).getRuleName(); } return text; } /** * @see org.eclipse.jface.viewers.LabelProvider#getImage(java.lang.Object) */ @Override public Image getImage(Object element) { Image image = null; if (element instanceof RuleGroupMetadata) { image = isGroupUsed((RuleGroupMetadata) element) ? CheckstyleUIPluginImages .getImage(CheckstyleUIPluginImages.MODULEGROUP_TICKED_ICON) : CheckstyleUIPluginImages.getImage(CheckstyleUIPluginImages.MODULEGROUP_ICON); } else if (element instanceof RuleMetadata) { image = isMetadataUsed((RuleMetadata) element) ? CheckstyleUIPluginImages.getImage(CheckstyleUIPluginImages.MODULE_TICKED_ICON) : CheckstyleUIPluginImages.getImage(CheckstyleUIPluginImages.MODULE_ICON); } return image; } private boolean isGroupUsed(RuleGroupMetadata group) { boolean used = true; for (RuleMetadata metadata : group.getRuleMetadata()) { if (!isMetadataUsed(metadata)) { used = false; break; } } return used; } private boolean isMetadataUsed(RuleMetadata metadata) { boolean used = false; if (mModules != null) { for (Module module : mModules) { if (metadata.equals(module.getMetaData())) { used = true; break; } } } return used; } } /** * Label provider for the table showing the configured modules. * * @author Lars Ködderitzsch */ private class ModuleLabelProvider extends LabelProvider implements ITableLabelProvider, ITableComparableProvider, ITableSettingsProvider { /** * {@inheritDoc} */ @Override public Image getColumnImage(Object element, int columnIndex) { return null; } /** * {@inheritDoc} */ @Override public String getColumnText(Object element, int columnIndex) { String text = null; if (element instanceof Module) { Module module = (Module) element; switch (columnIndex) { case 0: text = ""; break; case 1: text = module.getName() != null ? module.getName() : ""; break; case 2: text = module.getSeverity() != null ? module.getSeverity().name() : ""; break; case 3: text = module.getComment() != null ? module.getComment() : ""; break; default: text = ""; break; } } return text; } /** * {@inheritDoc} */ @Override public Comparable<?> getComparableValue(Object element, int col) { if (element instanceof Module && col == 0) { return Severity.ignore.equals(((Module) element).getSeverity()) ? Integer.valueOf(0) : Integer.valueOf(1); } return getColumnText(element, col); } /** * {@inheritDoc} */ @Override public IDialogSettings getTableSettings() { String concreteViewId = CheckConfigurationConfigureDialog.class.getName(); IDialogSettings workbenchSettings = CheckstyleUIPlugin.getDefault().getDialogSettings(); IDialogSettings settings = workbenchSettings.getSection(concreteViewId); if (settings == null) { settings = workbenchSettings.addNewSection(concreteViewId); } return settings; } } /** * Viewer filter that includes all modules that belong to the currently selected group. * * @author Lars Ködderitzsch */ private class RuleGroupModuleFilter extends ViewerFilter { /** the current rule group. */ private RuleGroupMetadata mCurrentGroup; /** * Sets the current rule group. * * @param groupMetaData the group metadata */ public void setCurrentGroup(RuleGroupMetadata groupMetaData) { mCurrentGroup = groupMetaData; } /** * @see org.eclipse.jface.viewers.ViewerFilter#select(org.eclipse.jface.viewers.Viewer, * java.lang.Object, java.lang.Object) */ @Override public boolean select(Viewer viewer, Object parentElement, Object element) { boolean result = false; Module module = (Module) element; RuleMetadata metaData = module.getMetaData(); if (metaData == null) { return true; } RuleGroupMetadata moduleGroup = metaData.getGroup(); if (mCurrentGroup == null || metaData.isHidden()) { result = false; } else if (mCurrentGroup == moduleGroup) { result = true; } return result; } } /** * Filter implementation that filters the module tree with respect of a filter text field to input * a search word. * * @author Lars Ködderitzsch */ private class TreeFilter extends ViewerFilter { @Override public boolean select(Viewer viewer, Object parentElement, Object element) { boolean result = true; String filterText = mTxtTreeFilter.getText(); if (element instanceof RuleMetadata) { result = selectRule((RuleMetadata) element, filterText); } else if (element instanceof RuleGroupMetadata) { result = selectGroup((RuleGroupMetadata) element, filterText); } return result; } private boolean selectRule(RuleMetadata element, String filterText) { Pattern matchPattern = Pattern.compile(Pattern.quote(filterText), Pattern.CASE_INSENSITIVE); String ruleName = element.getRuleName(); String internalName = element.getInternalName(); String description = element.getDescription(); boolean passes = (ruleName != null && matchPattern.matcher(ruleName).find()) || (internalName != null && matchPattern.matcher(internalName).find()) || (description != null && matchPattern.matcher(description).find()); return passes; } private boolean selectGroup(RuleGroupMetadata group, String filterText) { boolean hasAtLeastOneMatchingChild = false; for (RuleMetadata element : group.getRuleMetadata()) { if (selectRule(element, filterText)) { hasAtLeastOneMatchingChild = true; break; } } return hasAtLeastOneMatchingChild; } } /** * Convert a module description to HTML for use with a browser component. * @param description module description * @return HTML converted description */ public static String getDescriptionHtml(String description) { StringBuffer buf = new StringBuffer(); buf.append("<html><body style=\"margin: 3px; font-size: 11px; "); buf.append("font-family: verdana, 'trebuchet MS', helvetica, sans-serif;\">"); buf.append(description != null ? description : Messages.CheckConfigurationConfigureDialog_txtNoDescription); buf.append("</body></html>"); return buf.toString(); } }