/******************************************************************************* * Copyright (c) 2007 Spring IDE Developers * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Spring IDE Developers - initial API and implementation *******************************************************************************/ package org.springframework.ide.eclipse.aop.ui.matcher; import java.util.ArrayList; import java.util.List; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.DialogPage; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.search.ui.ISearchPage; import org.eclipse.search.ui.ISearchPageContainer; import org.eclipse.search.ui.ISearchQuery; import org.eclipse.search.ui.NewSearchUI; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.IWorkingSet; import org.eclipse.ui.IWorkingSetManager; import org.eclipse.ui.PlatformUI; import org.springframework.ide.eclipse.aop.ui.matcher.internal.PointcutMatchQuery; import org.springframework.ide.eclipse.aop.ui.matcher.internal.PointcutMatcherScope; import org.springframework.ide.eclipse.aop.ui.matcher.internal.PointcutMatcherMessages; /** * {@link ISearchPage} implementation that is used to enter pointcut match * requests in Eclipse' search UI. * @author Christian Dupuis * @since 2.0.2 */ public class PointcutMatcherSearchPage extends DialogPage implements ISearchPage { private static class PointcutMatchData { public static PointcutMatchData create(IDialogSettings settings) { String pattern = settings.get("pattern"); if (pattern.length() == 0) { return null; } String[] wsIds = settings.getArray("workingSets"); IWorkingSet[] workingSets = null; if (wsIds != null && wsIds.length > 0) { IWorkingSetManager workingSetManager = PlatformUI .getWorkbench().getWorkingSetManager(); workingSets = new IWorkingSet[wsIds.length]; for (int i = 0; workingSets != null && i < wsIds.length; i++) { workingSets[i] = workingSetManager.getWorkingSet(wsIds[i]); if (workingSets[i] == null) { workingSets = null; } } } try { int scope = settings.getInt("scope"); boolean isProxyTargetClass = settings .getBoolean("isProxyTargetClass"); return new PointcutMatchData(pattern, isProxyTargetClass, scope, workingSets); } catch (NumberFormatException e) { return null; } } private String expression; private boolean isProxyTargetClass; private int scope; private IWorkingSet[] workingSets; public PointcutMatchData(String pattern, boolean isProxyTargetClass) { this(pattern, isProxyTargetClass, ISearchPageContainer.WORKSPACE_SCOPE, null); } public PointcutMatchData(String pattern, boolean isProxyTargetClass, int scope, IWorkingSet[] workingSets) { this.expression = pattern; this.isProxyTargetClass = isProxyTargetClass; this.scope = scope; this.workingSets = workingSets; } public String getExpression() { return expression; } public int getScope() { return scope; } public IWorkingSet[] getWorkingSets() { return workingSets; } public boolean isProxyTargetClass() { return isProxyTargetClass; } public void store(IDialogSettings settings) { settings.put("pattern", expression); settings.put("isProxyTargetClass", isProxyTargetClass); settings.put("scope", scope); if (workingSets != null) { String[] wsIds = new String[workingSets.length]; for (int i = 0; i < workingSets.length; i++) { wsIds[i] = workingSets[i].getId(); } settings.put("workingSets", wsIds); } else { settings.put("workingSets", new String[0]); } } } private static final int HISTORY_SIZE = 12; // Dialog store id constants private final static String PAGE_NAME = "PointcutMatcherPage"; private static final String STORE_PROXY_TARGET_CLASS = "PROXY_TARGET_CLASS"; private final static String STORE_HISTORY = "HISTORY"; private final static String STORE_HISTORY_SIZE = "HISTORY_SIZE"; private final List<PointcutMatchData> previousPointcutMatchData = new ArrayList<PointcutMatchData>(); private boolean firstTime = true; private IDialogSettings dialogSettings; private boolean isProxyTargetClass; private Combo expressionCombo; private ISearchPageContainer searchContainer; private CLabel statusLabel; private Button proxyTargetClassCheckbox; private PointcutMatcherScope scope; public PointcutMatcherSearchPage() { // required } public PointcutMatcherSearchPage(String title) { super(title); } public PointcutMatcherSearchPage(String title, ImageDescriptor image) { super(title, image); } /** * Creates the page's content. */ public void createControl(Composite parent) { initializeDialogUnits(parent); readConfiguration(); Composite result = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(2, false); layout.horizontalSpacing = 10; result.setLayout(layout); Control expressionComposite = createExpression(result); expressionComposite.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 2, 1)); Label separator = new Label(result, SWT.NONE); separator.setVisible(false); GridData data = new GridData(GridData.FILL, GridData.FILL, false, false, 2, 1); data.heightHint = convertHeightInCharsToPixels(1) / 3; separator.setLayoutData(data); setControl(result); Dialog.applyDialogFont(result); } private Control createExpression(Composite parent) { // Group with grid layout with 2 columns Composite group = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(2, false); layout.marginWidth = 0; layout.marginHeight = 0; group.setLayout(layout); // Expression text + info Label label = new Label(group, SWT.LEFT); label.setText(PointcutMatcherMessages.MatcherPage_expression); label.setLayoutData(new GridData(GridData.FILL, GridData.FILL, false, false, 2, 1)); // Expression combo expressionCombo = new Combo(group, SWT.SINGLE | SWT.BORDER); expressionCombo.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { handlePatternSelected(); updateOKStatus(); } }); expressionCombo.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { updateOKStatus(); } }); GridData data = new GridData(GridData.FILL, GridData.FILL, true, false, 1, 1); data.widthHint = convertWidthInCharsToPixels(50); expressionCombo.setLayoutData(data); // proxy target class checkbox proxyTargetClassCheckbox = new Button(group, SWT.CHECK); proxyTargetClassCheckbox .setText(PointcutMatcherMessages.MatcherPage_proxyTargetClass); proxyTargetClassCheckbox.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { isProxyTargetClass = proxyTargetClassCheckbox.getSelection(); } }); proxyTargetClassCheckbox.setLayoutData(new GridData(GridData.FILL, GridData.FILL, false, false, 1, 1)); // Text line which explains the special characters statusLabel = new CLabel(group, SWT.LEAD); statusLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); statusLabel.setFont(group.getFont()); statusLabel.setAlignment(SWT.LEFT); statusLabel.setText(PointcutMatcherMessages.MatcherPage_expressionHint); return group; } @Override public void dispose() { writeConfiguration(); super.dispose(); } private PointcutMatchData findInPrevious(String pattern) { for (PointcutMatchData element : previousPointcutMatchData) { if (pattern.equals(element.getExpression())) { return element; } } return null; } private PointcutMatchData getDefaultInitValues() { if (!previousPointcutMatchData.isEmpty()) { return previousPointcutMatchData.get(0); } return new PointcutMatchData("", false); } /** * Returns the page settings for this search page. * @return the page settings to be used */ private IDialogSettings getDialogSettings() { IDialogSettings settings = PointcutMatcherPlugin.getDefault() .getDialogSettings(); dialogSettings = settings.getSection(PAGE_NAME); if (dialogSettings == null) { dialogSettings = settings.addNewSection(PAGE_NAME); } return dialogSettings; } private String getExpression() { return expressionCombo.getText(); } /** * Returns search pattern data and update previous searches. An existing * entry will be updated. */ private PointcutMatchData getPatternData() { String pattern = getExpression(); PointcutMatchData match = findInPrevious(pattern); if (match != null) { previousPointcutMatchData.remove(match); } match = new PointcutMatchData(pattern, isProxyTargetClass(), searchContainer.getSelectedScope(), searchContainer .getSelectedWorkingSets()); previousPointcutMatchData.add(0, match); // insert on top return match; } private String[] getPreviousExpressions() { // Search results are not persistent int patternCount = previousPointcutMatchData.size(); String[] patterns = new String[patternCount]; for (int i = 0; i < patternCount; i++) { patterns[i] = (previousPointcutMatchData.get(i)).getExpression(); } return patterns; } private void handlePatternSelected() { int selectionIndex = expressionCombo.getSelectionIndex(); if (selectionIndex < 0 || selectionIndex >= previousPointcutMatchData.size()) { return; } PointcutMatchData data = previousPointcutMatchData .get(selectionIndex); expressionCombo.setText(data.getExpression()); isProxyTargetClass = data.isProxyTargetClass(); proxyTargetClassCheckbox.setSelection(data.isProxyTargetClass()); if (data.getWorkingSets() != null) { searchContainer.setSelectedWorkingSets(data.getWorkingSets()); } else { searchContainer.setSelectedScope(data.getScope()); } } private void initSelections() { PointcutMatchData initData = null; // TODO handle seclection // ISelection sel = searchContainer.getSelection(); // if (sel instanceof IStructuredSelection) { // initData = tryStructuredSelection((IStructuredSelection) sel); // } else if (sel instanceof ITextSelection) { // initData = trySimpleTextSelection((ITextSelection) sel); // } if (initData == null) { initData = getDefaultInitValues(); } expressionCombo.setText(initData.getExpression()); proxyTargetClassCheckbox.setSelection(initData.isProxyTargetClass()); } private boolean isProxyTargetClass() { return proxyTargetClassCheckbox.getSelection(); } private boolean isValidExpression() { if (getExpression().length() == 0) { return false; } // TODO CD move validation /* * try { AspectJExpressionPointcut pointcut = new * AspectJExpressionPointcut(); * pointcut.setExpression(getPointcutExpression()); * pointcut.matches(getClass()); } catch (Exception e) { * e.printStackTrace(); } */ return true; } public boolean performAction() { switch (searchContainer.getSelectedScope()) { case ISearchPageContainer.SELECTION_SCOPE: scope = PointcutMatcherScope.newSearchScope(searchContainer .getSelection(), false); break; case ISearchPageContainer.WORKING_SET_SCOPE: scope = PointcutMatcherScope.newSearchScope(searchContainer .getSelectedWorkingSets()); break; case ISearchPageContainer.SELECTED_PROJECTS_SCOPE: scope = PointcutMatcherScope.newSearchScope(searchContainer .getSelection(), true); break; default: scope = PointcutMatcherScope.newSearchScope(); } PointcutMatchData data = getPatternData(); ISearchQuery query = new PointcutMatchQuery(scope, data.getExpression(), data.isProxyTargetClass()); NewSearchUI.activateSearchResultView(); NewSearchUI.runQueryInBackground(query); return true; } /** * Initializes itself from the stored page settings. */ private void readConfiguration() { IDialogSettings s = getDialogSettings(); isProxyTargetClass = s.getBoolean(STORE_PROXY_TARGET_CLASS); try { int historySize = s.getInt(STORE_HISTORY_SIZE); for (int i = 0; i < historySize; i++) { IDialogSettings histSettings = s.getSection(STORE_HISTORY + i); if (histSettings != null) { PointcutMatchData data = PointcutMatchData .create(histSettings); if (data != null) { previousPointcutMatchData.add(data); } } } } catch (NumberFormatException e) { // ignore } } public void setContainer(ISearchPageContainer container) { searchContainer = container; } @Override public void setVisible(boolean visible) { if (visible && expressionCombo != null) { if (firstTime) { firstTime = false; // Set item and text here to prevent page from resizing expressionCombo.setItems(getPreviousExpressions()); initSelections(); } expressionCombo.setFocus(); } updateOKStatus(); super.setVisible(visible); } // private SearchData tryStructuredSelection(IStructuredSelection selection) // { // if (selection == null || selection.size() > 1) { // return null; // } // Object o = selection.getFirstElement(); // SearchData res = null; // if (res == null && o instanceof IAdaptable) { // IWorkbenchAdapter adapter = (IWorkbenchAdapter) // ((IAdaptable)o).getAdapter(IWorkbenchAdapter.class); // if (adapter != null) { // return new SearchData(SEARCH_FOR_BEAN_CLASS, adapter.getLabel(o), // isCaseSensitive, false); // } // } // return res; // } // private SearchData trySimpleTextSelection(ITextSelection selection) { // String selectedText= selection.getText(); // if (selectedText != null && selectedText.length() > 0) { // int i = 0; // TODO while (i < selectedText.length() && // !StringUtils.isLineDelimiterChar(selectedText.charAt(i))) { // while (i < selectedText.length()) { // i++; // } // if (i > 0) { // return new SearchData(SEARCH_FOR_BEAN_CLASS, // selectedText.substring(0, i), isCaseSensitive, false); // } // } // return null; // } final void updateOKStatus() { boolean isValid = isValidExpression(); searchContainer.setPerformActionEnabled(isValid); } /** * Stores it current configuration in the dialog store. */ private void writeConfiguration() { IDialogSettings s = getDialogSettings(); s.put(STORE_PROXY_TARGET_CLASS, isProxyTargetClass); int historySize = Math.min(previousPointcutMatchData.size(), HISTORY_SIZE); s.put(STORE_HISTORY_SIZE, historySize); for (int i = 0; i < historySize; i++) { IDialogSettings histSettings = s.addNewSection(STORE_HISTORY + i); PointcutMatchData data = (previousPointcutMatchData.get(i)); data.store(histSettings); } } }