/*******************************************************************************
* Copyright (c) 2009, 2012 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.beans.ui.preferences;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
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.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.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.springframework.ide.eclipse.beans.core.BeansCorePlugin;
import org.springframework.ide.eclipse.beans.ui.BeansUIImages;
import org.springframework.ide.eclipse.beans.ui.namespaces.INamespaceDefinition;
import org.springframework.ide.eclipse.beans.ui.namespaces.NamespaceUtils;
import org.springframework.ide.eclipse.core.SpringCorePreferences;
import org.springframework.ide.eclipse.ui.dialogs.ProjectAndPreferencePage;
import org.springframework.util.StringUtils;
/**
* {@link ProjectAndPreferencePage} that allows to configure default namespace versions.
* @author Christian Dupuis
* @since 2.2.5
*/
@SuppressWarnings("deprecation")
public class NamespaceVersionPreferencePage extends ProjectAndPreferencePage {
public static final String PREF_ID = "org.springframework.ide.eclipse.beans.ui.namespaces.preferencePage"; //$NON-NLS-1$
public static final String PROP_ID = "org.springframework.ide.eclipse.beans.ui.namespaces.projectPropertyPage"; //$NON-NLS-1$
public class XsdLabelProvider extends LabelProvider {
public Image getImage(Object element) {
if (element instanceof INamespaceDefinition) {
INamespaceDefinition xsdDef = (INamespaceDefinition) element;
return xsdDef.getNamespaceImage();
}
return BeansUIImages.getImage(BeansUIImages.IMG_OBJS_XSD);
}
public String getText(Object element) {
if (element instanceof INamespaceDefinition) {
INamespaceDefinition xsdDef = (INamespaceDefinition) element;
return prefixes.get(xsdDef) + " - " + xsdDef.getNamespaceURI();
}
return "";
}
}
public class VersionLabelProvider extends LabelProvider {
public Image getImage(Object element) {
return BeansUIImages.getImage(BeansUIImages.IMG_OBJS_XSD);
}
public String getText(Object element) {
if (element instanceof String) {
String label = (String) element;
return label;
}
return super.getText(element);
}
}
private class XsdConfigContentProvider implements IStructuredContentProvider {
public Object[] getElements(Object obj) {
return getNamespaceDefinitionList().toArray();
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
public void dispose() {
}
}
private class VersionContentProvider implements IStructuredContentProvider {
public Object[] getElements(Object obj) {
if (obj instanceof INamespaceDefinition) {
return ((INamespaceDefinition) obj).getSchemaLocations().toArray();
}
else {
return new Object[0];
}
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
public void dispose() {
}
}
private static final int XSD_LIST_VIEWER_HEIGHT = 150;
private static final int LIST_VIEWER_WIDTH = 340;
private TableViewer xsdViewer;
private CheckboxTableViewer versionViewer;
private Button versionCheckbox;
private Button classpathCheckbox;
private Button disableNamespaceCachingCheckbox;
private Map<INamespaceDefinition, String> versions = new ConcurrentHashMap<INamespaceDefinition, String>();
private Map<INamespaceDefinition, String> prefixes = new ConcurrentHashMap<INamespaceDefinition, String>();
private INamespaceDefinition selectedNamespaceDefinition;
private Text prefixText;
private volatile List<INamespaceDefinition> namespaceDefinitionList = new CopyOnWriteArrayList<INamespaceDefinition>();
private volatile boolean loading = false;
private synchronized List<INamespaceDefinition> getNamespaceDefinitionList() {
if ((namespaceDefinitionList == null || namespaceDefinitionList.size() == 0) && !loading) {
loading = true;
NamespaceUtils.getNamespaceDefinitions(getProject(), new NamespaceUtils.INamespaceDefinitionTemplate() {
public void doWithNamespaceDefinitions(INamespaceDefinition[] namespaceDefinitions, IProject project) {
namespaceDefinitionList = new ArrayList<INamespaceDefinition>(Arrays.asList(namespaceDefinitions));
versions.clear();
prefixes.clear();
if (isProjectPreferencePage()) {
SpringCorePreferences prefs = SpringCorePreferences.getProjectPreferences(getProject(),
BeansCorePlugin.PLUGIN_ID);
for (INamespaceDefinition namespace : namespaceDefinitions) {
String version = prefs.getString(BeansCorePlugin.NAMESPACE_DEFAULT_VERSION_PREFERENCE_ID
+ namespace.getNamespaceURI(), "");
versions.put(namespace, version);
String prefix = prefs.getString(BeansCorePlugin.NAMESPACE_PREFIX_PREFERENCE_ID
+ namespace.getNamespaceURI(), namespace.getDefaultNamespacePrefix());
prefixes.put(namespace, prefix);
}
}
else {
Preferences prefs = BeansCorePlugin.getDefault().getPluginPreferences();
for (INamespaceDefinition namespace : namespaceDefinitions) {
String version = prefs.getString(BeansCorePlugin.NAMESPACE_DEFAULT_VERSION_PREFERENCE_ID
+ namespace.getNamespaceURI());
versions.put(namespace, version);
String prefix = prefs.getString(BeansCorePlugin.NAMESPACE_PREFIX_PREFERENCE_ID
+ namespace.getNamespaceURI());
prefixes.put(namespace, (StringUtils.hasLength(prefix) ? prefix : namespace
.getDefaultNamespacePrefix()));
}
}
Display.getDefault().asyncExec(new Runnable() {
public void run() {
refresh();
}
});
loading = false;
}
});
}
return namespaceDefinitionList;
}
public Composite createPreferenceContent(Composite parent) {
boolean versionClasspath = true;
boolean useClasspath = true;
boolean disableCachingNamespaces = false;
if (isProjectPreferencePage()) {
SpringCorePreferences prefs = SpringCorePreferences.getProjectPreferences(getProject(),
BeansCorePlugin.PLUGIN_ID);
versionClasspath = prefs.getBoolean(BeansCorePlugin.NAMESPACE_DEFAULT_FROM_CLASSPATH_ID, true);
useClasspath = prefs.getBoolean(BeansCorePlugin.LOAD_NAMESPACEHANDLER_FROM_CLASSPATH_ID, true);
disableCachingNamespaces = prefs.getBoolean(BeansCorePlugin.DISABLE_CACHING_FOR_NAMESPACE_LOADING_ID, false);
}
else {
Preferences prefs = BeansCorePlugin.getDefault().getPluginPreferences();
versionClasspath = prefs.getBoolean(BeansCorePlugin.NAMESPACE_DEFAULT_FROM_CLASSPATH_ID);
useClasspath = prefs.getBoolean(BeansCorePlugin.LOAD_NAMESPACEHANDLER_FROM_CLASSPATH_ID);
disableCachingNamespaces = prefs.getBoolean(BeansCorePlugin.DISABLE_CACHING_FOR_NAMESPACE_LOADING_ID);
}
initializeDialogUnits(parent);
// top level group
Composite composite = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
composite.setLayout(layout);
composite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL));
composite.setFont(parent.getFont());
versionCheckbox = new Button(composite, SWT.CHECK);
versionCheckbox.setText("Use highest XSD version that is available on the project's classpath");
versionCheckbox.setSelection(versionClasspath);
classpathCheckbox = new Button(composite, SWT.CHECK);
classpathCheckbox.setText("Load NamespaceHandlers and XSDs from project's classpath");
classpathCheckbox.setSelection(useClasspath);
classpathCheckbox.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
if (isProjectPreferencePage()) {
if (useProjectSettings()) {
SpringCorePreferences.getProjectPreferences(getProject(), BeansCorePlugin.PLUGIN_ID).putBoolean(
BeansCorePlugin.PROJECT_PROPERTY_ID, true);
}
else {
SpringCorePreferences.getProjectPreferences(getProject(), BeansCorePlugin.PLUGIN_ID).putBoolean(
BeansCorePlugin.PROJECT_PROPERTY_ID, false);
}
SpringCorePreferences.getProjectPreferences(getProject(), BeansCorePlugin.PLUGIN_ID).putBoolean(
BeansCorePlugin.LOAD_NAMESPACEHANDLER_FROM_CLASSPATH_ID, classpathCheckbox.getSelection());
}
else {
BeansCorePlugin.getDefault().getPluginPreferences().setValue(
BeansCorePlugin.LOAD_NAMESPACEHANDLER_FROM_CLASSPATH_ID, classpathCheckbox.getSelection());
BeansCorePlugin.getDefault().savePluginPreferences();
}
namespaceDefinitionList.clear();
refresh();
disableNamespaceCachingCheckbox.setEnabled(classpathCheckbox.getSelection());
}
});
disableNamespaceCachingCheckbox = new Button(composite, SWT.CHECK);
disableNamespaceCachingCheckbox.setText("Disable caching for namespace resolving and loading");
disableNamespaceCachingCheckbox.setSelection(disableCachingNamespaces);
disableNamespaceCachingCheckbox.setEnabled(useClasspath);
GridData data = new GridData(SWT.FILL, SWT.FILL, true, false);
data.horizontalIndent = 15;
disableNamespaceCachingCheckbox.setLayoutData(data);
disableNamespaceCachingCheckbox.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (isProjectPreferencePage()) {
SpringCorePreferences.getProjectPreferences(getProject(), BeansCorePlugin.PLUGIN_ID).putBoolean(
BeansCorePlugin.DISABLE_CACHING_FOR_NAMESPACE_LOADING_ID, disableNamespaceCachingCheckbox.getSelection());
}
else {
BeansCorePlugin.getDefault().getPluginPreferences().setValue(
BeansCorePlugin.DISABLE_CACHING_FOR_NAMESPACE_LOADING_ID, disableNamespaceCachingCheckbox.getSelection());
BeansCorePlugin.getDefault().savePluginPreferences();
}
}
});
Label namespaceLabel = new Label(composite, SWT.NONE);
namespaceLabel.setText("Select XSD namespace to configure prefix and default version:");
GridData gd = new GridData(GridData.FILL_BOTH);
gd.widthHint = LIST_VIEWER_WIDTH;
gd.heightHint = XSD_LIST_VIEWER_HEIGHT;
// config set list viewer
xsdViewer = new TableViewer(composite, SWT.BORDER);
xsdViewer.getTable().setLayoutData(gd);
xsdViewer.setContentProvider(new XsdConfigContentProvider());
xsdViewer.setLabelProvider(new XsdLabelProvider());
xsdViewer.setInput(this); // activate content provider
xsdViewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
if (event.getSelection() instanceof IStructuredSelection) {
Object obj = ((IStructuredSelection) event.getSelection()).getFirstElement();
if (obj != null) {
selectedNamespaceDefinition = (INamespaceDefinition) obj;
versionViewer.setInput(obj);
prefixText.setText(prefixes.get(selectedNamespaceDefinition));
if (versions.get(selectedNamespaceDefinition) != null) {
versionViewer.setCheckedElements(new Object[] { versions.get(selectedNamespaceDefinition) });
}
if (selectedNamespaceDefinition.getSchemaLocations().size() > 0) {
versionViewer.getControl().setEnabled(true);
}
else {
versionViewer.getControl().setEnabled(false);
}
}
}
}
});
new Label(composite, SWT.DELIMITER_SELECTION);
Composite prefixComposite = new Composite(composite, SWT.NONE);
GridLayout prefixLayout = new GridLayout();
prefixLayout.numColumns = 2;
prefixLayout.marginWidth = 0;
prefixLayout.marginHeight = 0;
prefixComposite.setLayout(prefixLayout);
prefixComposite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL));
prefixComposite.setFont(parent.getFont());
Label prefixLabel = new Label(prefixComposite, SWT.NONE);
prefixLabel.setText("Namespace prefix:");
prefixText = new Text(prefixComposite, SWT.BORDER);
prefixText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
prefixText.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
boolean valid = true;
for (Map.Entry<INamespaceDefinition, String> entry : prefixes.entrySet()) {
if (!entry.getKey().equals(selectedNamespaceDefinition)
&& entry.getValue().equals(prefixText.getText())) {
setErrorMessage(String.format("Prefix '%s' not unique", entry.getValue()));
valid = false;
}
}
setValid(valid);
if (valid) {
setErrorMessage(null);
}
if (StringUtils.hasLength(prefixText.getText())) {
prefixes.put(selectedNamespaceDefinition, prefixText.getText());
}
else {
prefixes.put(selectedNamespaceDefinition, selectedNamespaceDefinition.getDefaultNamespacePrefix());
}
xsdViewer.setInput(this);
}
});
Label versionLabel = new Label(composite, SWT.NONE);
versionLabel
.setText("Select default schema version (if none is selected the versionless schema will be used):");
versionViewer = CheckboxTableViewer.newCheckList(composite, SWT.BORDER);
versionViewer.getTable().setLayoutData(gd);
versionViewer.setContentProvider(new VersionContentProvider());
versionViewer.setLabelProvider(new VersionLabelProvider());
versionViewer.setSorter(new ViewerSorter());
versionViewer.addCheckStateListener(new ICheckStateListener() {
public void checkStateChanged(final CheckStateChangedEvent event) {
if (event.getChecked()) {
versionViewer.setCheckedElements(new Object[] { event.getElement() });
if (selectedNamespaceDefinition != null) {
versions.put(selectedNamespaceDefinition, (String) event.getElement());
}
}
else {
versionViewer.setCheckedElements(new Object[0]);
versions.put(selectedNamespaceDefinition, "");
}
}
});
return composite;
}
@Override
protected String getPreferencePageID() {
return PREF_ID;
}
@Override
protected String getPropertyPageID() {
return PROP_ID;
}
@Override
protected boolean hasProjectSpecificOptions(IProject project) {
return SpringCorePreferences.getProjectPreferences(project, BeansCorePlugin.PLUGIN_ID).getBoolean(
BeansCorePlugin.PROJECT_PROPERTY_ID, false);
}
public boolean performOk() {
if (isProjectPreferencePage()) {
if (useProjectSettings()) {
SpringCorePreferences.getProjectPreferences(getProject(), BeansCorePlugin.PLUGIN_ID).putBoolean(
BeansCorePlugin.PROJECT_PROPERTY_ID, true);
}
else {
SpringCorePreferences.getProjectPreferences(getProject(), BeansCorePlugin.PLUGIN_ID).putBoolean(
BeansCorePlugin.PROJECT_PROPERTY_ID, false);
}
for (Map.Entry<INamespaceDefinition, String> entry : versions.entrySet()) {
SpringCorePreferences.getProjectPreferences(getProject(), BeansCorePlugin.PLUGIN_ID).putString(
BeansCorePlugin.NAMESPACE_DEFAULT_VERSION_PREFERENCE_ID + entry.getKey().getNamespaceURI(),
entry.getValue());
}
for (Map.Entry<INamespaceDefinition, String> entry : prefixes.entrySet()) {
SpringCorePreferences.getProjectPreferences(getProject(), BeansCorePlugin.PLUGIN_ID).putString(
BeansCorePlugin.NAMESPACE_PREFIX_PREFERENCE_ID + entry.getKey().getNamespaceURI(),
entry.getValue());
}
SpringCorePreferences.getProjectPreferences(getProject(), BeansCorePlugin.PLUGIN_ID).putBoolean(
BeansCorePlugin.NAMESPACE_DEFAULT_FROM_CLASSPATH_ID, versionCheckbox.getSelection());
SpringCorePreferences.getProjectPreferences(getProject(), BeansCorePlugin.PLUGIN_ID).putBoolean(
BeansCorePlugin.LOAD_NAMESPACEHANDLER_FROM_CLASSPATH_ID, classpathCheckbox.getSelection());
}
else {
for (Map.Entry<INamespaceDefinition, String> entry : versions.entrySet()) {
BeansCorePlugin.getDefault().getPluginPreferences().setValue(
BeansCorePlugin.NAMESPACE_DEFAULT_VERSION_PREFERENCE_ID + entry.getKey().getNamespaceURI(),
entry.getValue());
}
for (Map.Entry<INamespaceDefinition, String> entry : prefixes.entrySet()) {
BeansCorePlugin.getDefault().getPluginPreferences().setValue(
BeansCorePlugin.NAMESPACE_PREFIX_PREFERENCE_ID + entry.getKey().getNamespaceURI(),
entry.getValue());
}
BeansCorePlugin.getDefault().getPluginPreferences().setValue(
BeansCorePlugin.NAMESPACE_DEFAULT_FROM_CLASSPATH_ID, versionCheckbox.getSelection());
BeansCorePlugin.getDefault().getPluginPreferences().setValue(
BeansCorePlugin.LOAD_NAMESPACEHANDLER_FROM_CLASSPATH_ID, classpathCheckbox.getSelection());
BeansCorePlugin.getDefault().savePluginPreferences();
}
// Set notifications to update UI
BeansCorePlugin.notifyNamespaceDefinitionListeners(null);
return true;
};
@Override
protected void performDefaults() {
super.performDefaults();
for (Map.Entry<INamespaceDefinition, String> entry : versions.entrySet()) {
entry.setValue("");
}
for (Map.Entry<INamespaceDefinition, String> entry : prefixes.entrySet()) {
prefixes.put(entry.getKey(), entry.getKey().getDefaultNamespacePrefix());
}
xsdViewer.setInput(this);
}
private void refresh() {
if (xsdViewer != null && xsdViewer.getControl() != null && !xsdViewer.getControl().isDisposed()) {
xsdViewer.setInput(this);
}
}
}