org.springframework.ide.eclipse.config.ui.wizards.NamespaceSelectionWizardPage.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.ide.eclipse.config.ui.wizards.NamespaceSelectionWizardPage.java

Source

/*******************************************************************************
 *  Copyright (c) 2012 VMware, 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:
 *      VMware, Inc. - initial API and implementation
 *******************************************************************************/
package org.springframework.ide.eclipse.config.ui.wizards;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.resources.IFile;
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.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.springframework.ide.eclipse.beans.ui.BeansUIImages;
import org.springframework.ide.eclipse.beans.ui.namespaces.DefaultNamespaceDefinition;
import org.springframework.ide.eclipse.beans.ui.namespaces.INamespaceDefinition;
import org.springframework.ide.eclipse.beans.ui.namespaces.NamespaceUtils;
import org.springsource.ide.eclipse.commons.ui.StsUiImages;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

/**
 * {@link WizardPage} that displays a list of {@link INamespaceDefinition}s to
 * the user in order to allow for selecting the desired XSD namespace
 * declarations.
 * @author Wesley Coelho
 * @author Leo Dos Santos
 * @author Christian Dupuis
 */
public class NamespaceSelectionWizardPage extends WizardPage {

    private class VersionContentProvider implements IStructuredContentProvider {

        public void dispose() {
        }

        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 class VersionLabelProvider extends LabelProvider {

        @Override
        public Image getImage(Object element) {
            return BeansUIImages.getImage(BeansUIImages.IMG_OBJS_XSD);
        }

        @Override
        public String getText(Object element) {
            if (element instanceof String) {
                String label = (String) element;
                if (selectedNamespaceDefinition != null
                        && label.equals(selectedNamespaceDefinition.getDefaultSchemaLocation(file))) {
                    label += " " + ConfigWizardsMessages.NamespaceConfig_default;
                }
                return label;
            }
            return super.getText(element);
        }
    }

    /**
     * Content provider that supplies the list of available namespaces that are
     * declared to the tooling via an extension point or that already appear in
     * the XML configuration.
     */
    private class XsdConfigContentProvider implements IStructuredContentProvider {

        public void dispose() {
        }

        public Object[] getElements(Object obj) {
            return getNamespaceDefinitionList().toArray();
        }

        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
        }
    }

    public class XsdLabelProvider extends LabelProvider {

        @Override
        public Image getImage(Object element) {
            if (element instanceof INamespaceDefinition) {
                INamespaceDefinition xsdDef = (INamespaceDefinition) element;
                return xsdDef.getNamespaceImage();
            }
            return BeansUIImages.getImage(BeansUIImages.IMG_OBJS_XSD);
        }

        @Override
        public String getText(Object element) {
            if (element instanceof INamespaceDefinition) {
                INamespaceDefinition xsdDef = (INamespaceDefinition) element;
                return xsdDef.getNamespacePrefix(file) + " - " + xsdDef.getNamespaceURI();
            }
            return "";
        }
    }

    public static final String PAGE_NAME = "xsdPage";

    private static final int XSD_LIST_VIEWER_HEIGHT = 150;

    private static final int LIST_VIEWER_WIDTH = 340;

    private CheckboxTableViewer xsdViewer;

    private CheckboxTableViewer versionViewer;

    private final Map<INamespaceDefinition, String> selectedNamespaceVersionMap = new HashMap<INamespaceDefinition, String>();

    private INamespaceDefinition selectedNamespaceDefinition;

    private final Element beansElement;

    private List<INamespaceDefinition> namespaceDefinitionList = null;

    private INamespaceDefinition defaultNamespace = null;

    private final IFile file;

    protected NamespaceSelectionWizardPage(String pageName, Element beansElement, IFile file) {
        super(pageName);
        this.beansElement = beansElement;
        this.file = file;
        setTitle(ConfigWizardsMessages.NamespaceConfig_title);
        setDescription(ConfigWizardsMessages.NamespaceConfig_xsdDescription);
    }

    private String attributeNameToPrefix(String attributeName, String uri) {
        int colonIndex = attributeName.indexOf(":");
        if (attributeName.length() > 6 && attributeName.indexOf(":") > 0) {
            return attributeName.substring(colonIndex + 1, attributeName.length());
        } else if (attributeName.equals("xmlns")) {
            return uri.substring(uri.lastIndexOf("/") + 1);
        } else {
            return null;
        }
    }

    private void checkForDefaultNamespace() {

        if (defaultNamespace == null) {
            return;
        }

        Object[] checkedElements = xsdViewer.getCheckedElements();
        if (checkedElements != null) {

            for (Object currElement : checkedElements) {
                if (currElement.equals(defaultNamespace)) {
                    this.setErrorMessage(null);
                    setDescription(ConfigWizardsMessages.NamespaceConfig_xsdDescription);
                    this.setPageComplete(true);
                    return;
                }
            }
            this.setErrorMessage(ConfigWizardsMessages.NamespaceConfig_mustIncludeDefault);
            this.setPageComplete(false);
        }

    }

    public void createControl(Composite parent) {
        namespaceDefinitionList = getNamespaceDefinitionList();
        defaultNamespace = getDefaultNamespaceDefinition(namespaceDefinitionList);

        initializeDialogUnits(parent);
        // top level group
        Composite composite = new Composite(parent, SWT.NONE);
        GridLayout layout = new GridLayout();
        layout.marginTop = 5;
        composite.setLayout(layout);
        composite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL));
        composite.setFont(parent.getFont());
        setControl(composite);

        Label namespaceLabel = new Label(composite, SWT.NONE);
        namespaceLabel.setText(ConfigWizardsMessages.NamespaceConfig_selectNamespace);

        GridData gd = new GridData(GridData.FILL_BOTH);
        gd.widthHint = LIST_VIEWER_WIDTH;
        gd.heightHint = XSD_LIST_VIEWER_HEIGHT;

        // config set list viewer
        xsdViewer = CheckboxTableViewer.newCheckList(composite, SWT.BORDER);
        xsdViewer.getTable().setLayoutData(gd);
        xsdViewer.setContentProvider(new XsdConfigContentProvider());
        xsdViewer.setLabelProvider(new XsdLabelProvider());
        xsdViewer.setInput(this); // activate content provider
        xsdViewer.setCheckedElements(getPreselectedElements());

        xsdViewer.addSelectionChangedListener(new ISelectionChangedListener() {

            public void selectionChanged(SelectionChangedEvent event) {
                if (event.getSelection() instanceof IStructuredSelection) {
                    Object obj = ((IStructuredSelection) event.getSelection()).getFirstElement();
                    selectedNamespaceDefinition = (INamespaceDefinition) obj;
                    versionViewer.setInput(obj);
                    if (selectedNamespaceVersionMap.containsKey(selectedNamespaceDefinition)) {
                        versionViewer.setCheckedElements(new Object[] {
                                selectedNamespaceVersionMap.get(selectedNamespaceDefinition).trim() });
                    }
                    if (xsdViewer.getChecked(obj) && selectedNamespaceDefinition.getSchemaLocations().size() > 0) {
                        versionViewer.getControl().setEnabled(true);
                    } else {
                        versionViewer.getControl().setEnabled(false);
                    }

                    checkForDefaultNamespace();
                }
            }
        });

        xsdViewer.addCheckStateListener(new ICheckStateListener() {

            public void checkStateChanged(final CheckStateChangedEvent event) {
                Object obj = event.getElement();
                selectedNamespaceDefinition = (INamespaceDefinition) obj;
                versionViewer.setInput(obj);
                if (selectedNamespaceVersionMap.containsKey(selectedNamespaceDefinition)) {
                    versionViewer.setCheckedElements(
                            new Object[] { selectedNamespaceVersionMap.get(selectedNamespaceDefinition).trim() });
                }

                if (event.getChecked() && selectedNamespaceDefinition != null
                        && selectedNamespaceDefinition.getSchemaLocations().size() > 0) {
                    versionViewer.getControl().setEnabled(true);
                } else {
                    versionViewer.getControl().setEnabled(false);
                }

            }
        });

        Label versionLabel = new Label(composite, SWT.NONE);
        versionLabel.setText(ConfigWizardsMessages.NamespaceConfig_selectSpecificXsd);

        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) {
                        selectedNamespaceVersionMap.put(selectedNamespaceDefinition, (String) event.getElement());
                    }
                } else {
                    versionViewer.setCheckedElements(new Object[0]);
                    selectedNamespaceVersionMap.remove(selectedNamespaceDefinition);
                }
            }
        });
    }

    /**
     * Returns true if the given namespaceDefinition exists as an attribute in
     * the XML configuration file.
     */
    private boolean existsInConfiguration(INamespaceDefinition namespaceDefinition) {
        NamedNodeMap attributeMap = beansElement.getAttributes();
        for (int i = 0; i < attributeMap.getLength(); i++) {
            Node currItem = attributeMap.item(i);
            // Regular namespace case
            if (currItem.getNodeName().equals("xmlns:" + namespaceDefinition.getNamespacePrefix(file))) {
                return true;
            }
            // Default namespace case
            else if (currItem.getNodeName().equals("xmlns")
                    && currItem.getNodeValue().equals(namespaceDefinition.getNamespaceURI())) {
                return true;
            }
        }
        return false;
    }

    private INamespaceDefinition getDefaultNamespaceDefinition(List<INamespaceDefinition> namespaceDefinitions) {
        NamedNodeMap beanAttributes = beansElement.getAttributes();
        for (int i = 0; i < beanAttributes.getLength(); i++) {
            Node currAttributeNode = beanAttributes.item(i);
            String currAttributeName = currAttributeNode.getNodeName();
            String uri = currAttributeNode.getNodeValue();
            if (currAttributeName.equalsIgnoreCase("xmlns")) {
                for (INamespaceDefinition currNamespaceDefinition : namespaceDefinitions) {
                    if (currNamespaceDefinition.getNamespaceURI().equals(uri)) {
                        return currNamespaceDefinition;
                    }
                }
            }
        }
        return null;
    }

    private List<INamespaceDefinition> getNamespaceDefinitionList() {
        if (namespaceDefinitionList == null) {
            namespaceDefinitionList = new ArrayList<INamespaceDefinition>();

            // Add namespaces declared using the extension point
            namespaceDefinitionList.addAll(NamespaceUtils.getNamespaceDefinitions());

            // Add any namespaces that exist in the XML document but aren't
            // already known to the tooling via the extension point
            NamedNodeMap beanAttributes = beansElement.getAttributes();
            for (int i = 0; i < beanAttributes.getLength(); i++) {
                Node currAttributeNode = beanAttributes.item(i);
                String currAttributeName = currAttributeNode.getNodeName();
                String uri = currAttributeNode.getNodeValue();
                if (isUnknownNamespace(currAttributeName, uri, namespaceDefinitionList)) {
                    String schemaVersion = getSchemaVersionFromXml(uri);
                    INamespaceDefinition namespaceDefinition = new DefaultNamespaceDefinition(
                            attributeNameToPrefix(currAttributeName, uri), uri, schemaVersion,
                            StsUiImages.XML_FILE.createImage());
                    if (!"".equals(schemaVersion)) {
                        this.selectedNamespaceVersionMap.put(namespaceDefinition, schemaVersion);
                    }
                    namespaceDefinitionList.add(namespaceDefinition);
                }
            }
        }
        return namespaceDefinitionList;
    }

    /**
     * Return the namespace definitions that are already declared in the
     * configuration file.
     */
    private Object[] getPreselectedElements() {
        Set<INamespaceDefinition> checkedElements = new HashSet<INamespaceDefinition>();
        Object[] availableNamespaces = ((IStructuredContentProvider) xsdViewer.getContentProvider())
                .getElements(null);

        for (Object currAvailableNamespace : availableNamespaces) {
            INamespaceDefinition currNamespaceDefinition = (INamespaceDefinition) currAvailableNamespace;
            if (existsInConfiguration(currNamespaceDefinition)) {
                checkedElements.add(currNamespaceDefinition);
                String existingVersion = getSchemaVersionFromXml(currNamespaceDefinition.getNamespaceURI());
                if (!"".equals(existingVersion)) {
                    selectedNamespaceVersionMap.put(currNamespaceDefinition, existingVersion);
                }
            }
        }

        return checkedElements.toArray();
    }

    private String getSchemaVersionFromXml(String namespaceUri) {
        String schemaLocationValue = beansElement.getAttribute(NamespaceConfigWizard.ATTR_SCHEMA_LOCATION);

        // Remove all line breaks and tabs
        schemaLocationValue = schemaLocationValue.replaceAll("\\n|\\t", " ");
        // Remove any extra spaces
        schemaLocationValue = schemaLocationValue.replaceAll(" +", " ");
        // Split along spaces into just the schema content
        String[] schemaVersions = schemaLocationValue.split(" ");

        for (int i = 0; i < schemaVersions.length; i++) {
            String currSchema = schemaVersions[i];
            if (currSchema.equals(namespaceUri) && (i + 1) < schemaVersions.length) {
                // String after the schema is the version
                return schemaVersions[i + 1];
            }
        }

        return "";
    }

    public Map<INamespaceDefinition, String> getSchemaVersions() {
        return selectedNamespaceVersionMap;
    }

    public List<INamespaceDefinition> getXmlSchemaDefinitions() {
        List<INamespaceDefinition> defs = new ArrayList<INamespaceDefinition>();
        Object[] checkedElements = xsdViewer.getCheckedElements();
        if (checkedElements != null) {
            for (Object element : checkedElements) {
                defs.add((INamespaceDefinition) element);
            }
        }
        return defs;
    }

    private boolean isUnknownNamespace(String attributeName, String namespaceUri,
            List<INamespaceDefinition> namespaceDefinitionList) {

        // Ignore xsi
        if (attributeName.toLowerCase().startsWith("xmlns:xsi")) {
            return false;
        }

        // Check non-default namespace case
        if (attributeName.toLowerCase().startsWith("xmlns:")
                && !namespaceAttributeExistsInList(attributeName, namespaceUri, namespaceDefinitionList)
                && attributeNameToPrefix(attributeName, namespaceUri) != null) {
            return true;
        }

        // Check default namespace case
        if (attributeName.equalsIgnoreCase("xmlns")
                && !namespaceAttributeExistsInList(attributeName, namespaceUri, namespaceDefinitionList)) {
            return true;
        }

        return false;
    }

    private boolean namespaceAttributeExistsInList(String attributeName, String namespaceUri,
            List<INamespaceDefinition> namespaces) {
        String namespacePrefix = attributeNameToPrefix(attributeName, namespaceUri);
        for (INamespaceDefinition namespaceDefinition : namespaces) {
            INamespaceDefinition currNamespaceDefinition = namespaceDefinition;
            if (currNamespaceDefinition.getNamespacePrefix(file).equals(namespacePrefix)
                    || namespaceUri.equalsIgnoreCase(currNamespaceDefinition.getNamespaceURI())) {
                return true;
            }
        }
        return false;
    }
}