/******************************************************************************* * Copyright (c) 2012 - 2013 GoPivotal, Inc. * 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: * GoPivotal, Inc. - initial API and implementation *******************************************************************************/ package org.springframework.ide.eclipse.config.ui.editors; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.ui.IJavaElementSearchConstants; import org.eclipse.jdt.ui.JavaUI; import org.eclipse.jface.window.Window; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.dialogs.SelectionDialog; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.Section; import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement; import org.springframework.ide.eclipse.config.ui.ConfigUiPlugin; import org.springframework.ide.eclipse.config.ui.hyperlinks.AdviceMethodHyperlinkProvider; import org.springframework.ide.eclipse.config.ui.hyperlinks.BeanHyperlinkProvider; import org.springframework.ide.eclipse.config.ui.hyperlinks.ClassHyperlinkProvider; import org.springframework.ide.eclipse.config.ui.hyperlinks.FactoryMethodHyperlinkProvider; import org.springframework.ide.eclipse.config.ui.hyperlinks.FieldHyperlinkProvider; import org.springframework.ide.eclipse.config.ui.hyperlinks.ImportHyperlinkProvider; import org.springframework.ide.eclipse.config.ui.hyperlinks.InitDestroyMethodHyperlinkProvider; import org.springframework.ide.eclipse.config.ui.hyperlinks.ListenerMethodHyperlinkProvider; import org.springframework.ide.eclipse.config.ui.hyperlinks.LookupReplaceMethodHyperlinkProvider; import org.springframework.ide.eclipse.config.ui.hyperlinks.PointcutReferenceHyperlinkProvider; import org.springframework.ide.eclipse.config.ui.hyperlinks.PropertyNameHyperlinkProvider; import org.springframework.ide.eclipse.config.ui.hyperlinks.ToolAnnotationBasedHyperlinkProvider; import org.springframework.ide.eclipse.config.ui.hyperlinks.XmlBackedHyperlinkProvider; import org.springframework.ide.eclipse.config.ui.widgets.ButtonAttribute; import org.springframework.ide.eclipse.config.ui.widgets.ComboAttribute; import org.springframework.ide.eclipse.config.ui.widgets.HyperlinkedComboAttribute; import org.springframework.ide.eclipse.config.ui.widgets.HyperlinkedTextAttribute; import org.springframework.ide.eclipse.config.ui.widgets.TextAreaAttribute; import org.springframework.ide.eclipse.config.ui.widgets.TextAttribute; import org.springframework.ide.eclipse.config.ui.wizards.ExtendedNewClassCreationWizard; import org.springsource.ide.eclipse.commons.core.StatusHandler; /** * @author Leo Dos Santos * @author Steffen Pingel * @since 2.3.4 */ @SuppressWarnings("restriction") public abstract class AbstractConfigDetailsSectionPart extends AbstractConfigSectionPart { /** * An abstract implementation of {@link HyperlinkedComboAttribute} designed * to operate on an XML attribute. Clients must implement the * <code>openHyperlink</code> method. */ protected abstract class XmlBackedHyperlinkComboAttribute extends HyperlinkedComboAttribute { public XmlBackedHyperlinkComboAttribute(Composite client, FormToolkit toolkit, String attrName) { this(client, toolkit, attrName, false); } public XmlBackedHyperlinkComboAttribute(Composite client, FormToolkit toolkit, String attrName, boolean required) { super(client, toolkit, attrName, null, required); } @Override public void modifyAttribute() { editAttribute(attr, combo.getItem(combo.getSelectionIndex())); } @Override public void update() { setComboSelection(combo, getAttributeValue(attr)); } } /** * An abstract implementation of {@link HyperlinkedTextAttribute} designed * to operate on an XML attribute. Clients must implement the * <code>openHyperlink</code> method. */ protected abstract class XmlBackedHyperlinkTextAttribute extends HyperlinkedTextAttribute { public XmlBackedHyperlinkTextAttribute(Composite client, FormToolkit toolkit, String attrName) { this(client, toolkit, attrName, false); } public XmlBackedHyperlinkTextAttribute(Composite client, FormToolkit toolkit, String attrName, boolean required) { super(client, toolkit, attrName, required); } @Override public void modifyAttribute() { editAttribute(attr, text.getText()); } @Override public void update() { setTextValue(text, getAttributeValue(attr)); } } private final FormToolkit toolkit; private final SpringConfigInputAccessor delegate; public AbstractConfigDetailsSectionPart(AbstractConfigEditor editor, IDOMElement input, Composite parent, FormToolkit toolkit) { super(editor, input, parent, toolkit, Section.TITLE_BAR | Section.DESCRIPTION); this.toolkit = toolkit; delegate = new SpringConfigInputAccessor(editor, input); } /** * Creates a {@link HyperlinkedTextAttribute} widget set for displaying an * attribute that refers to an AOP advice method. Clicking the hyperlink * will open the class file at the method displayed in the text field. * * @param client the parent composite * @param attr the attribute name * @param required denotes whether this is a required field * @return {@link HyperlinkedTextAttribute} widget set */ protected HyperlinkedTextAttribute createAdviceMethodAttribute(Composite client, String attr, boolean required) { HyperlinkedTextAttribute linkAttr = new XmlBackedHyperlinkTextAttribute(client, toolkit, attr, required) { public void openHyperlink() { XmlBackedHyperlinkProvider provider = new AdviceMethodHyperlinkProvider(getConfigEditor() .getTextViewer(), getInput(), attr); provider.open(text.getText()); } }; linkAttr.createAttribute(2); return linkAttr; } protected abstract void createAttributes(Composite client); /** * Creates a {@link HyperlinkedTextAttribute} widget set for displaying an * attribute that refers to another Spring bean. Clicking the hyperlink will * open the configuration file containing the bean definition. * * @param client the parent composite * @param attr the attribute name * @param required denotes whether this is a required field * @return {@link HyperlinkedTextAttribute} widget set */ protected HyperlinkedTextAttribute createBeanAttribute(Composite client, String attr, boolean required) { HyperlinkedTextAttribute linkAttr = new XmlBackedHyperlinkTextAttribute(client, toolkit, attr, required) { public void openHyperlink() { XmlBackedHyperlinkProvider provider = new BeanHyperlinkProvider(getConfigEditor().getTextViewer(), getInput(), attr); provider.open(text.getText()); } }; linkAttr.createAttribute(2); return linkAttr; } /** * Creates a {@link ButtonAttribute} widget set for displaying an attribute * representing a Java class type. Clicking the hyperlink will open the * class file displayed in the text field, or open a class creation wizard * if the text field is empty. Clicking the button will invoke the open type * dialog. * * @param client the parent composite * @param attr the attribute name * @param includeInterfaces include interfaces in the proposals * @param required denotes whether this is a required field * @return {@link ButtonAttribute} widget set */ protected ButtonAttribute createClassAttribute(Composite client, String attr, final boolean includeInterfaces, boolean required) { ButtonAttribute buttonAttr = new ButtonAttribute(client, toolkit, attr, required) { @Override public void browse() { doOpenTypeDialog(attr, text.getText(), includeInterfaces); } @Override public void modifyAttribute() { editAttribute(attr, text.getText()); } public void openHyperlink() { XmlBackedHyperlinkProvider provider = new ClassHyperlinkProvider(getConfigEditor().getTextViewer(), getInput(), attr); if (!provider.open(text.getText())) { openNewClassWizard(attr, text.getText()); } } @Override public void update() { setTextValue(text, getAttributeValue(attr)); } }; buttonAttr.createAttribute(); return buttonAttr; } /** * Creates a {@link ComboAttribute} widget set for displaying an attribute * that can have multiple known values. * * @param client the parent composite * @param attr the attribute name * @param values an array of known values * @param required denotes whether this is a required field * @return {@link ComboAttribute} widget set */ protected ComboAttribute createComboAttribute(Composite client, String attr, String[] values, boolean required) { ComboAttribute comboAttr = new ComboAttribute(client, toolkit, attr, values, required) { @Override public void modifyAttribute() { editAttribute(attr, combo.getItem(combo.getSelectionIndex())); } @Override public void update() { setComboSelection(combo, getAttributeValue(attr)); } }; comboAttr.createAttribute(2); return comboAttr; } @Override public void createContent() { Section detailsSection = getSection(); detailsSection.setLayout(new GridLayout()); detailsSection.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_BEGINNING)); detailsSection.setText(Messages.getString("ToolingAwareDetailsPart.DETAILS_SECTION_TITLE")); //$NON-NLS-1$ detailsSection.setDescription(Messages.getString("ToolingAwareDetailsPart.DETAILS_SECTION_DESCRIPTION")); //$NON-NLS-1$) Composite detailsClient = toolkit.createComposite(detailsSection); detailsClient.setLayout(new GridLayout(3, false)); detailsClient.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); detailsSection.setClient(detailsClient); createAttributes(detailsClient); toolkit.paintBordersFor(detailsClient); } /** * Creates a {@link HyperlinkedTextAttribute} widget set for displaying an * attribute that refers to a Java method. Clicking the hyperlink will open * the class file at the method displayed in the text field. * * @param client the parent composite * @param attr the attribute name * @param required denotes whether this is a required field * @return {@link HyperlinkedTextAttribute} widget set */ protected HyperlinkedTextAttribute createFactoryMethodAttribute(Composite client, String attr, boolean required) { HyperlinkedTextAttribute linkAttr = new XmlBackedHyperlinkTextAttribute(client, toolkit, attr, required) { public void openHyperlink() { XmlBackedHyperlinkProvider provider = new FactoryMethodHyperlinkProvider(getConfigEditor() .getTextViewer(), getInput(), attr); provider.open(text.getText()); } }; linkAttr.createAttribute(2); return linkAttr; } /** * Creates a {@link HyperlinkedTextAttribute} widget set for displaying an * attribute that refers to a Java method. Clicking the hyperlink will open * the class file at the method displayed in the text field. * * @param client the parent composite * @param attr the attribute name * @param referenceNode the name of the factory bean reference node * @param required denotes whether this is a required field * @return {@link HyperlinkedTextAttribute} widget set */ protected HyperlinkedTextAttribute createFactoryMethodAttribute(Composite client, String attr, final String referenceNode, boolean required) { HyperlinkedTextAttribute linkAttr = new XmlBackedHyperlinkTextAttribute(client, toolkit, attr, required) { public void openHyperlink() { XmlBackedHyperlinkProvider provider = new FactoryMethodHyperlinkProvider(getConfigEditor() .getTextViewer(), getInput(), attr, referenceNode); provider.open(text.getText()); } }; linkAttr.createAttribute(2); return linkAttr; } /** * Creates a {@link HyperlinkedTextAttribute} widget set for displaying an * attribute that refers to a field inside a class. Clicking the hyperlink * will open the class file specified by the bean. * * @param client the parent composite * @param attr the attribute name * @param required denotes whether this is a required field * @return {@link HyperlinkedTextAttribute} widget set */ protected HyperlinkedTextAttribute createFieldAttribute(Composite client, String attr, boolean required) { HyperlinkedTextAttribute linkAttr = new XmlBackedHyperlinkTextAttribute(client, toolkit, attr, required) { public void openHyperlink() { XmlBackedHyperlinkProvider provider = new FieldHyperlinkProvider(getConfigEditor().getTextViewer(), getInput(), attr); provider.open(text.getText()); } }; linkAttr.createAttribute(2); return linkAttr; } /** * Creates a {@link HyperlinkedTextAttribute} widget set for displaying an * attribute that refers to an external resource. Clicking the hyperlink * will open the referenced resource. * * @param client the parent composite * @param attr the attribute name * @param required denotes whether this is a required field * @return {@link HyperlinkedTextAttribute} widget set */ protected HyperlinkedTextAttribute createImportAttribute(Composite client, String attr, boolean required) { HyperlinkedTextAttribute linkAttr = new XmlBackedHyperlinkTextAttribute(client, toolkit, attr, required) { public void openHyperlink() { XmlBackedHyperlinkProvider provider = new ImportHyperlinkProvider(getConfigEditor().getTextViewer(), getInput(), attr); provider.open(text.getText()); } }; linkAttr.createAttribute(2); return linkAttr; } /** * Creates a {@link HyperlinkedTextAttribute} widget set for displaying an * attribute that refers to a Java method. Clicking the hyperlink will open * the class file at the method displayed in the text field. * * @param client the parent composite * @param attr the attribute name * @param required denotes whether this is a required field * @return {@link HyperlinkedTextAttribute} widget set */ protected HyperlinkedTextAttribute createInitDestroyMethodAttribute(Composite client, String attr, boolean required) { HyperlinkedTextAttribute linkAttr = new XmlBackedHyperlinkTextAttribute(client, toolkit, attr, required) { public void openHyperlink() { XmlBackedHyperlinkProvider provider = new InitDestroyMethodHyperlinkProvider(getConfigEditor() .getTextViewer(), getInput(), attr); provider.open(text.getText()); } }; linkAttr.createAttribute(2); return linkAttr; } /** * Creates a {@link HyperlinkedTextAttribute} widget set for displaying an * attribute that refers to a Java method. Clicking the hyperlink will open * the class file at the method displayed in the text field. * * @param client the parent composite * @param attr the attribute name * @param required denotes whether this is a required field * @return {@link HyperlinkedTextAttribute} widget set */ protected HyperlinkedTextAttribute createListenerMethodAttribute(Composite client, String attr, boolean required) { HyperlinkedTextAttribute linkAttr = new XmlBackedHyperlinkTextAttribute(client, toolkit, attr, required) { public void openHyperlink() { XmlBackedHyperlinkProvider provider = new ListenerMethodHyperlinkProvider(getConfigEditor() .getTextViewer(), getInput(), attr); provider.open(text.getText()); } }; linkAttr.createAttribute(2); return linkAttr; } /** * Creates a {@link HyperlinkedTextAttribute} widget set for displaying an * attribute that refers to a Java method. Clicking the hyperlink will open * the class file at the method displayed in the text field. * * @param client the parent composite * @param attr the attribute name * @param required denotes whether this is a required field * @return {@link HyperlinkedTextAttribute} widget set */ protected HyperlinkedTextAttribute createLookupReplaceMethodAttribute(Composite client, String attr, boolean required) { HyperlinkedTextAttribute linkAttr = new XmlBackedHyperlinkTextAttribute(client, toolkit, attr, required) { public void openHyperlink() { XmlBackedHyperlinkProvider provider = new LookupReplaceMethodHyperlinkProvider(getConfigEditor() .getTextViewer(), getInput(), attr); provider.open(text.getText()); } }; linkAttr.createAttribute(2); return linkAttr; } /** * Creates a {@link HyperlinkedTextAttribute} widget set for displaying an * attribute that refers to an AOP pointcut. Clicking the hyperlink will * open the configuration file containing the pointcut definition. * * @param client the parent composite * @param attr the attribute name * @param required denotes whether this is a required field * @return {@link HyperlinkedTextAttribute} widget set */ protected HyperlinkedTextAttribute createPointcutAttribute(Composite client, String attr, boolean required) { HyperlinkedTextAttribute linkAttr = new XmlBackedHyperlinkTextAttribute(client, toolkit, attr, required) { public void openHyperlink() { XmlBackedHyperlinkProvider provider = new PointcutReferenceHyperlinkProvider(getConfigEditor() .getTextViewer(), getInput(), attr); provider.open(text.getText()); } }; linkAttr.createAttribute(2); return linkAttr; } /** * Creates a {@link HyperlinkedTextAttribute} widget set for displaying an * attribute that refers to a Java method. Clicking the hyperlink will open * the class file at the method displayed in the text field. * * @param client the parent composite * @param attr the attribute name * @param required denotes whether this is a required field * @return {@link HyperlinkedTextAttribute} widget set */ protected HyperlinkedTextAttribute createPropertyNameAttribute(Composite client, String attr, boolean required) { HyperlinkedTextAttribute linkAttr = new XmlBackedHyperlinkTextAttribute(client, toolkit, attr, required) { public void openHyperlink() { XmlBackedHyperlinkProvider provider = new PropertyNameHyperlinkProvider(getConfigEditor() .getTextViewer(), getInput(), attr); provider.open(text.getText()); } }; linkAttr.createAttribute(2); return linkAttr; } /** * Creates a {@link TextAreaAttribute} widget set for displaying a block of * text nested between an element's start and end tags. * * @param client the parent composite * @param elem the element name * @return {@link TextAreaAttribute} widget set */ protected TextAreaAttribute createTextArea(Composite client, String elem) { TextAreaAttribute textElem = new TextAreaAttribute(client, toolkit, elem) { @Override public void modifyAttribute() { editElement(text.getText()); } @Override public void update() { setTextValue(text, getElementValue()); } }; textElem.createAttribute(2); return textElem; } /** * Creates a {@link TextAttribute} widget set for displaying an attribute * that can have any text value. * * @param client the parent composite * @param attr the attribute name * @param required denotes whether this is a required field * @return {@link TextAttribute} widget set */ protected TextAttribute createTextAttribute(Composite client, String attr, boolean required) { TextAttribute textAttr = new TextAttribute(client, toolkit, attr, required) { @Override public void modifyAttribute() { editAttribute(attr, text.getText()); } @Override public void update() { setTextValue(text, getAttributeValue(attr)); } }; textAttr.createAttribute(2); return textAttr; } /** * Creates a {@link HyperlinkedTextAttribute} widget set for displaying an * attribute whose reference is defined through a tool annotation. Clicking * the hyperlink will open to an appropriate file (ie. a class file, or a * configuration file) containing the reference displayed in the text field. * * @param client the parent composite * @param attr the attribute name * @param required denotes whether this is a required field * @return {@link HyperlinkedTextAttribute} widget set */ protected HyperlinkedTextAttribute createToolAnnotationAttribute(Composite client, String attr, boolean required) { HyperlinkedTextAttribute linkAttr = new XmlBackedHyperlinkTextAttribute(client, toolkit, attr, required) { public void openHyperlink() { XmlBackedHyperlinkProvider provider = new ToolAnnotationBasedHyperlinkProvider(getConfigEditor() .getTextViewer(), getInput(), attr); provider.open(text.getText()); } }; linkAttr.createAttribute(2); return linkAttr; } private void doOpenTypeDialog(String attr, String filter, boolean includeInterfaces) { filter = filter.replace('$', '.'); try { if (filter == null) { filter = ""; //$NON-NLS-1$ } int scope; if (includeInterfaces) { scope = IJavaElementSearchConstants.CONSIDER_CLASSES_AND_INTERFACES; } else { scope = IJavaElementSearchConstants.CONSIDER_CLASSES; } SelectionDialog dialog = JavaUI.createTypeDialog(getConfigEditor().getSite().getShell(), PlatformUI .getWorkbench().getProgressService(), null, scope, false, filter); dialog.setTitle(Messages.getString("AbstractNamespaceDetailsPart.TYPE_SELECTION_DIALOG_TITLE")); //$NON-NLS-1$ if (dialog.open() == Window.OK) { IType type = (IType) dialog.getResult()[0]; String newValue = type.getFullyQualifiedName('$'); editAttribute(attr, newValue); } } catch (JavaModelException e) { StatusHandler.log(new Status(IStatus.ERROR, ConfigUiPlugin.PLUGIN_ID, Messages .getString("AbstractNamespaceDetailsPart.ERROR_OPENING_DIALOG"), e)); //$NON-NLS-1$ } } private void editAttribute(String attrName, String newValue) { delegate.editAttribute(attrName, newValue); } private void editElement(String elemValue) { delegate.editElement(elemValue); } private String getAttributeValue(String attr) { return delegate.getAttributeValue(attr); } private String getElementValue() { return delegate.getElementValue(); } private void openNewClassWizard(String attr, String name) { name = name.replace('$', '.'); IProject project = getConfigEditor().getResourceFile().getProject(); ExtendedNewClassCreationWizard wizard = new ExtendedNewClassCreationWizard(project, name, true); wizard.init(PlatformUI.getWorkbench(), null); WizardDialog dialog = new WizardDialog(getConfigEditor().getSite().getShell(), wizard); dialog.create(); if (dialog.open() == Window.OK) { String newValue = wizard.getQualifiedName(); editAttribute(attr, newValue); } } /** * Sets the selection on the given combo to the given value. * * @param combo the combo to modify * @param value the new combo value */ protected void setComboSelection(Combo combo, String value) { for (int i = 0; i < combo.getItemCount(); i++) { String item = combo.getItem(i); if (item.equals(value) && combo.getSelectionIndex() != i) { combo.select(i); break; } } } /** * Sets the text on the given text field to the given value. * * @param text the text field to modify * @param value the new text field value */ protected void setTextValue(Text text, String value) { if (!text.getText().equals(value)) { text.setText(value); text.setSelection(text.getText().length()); } }; }