Package org.springframework.ide.eclipse.config.ui.editors.namespaces

Source Code of org.springframework.ide.eclipse.config.ui.editors.namespaces.NamespacesMasterPart$CheckStateListener

/*******************************************************************************
*  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.namespaces;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;

import org.eclipse.core.resources.IProject;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.dialogs.MessageDialogWithToggle;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.wst.sse.ui.internal.StructuredTextViewer;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
import org.springframework.ide.eclipse.beans.core.BeansCorePlugin;
import org.springframework.ide.eclipse.beans.core.model.INamespaceDefinitionListener;
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.springframework.ide.eclipse.config.core.ConfigCoreUtils;
import org.springframework.ide.eclipse.config.core.formatting.ShallowFormatProcessorXML;
import org.springframework.ide.eclipse.config.core.preferences.SpringConfigPreferenceConstants;
import org.springframework.ide.eclipse.config.core.schemas.BeansSchemaConstants;
import org.springframework.ide.eclipse.config.ui.ConfigUiPlugin;
import org.springframework.ide.eclipse.config.ui.editors.AbstractConfigFormPage;
import org.springframework.ide.eclipse.config.ui.editors.AbstractConfigLabelProvider;
import org.springframework.ide.eclipse.config.ui.editors.AbstractConfigMasterPart;
import org.springframework.ide.eclipse.config.ui.editors.SpringConfigContentProvider;
import org.springsource.ide.eclipse.commons.ui.StsUiImages;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

/**
* @author Leo Dos Santos
* @author Christian Dupuis
*/
@SuppressWarnings("restriction")
public class NamespacesMasterPart extends AbstractConfigMasterPart implements INamespaceDefinitionListener {

  private class CheckStateListener implements ICheckStateListener {

    public void checkStateChanged(CheckStateChangedEvent event) {
      if (event.getElement() != null && event.getElement() instanceof INamespaceDefinition) {
        INamespaceDefinition definition = (INamespaceDefinition) event.getElement();
        updateDefinitionFromCheckState(definition, event.getChecked());
      }
    }

  }

  private class XsdConfigContentProvider extends SpringConfigContentProvider {

    public XsdConfigContentProvider(AbstractConfigFormPage page) {
      super(page);
    }

    @Override
    protected List<String> getChildNames(IDOMElement element) {
      return new ArrayList<String>();
    }

    @Override
    public Object[] getElements(Object inputElement) {
      List<INamespaceDefinition> result = new ArrayList<INamespaceDefinition>();
      if (inputElement instanceof Document) {
        Document document = (Document) inputElement;
        rootElement = document.getDocumentElement();
        result = namespaceDefinitionList;
      }
      return result.toArray();
    }

  }

  private Element rootElement;

  private volatile List<INamespaceDefinition> namespaceDefinitionList = new CopyOnWriteArrayList<INamespaceDefinition>();

  private volatile boolean loading = false;

  private final Set<INamespaceDefinition> selectedNamespaces;

  private final Map<INamespaceDefinition, String> selectedVersions;

  private CheckboxTableViewer xsdViewer;

  private CheckStateListener checkListener;

  private final ShallowFormatProcessorXML formatProcessor;

  private final CountDownLatch lazyInitializationLatch;

  public NamespacesMasterPart(AbstractConfigFormPage page, Composite parent) {
    super(page, parent);
    selectedNamespaces = new HashSet<INamespaceDefinition>();
    selectedVersions = new HashMap<INamespaceDefinition, String>();
    formatProcessor = new ShallowFormatProcessorXML();
    lazyInitializationLatch = new CountDownLatch(1);
    BeansCorePlugin.registerNamespaceDefinitionListener(this);
    getNamespaceDefinitionList();
  }

  protected void addXsdDefinition(INamespaceDefinition definition) {
    if (!existsInConfiguration(definition)) {
      StructuredTextViewer textView = getConfigEditor().getTextViewer();
      IDOMDocument doc = getConfigEditor().getDomDocument();
      doc.getModel().beginRecording(textView);

      if (rootElement == null) {
        // Create a beans element and add the default namespace
        rootElement = doc.createElement(BeansSchemaConstants.ELEM_BEANS);
        doc.appendChild(rootElement);

        INamespaceDefinition defNamespace = NamespaceUtils.getDefaultNamespaceDefinition();
        if (defNamespace != null) {
          if (!xsdViewer.getChecked(defNamespace)) {
            xsdViewer.setChecked(defNamespace, true);
          }
          rootElement.setAttribute(ConfigCoreUtils.ATTR_DEFAULT_NAMESPACE, defNamespace.getNamespaceURI());
        }
        rootElement.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); //$NON-NLS-1$ //$NON-NLS-2$
      }

      // Check again so we don't add the default namespace twice
      if (!existsInConfiguration(definition)) {
        rootElement.setAttribute(
            ConfigCoreUtils.ATTR_NAMESPACE_PREFIX
                + definition.getNamespacePrefix(getConfigEditor().getResourceFile()),
            definition.getNamespaceURI());
      }

      selectedNamespaces.add(definition);
      updateXsdVersion();
      doc.getModel().endRecording(textView);
    }
  }

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

  @Override
  protected void createButtons(Composite client) {
    // Ignore
  }

  @Override
  protected ColumnViewer createViewer(Composite client) {
    return CheckboxTableViewer.newCheckList(client, SWT.BORDER);
  }

  @Override
  protected SpringConfigContentProvider createViewerContentProvider() {
    return new XsdConfigContentProvider(getFormPage());
  }

  @Override
  protected AbstractConfigLabelProvider createViewerLabelProvider() {
    return new NamespacesLabelProvider(getConfigEditor().getResourceFile());
  }

  @Override
  public void dispose() {
    if (xsdViewer != null && checkListener != null) {
      xsdViewer.removeCheckStateListener(checkListener);
    }
    BeansCorePlugin.unregisterNamespaceDefinitionListener(this);
  }

  /**
   * Returns true if the given namespaceDefinition exists as an attribute in
   * the XML configuration file.
   */
  private boolean existsInConfiguration(INamespaceDefinition namespaceDefinition) {
    if (rootElement != null) {
      NamedNodeMap attributeMap = rootElement.getAttributes();
      for (int i = 0; i < attributeMap.getLength(); i++) {
        Node currItem = attributeMap.item(i);
        // Regular namespace case
        if (currItem.getNodeName().equals(
            ConfigCoreUtils.ATTR_NAMESPACE_PREFIX
                + namespaceDefinition.getNamespacePrefix(getConfigEditor().getResourceFile()))) {
          return true;
        }
        // Default namespace case
        else if (currItem.getNodeName().equals(ConfigCoreUtils.ATTR_DEFAULT_NAMESPACE)
            && currItem.getNodeValue().equals(namespaceDefinition.getNamespaceURI())) {
          return true;
        }
      }
      // Special case
      List<String> schemaLocationAttrs = ConfigCoreUtils.parseSchemaLocationAttr(getConfigEditor()
          .getDomDocument());
      if (schemaLocationAttrs != null && schemaLocationAttrs.contains(namespaceDefinition.getNamespaceURI())) {
        return true;
      }
    }
    return false;
  }

  @Override
  protected void fillContextMenu(IMenuManager manager) {
    // TODO Auto-generated method stub

  }

  public CountDownLatch getLazyInitializationLatch() {
    return lazyInitializationLatch;
  }

  private synchronized List<INamespaceDefinition> getNamespaceDefinitionList() {
    if ((namespaceDefinitionList == null || namespaceDefinitionList.size() == 0) && !loading) {
      loading = true;
      if (getConfigEditor().getResourceFile() != null) {
        NamespaceUtils.getNamespaceDefinitions(getConfigEditor().getResourceFile().getProject(),
            new NamespaceUtils.INamespaceDefinitionTemplate() {
              public void doWithNamespaceDefinitions(INamespaceDefinition[] namespaceDefinitions,
                  IProject project) {
                List<INamespaceDefinition> newNamespaceDefinitions = new ArrayList<INamespaceDefinition>(
                    Arrays.asList(namespaceDefinitions));
                NamespacesMasterPart.this.namespaceDefinitionList = triggerLoadNamespaceDefinitionList(newNamespaceDefinitions);
                Display.getDefault().asyncExec(new Runnable() {
                  public void run() {
                    if (getViewer().getControl() != null && !getViewer().getControl().isDisposed()) {
                      getViewer().setInput(getConfigEditor().getDomDocument());
                      refresh();
                    }
                  }
                });
                loading = false;
                lazyInitializationLatch.countDown();
              }
            });
      }
    }
    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) getViewer().getContentProvider())
        .getElements(getConfigEditor().getDomDocument());

    for (Object currAvailableNamespace : availableNamespaces) {
      INamespaceDefinition currNamespaceDefinition = (INamespaceDefinition) currAvailableNamespace;
      if (existsInConfiguration(currNamespaceDefinition)) {
        checkedElements.add(currNamespaceDefinition);
        selectedNamespaces.add(currNamespaceDefinition);
        String existingVersion = ConfigCoreUtils.getSelectedSchemaLocation(getConfigEditor().getDomDocument(),
            currNamespaceDefinition.getNamespaceURI());
        if (!"".equals(existingVersion)) { //$NON-NLS-1$
          selectedVersions.put(currNamespaceDefinition, existingVersion);
        }
      }
    }
    return checkedElements.toArray();
  }

  private String getSchemaLocationValue(INamespaceDefinition namespaceDefinition,
      Map<INamespaceDefinition, String> schemaVersions) {
    String schemaVersion = schemaVersions.get(namespaceDefinition);
    if (schemaVersion == null) {
      schemaVersion = namespaceDefinition.getDefaultSchemaLocation(getConfigEditor().getResourceFile());
    }
    return namespaceDefinition.getNamespaceURI() + " " + schemaVersion; //$NON-NLS-1$
  }

  protected Map<INamespaceDefinition, String> getSchemaVersions() {
    return selectedVersions;
  }

  @Override
  protected String getSectionDescription() {
    return Messages.getString("NamespacesMasterPart.MASTER_SECTION_DESCRIPTION"); //$NON-NLS-1$
  }

  @Override
  protected String getSectionTitle() {
    return Messages.getString("NamespacesMasterPart.MASTER_SECTION_TITLE"); //$NON-NLS-1$
  }

  private boolean isUnknownNamespace(String attributeName, String namespaceUri,
      List<INamespaceDefinition> namespaceDefinitionList) {
    // Ignore xsi
    if (attributeName.toLowerCase().startsWith("xmlns:xsi")) { //$NON-NLS-1$
      return false;
    }

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

    // Check default namespace case
    if (attributeName.equalsIgnoreCase(ConfigCoreUtils.ATTR_DEFAULT_NAMESPACE)
        && !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 ((namespacePrefix != null && namespacePrefix.equals(currNamespaceDefinition
          .getNamespacePrefix(getConfigEditor().getResourceFile())))
          || namespaceUri.equalsIgnoreCase(currNamespaceDefinition.getNamespaceURI())) {
        return true;
      }
    }
    return false;
  }

  public void onNamespaceDefinitionRegistered(INamespaceDefinitionListener.NamespaceDefinitionChangeEvent event) {
    if (shouldRefresh(event)) {
      namespaceDefinitionList.clear();
      getNamespaceDefinitionList();
    }
  }

  public void onNamespaceDefinitionUnregistered(INamespaceDefinitionListener.NamespaceDefinitionChangeEvent event) {
    onNamespaceDefinitionRegistered(event);
  }

  private void openPontDialog() {
    IPreferenceStore prefStore = ConfigUiPlugin.getDefault().getPreferenceStore();
    if (prefStore.getString(SpringConfigPreferenceConstants.PREF_DISPLAY_TABS_DIALOG).equals(
        MessageDialogWithToggle.PROMPT)) {
      MessageDialogWithToggle
          .openInformation(
              getFormPage().getSite().getShell(),
              Messages.getString("NamespacesMasterPart.PONT_DIALOG_TITLE"), //$NON-NLS-1$
              Messages.getString("NamespacesMasterPart.PONT_DIALOG_MESSAGE"), //$NON-NLS-1$
              Messages.getString("NamespacesMasterPart.PONT_DIALOG_CHECKBOX"), false, prefStore, SpringConfigPreferenceConstants.PREF_DISPLAY_TABS_DIALOG); //$NON-NLS-1$
    }
  }

  @Override
  protected void postCreateContents() {
    ColumnViewer viewer = getViewer();
    if (viewer != null && viewer instanceof CheckboxTableViewer) {
      checkListener = new CheckStateListener();
      xsdViewer = (CheckboxTableViewer) viewer;
      xsdViewer.setCheckedElements(getPreselectedElements());
      xsdViewer.addCheckStateListener(checkListener);
    }
  }

  @Override
  public void refresh() {
    xsdViewer.setCheckedElements(getPreselectedElements());
    super.refresh();
  }

  protected void removeXsdDefinition(INamespaceDefinition definition) {
    if (existsInConfiguration(definition)) {
      StructuredTextViewer textView = getConfigEditor().getTextViewer();
      IDOMDocument doc = getConfigEditor().getDomDocument();
      doc.getModel().beginRecording(textView);

      rootElement.removeAttribute(ConfigCoreUtils.ATTR_NAMESPACE_PREFIX
          + definition.getNamespacePrefix(getConfigEditor().getResourceFile()));
      Attr attr = rootElement.getAttributeNode(ConfigCoreUtils.ATTR_DEFAULT_NAMESPACE);
      if (attr != null && attr.getNodeValue().equals(definition.getNamespaceURI())) {
        rootElement.removeAttributeNode(attr);
      }
      selectedNamespaces.remove(definition);
      updateXsdVersion();
      doc.getModel().endRecording(textView);
    }
  }

  private boolean shouldRefresh(INamespaceDefinitionListener.NamespaceDefinitionChangeEvent event) {
    return event.getProject() == null
        || event.getProject().equals(getConfigEditor().getResourceFile().getProject());
  }

  private List<INamespaceDefinition> triggerLoadNamespaceDefinitionList(
      List<INamespaceDefinition> namespaceDefinitionList) {
    // Add any namespaces that exist in the XML document but aren't
    // already known to the tooling via the extension point
    if (rootElement == null) {
      rootElement = getConfigEditor().getDomDocument().getDocumentElement();
    }
    if (rootElement != null) {
      NamedNodeMap beanAttributes = rootElement.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 = ConfigCoreUtils.getSelectedSchemaLocation(
              getConfigEditor().getDomDocument(), uri);
          INamespaceDefinition namespaceDefinition = new DefaultNamespaceDefinition(attributeNameToPrefix(
              currAttributeName, uri), uri, schemaVersion, StsUiImages.XML_FILE.createImage());
          if (!"".equals(schemaVersion)) { //$NON-NLS-1$
            this.selectedVersions.put(namespaceDefinition, schemaVersion);
          }
          namespaceDefinitionList.add(namespaceDefinition);
        }
      }
    }
    // Special case
    List<String> schemaInfo = ConfigCoreUtils.parseSchemaLocationAttr(getConfigEditor().getDomDocument());
    if (schemaInfo != null) {
      Iterator<String> iter = schemaInfo.iterator();
      while (iter.hasNext()) {
        String uri = iter.next();
        if (iter.hasNext()) {
          String schemaVersion = iter.next();
          if (!namespaceAttributeExistsInList(ConfigCoreUtils.ATTR_SCHEMA_LOCATION, uri,
              namespaceDefinitionList)) {
            INamespaceDefinition namespaceDefinition = new DefaultNamespaceDefinition(
                attributeNameToPrefix(ConfigCoreUtils.ATTR_SCHEMA_LOCATION, uri), uri, schemaVersion,
                StsUiImages.XML_FILE.createImage());
            if (!"".equals(schemaVersion)) { //$NON-NLS-1$
              this.selectedVersions.put(namespaceDefinition, schemaVersion);
            }
            namespaceDefinitionList.add(namespaceDefinition);
          }
        }
      }
    }
    return namespaceDefinitionList;
  }

  public void updateDefinitionFromCheckState(INamespaceDefinition definition, boolean checked) {
    if (checked) {
      addXsdDefinition(definition);
    }
    else {
      removeXsdDefinition(definition);
    }
    openPontDialog();
  }

  protected void updateXsdVersion() {
    rootElement.removeAttribute(ConfigCoreUtils.ATTR_SCHEMA_LOCATION);
    Set<INamespaceDefinition> namespaces = selectedNamespaces;
    Map<INamespaceDefinition, String> schemaVersions = getSchemaVersions();
    String schemaLocationAttrVal = null;
    for (INamespaceDefinition currNamespaceDefinition : namespaces) {
      if (currNamespaceDefinition.getDefaultSchemaLocation(getConfigEditor().getResourceFile()) != null) {
        String currNamespaceDefSchemaLocationVal = getSchemaLocationValue(currNamespaceDefinition,
            schemaVersions);
        // Append the new schema location
        if (schemaLocationAttrVal == null) {
          schemaLocationAttrVal = currNamespaceDefSchemaLocationVal;
        }
        else {
          schemaLocationAttrVal += "\n" + "\t\t" + currNamespaceDefSchemaLocationVal; //$NON-NLS-1$ //$NON-NLS-2$
        }
      }
    }

    if (schemaLocationAttrVal != null) {
      rootElement.setAttribute(ConfigCoreUtils.ATTR_SCHEMA_LOCATION, schemaLocationAttrVal.trim());
    }
    formatProcessor.formatNode(rootElement);
  }

}
TOP

Related Classes of org.springframework.ide.eclipse.config.ui.editors.namespaces.NamespacesMasterPart$CheckStateListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.