Package org.locationtech.udig.style.sld.editor

Source Code of org.locationtech.udig.style.sld.editor.EditorPageManager

/* uDig - User Friendly Desktop Internet GIS client
* http://udig.refractions.net
* (C) 2012, Refractions Research Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* (http://www.eclipse.org/legal/epl-v10.html), and the Refractions BSD
* License v1.0 (http://udig.refractions.net/files/bsd3-v10.html).
*/
package org.locationtech.udig.style.sld.editor;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

import org.locationtech.udig.core.AdapterUtil;
import org.locationtech.udig.core.internal.ExtensionPointProcessor;
import org.locationtech.udig.core.internal.ExtensionPointUtil;
import org.locationtech.udig.project.ILayer;
import org.locationtech.udig.style.IStyleConfigurator;
import org.locationtech.udig.style.sld.SLDPlugin;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IRegistryChangeEvent;
import org.eclipse.core.runtime.IRegistryChangeListener;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.core.runtime.dynamichelpers.ExtensionTracker;
import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler;
import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
import org.eclipse.jface.preference.PreferenceManager;
import org.eclipse.ui.PlatformUI;

public class EditorPageManager implements IExtensionChangeHandler {

    public static final String ATT_ID = "id"; //$NON-NLS-1$
    public static final String ATT_CLASS = "class"; //$NON-NLS-1$
    public static final String ATT_NAME = "name"; //$NON-NLS-1$
    public static final String ATT_LABEL = "label"; //$NON-NLS-1$
    public static final String PL_KEYWORDS = "keywords"; //$NON-NLS-1$
   
    /**
     * Pre-order traversal means visit the root first,
     * then the children.
     */
    public static final int PRE_ORDER = 0;

    /**
     * Post-order means visit the children, and then the root.
     */
    public static final int POST_ORDER = 1;

    /**
     * The root node.
     * Note that the root node is a special internal node
     * that is used to collect together all the nodes that
     * have no parent; it is not given out to clients.
     */
    EditorNode root = new EditorNode("");//$NON-NLS-1$

    /**
     * The path separator character.
     */
    String separator;

    /**
     * Creates a new preference manager.
     */
    public EditorPageManager() {
        this('.');
    }
   
    /**
     * Create a new instance of the receiver with the specified seperatorChar
     *
     * @param separatorChar
     */
    public EditorPageManager(char separatorChar) {
        separator = new String(new char[] { separatorChar });
       
        IExtensionTracker tracker = PlatformUI.getWorkbench().getExtensionTracker();
        tracker.registerHandler(this, ExtensionTracker.createExtensionPointFilter(getExtensionPointFilter()));

        // add a listener for keyword deltas. If any occur clear all page caches
        Platform.getExtensionRegistry().addRegistryChangeListener(
                new IRegistryChangeListener() {

                    public void registryChanged(IRegistryChangeEvent event) {
                        if (event.getExtensionDeltas(StyleEditorPage.XPID, PL_KEYWORDS).length > 0) {
                            for (Iterator<?> j = getElements(
                                    PreferenceManager.POST_ORDER).iterator(); j
                                    .hasNext();) {
                                ((EditorNode) j.next())
                                        .clearKeywords();
                            }
                        }
                    }
                });
    }

    /**
     * Add the pages and the groups to the receiver.
     *
     * @param pageContributions
     */
    public void addPages(Collection<?> pageContributions) {

        // Add the contributions to the manager
        Iterator<?> iterator = pageContributions.iterator();
        while (iterator.hasNext()) {
            Object next = iterator.next();
            if (next instanceof EditorNode) {
                EditorNode node = (EditorNode) next;
                addToRoot(node);
                registerNode(node);
            }
        }

    }

    /**
     * Register a node with the extension tracker.
     *
     * @param node
     *            register the given node and its subnodes with the extension
     *            tracker
     */
    public void registerNode(EditorNode node) {
        PlatformUI.getWorkbench().getExtensionTracker().registerObject(
                node.getConfigurationElement().getDeclaringExtension(), node,
                IExtensionTracker.REF_WEAK);
        EditorNode[] subNodes = node.getSubNodes();
        for (int i = 0; i < subNodes.length; i++) {
            registerNode((EditorNode) subNodes[i]);
        }

    }

    /* (non-Javadoc)
     * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#addExtension(org.eclipse.core.runtime.dynamicHelpers.IExtensionTracker, org.eclipse.core.runtime.IExtension)
     */
    public void addExtension(IExtensionTracker tracker, IExtension extension) {
       
        IConfigurationElement[] elements = extension.getConfigurationElements();
        for (int i = 0; i < elements.length; i++) {
            EditorNode node = null;
           
            boolean nameMissing = elements[i].getAttribute(ATT_NAME) == null;
            String id = elements[i].getAttribute(ATT_ID);      
            boolean classMissing = getClassValue(elements[i], ATT_CLASS) == null;

            //System.out.println(elements[i].id+","+nameMissing+","+classMissing);
            if (!(nameMissing || id == null || classMissing)) {
                node = new EditorNode(id, elements[i]);
            }
           
            if (node == null)
                continue;
            registerNode(node);
            String category = node.getCategory();
            if (category == null) {
                addToRoot(node);
            } else {
                EditorNode parent = null;
                for (Iterator<?> j = getElements(PreferenceManager.POST_ORDER)
                        .iterator(); j.hasNext();) {
                    EditorNode element = (EditorNode) j.next();
                    if (category.equals(element.getId())) {
                        parent = element;
                        break;
                    }
                }
                if (parent == null) {
                    //TODO: log error
                    // Could not find the parent - log
//                    WorkbenchPlugin
//                            .log("Invalid preference page path: " + category); //$NON-NLS-1$
                    addToRoot(node);
                } else {
                    parent.add(node);
                }
            }
        }
    }
   
    public String getClassValue(IConfigurationElement configElement, String classAttributeName) {
        String className = configElement.getAttribute(classAttributeName);
        if (className != null)
            return className;
        IConfigurationElement [] candidateChildren = configElement.getChildren(classAttributeName);
        if (candidateChildren.length == 0)
            return null;
   
        return candidateChildren[0].getAttribute(ATT_CLASS);
    }


    /*
     * (non-Javadoc)
     *
     * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionAdditionHandler#getExtensionPointFilter()
     */
    private IExtensionPoint getExtensionPointFilter() {
        return Platform.getExtensionRegistry().getExtensionPoint(StyleEditorPage.XPID);
    }

    /* (non-Javadoc)
     * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#removeExtension(org.eclipse.core.runtime.IExtension, java.lang.Object[])
     */
    public void removeExtension(IExtension extension, Object[] objects) {
        for (int i = 0; i < objects.length; i++) {
            if (objects[i] instanceof EditorNode) {
                EditorNode node = (EditorNode) objects[i];
                node.disposeResources();
                deepRemove(getRoot(), node);
            }
        }
    }

    /**
     * Removes the node from the manager, searching through all subnodes.
     *
     * @param parent
     *            the node to search
     * @param nodeToRemove
     *            the node to remove
     * @return whether the node was removed
     */
    private boolean deepRemove(EditorNode parent,
            EditorNode nodeToRemove) {
        if (parent == nodeToRemove)
            if (parent == getRoot()) {
                removeAll(); // we're removing the root
                return true;
            }

        if (parent.remove(nodeToRemove))
            return true;

        EditorNode[] subNodes = parent.getSubNodes();
        for (int i = 0; i < subNodes.length; i++) {
            if (deepRemove(subNodes[i], nodeToRemove))
                return true;
        }
        return false;
    }
   

    /**
     * Adds the given preference node as a subnode of the
     * node at the given path.
     *
     * @param path the path
     * @param node the node to add
     * @return <code>true</code> if the add was successful,
     *  and <code>false</code> if there is no contribution at
     *  the given path
     */
    public boolean addTo(String path, EditorNode node) {
        EditorNode target = find(path);
        if (target == null)
            return false;
        target.add(node);
        return true;
    }

    /**
     * Adds the given preference node as a subnode of the
     * root.
     *
     * @param node the node to add, which must implement
     *   <code>SLDEditorPageNode</code>
     */
    public void addToRoot(EditorNode node) {
        Assert.isNotNull(node);
        root.add(node);
    }

    /**
     * Recursively enumerates all nodes at or below the given node
     * and adds them to the given list in the given order.
     *
     * @param node the starting node
     * @param sequence a read-write list of preference nodes
     *  (element type: <code>SLDEditorPageNode</code>)
     *  in the given order
     * @param order the traversal order, one of
     *  <code>PRE_ORDER</code> and <code>POST_ORDER</code>
     */
    protected void buildSequence(EditorNode node, List<EditorNode> sequence, int order) {
        if (order == PRE_ORDER)
            sequence.add(node);
        EditorNode[] subnodes = node.getSubNodes();
        for (int i = 0; i < subnodes.length; i++) {
            buildSequence(subnodes[i], sequence, order);
        }
        if (order == POST_ORDER)
            sequence.add(node);
    }

    /**
     * Finds and returns the contribution node at the given path.
     *
     * @param path the path
     * @return the node, or <code>null</code> if none
     */
    public EditorNode find(String path) {
       return find(path,root);
    }
   
    /**
     * Finds and returns the preference node directly
     * below the top at the given path.
     *
     * @param path the path
     * @return the node, or <code>null</code> if none
     *
     * @since 3.1
     */
    protected EditorNode find(String path, EditorNode top){
       Assert.isNotNull(path);
         StringTokenizer stok = new StringTokenizer(path, separator);
         EditorNode node = top;
         while (stok.hasMoreTokens()) {
             String id = stok.nextToken();
             node = node.findSubNode(id);
             if (node == null)
                 return null;
         }
         if (node == top)
             return null;
         return node;
    }

    /**
     * Returns all preference nodes managed by this
     * manager.
     *
     * @param order the traversal order, one of
     *  <code>PRE_ORDER</code> and <code>POST_ORDER</code>
     * @return a list of preference nodes
     *  (element type: <code>SLDEditorPageNode</code>)
     *  in the given order
     */
    public List<?> getElements(int order) {
        Assert.isTrue(order == PRE_ORDER || order == POST_ORDER,
                "invalid traversal order");//$NON-NLS-1$
        ArrayList<EditorNode> sequence = new ArrayList<EditorNode>();
        EditorNode[] subnodes = getRoot().getSubNodes();
        for (int i = 0; i < subnodes.length; i++)
            buildSequence(subnodes[i], sequence, order);
        return sequence;
    }

    /**
     * Returns the root node.
     * Note that the root node is a special internal node
     * that is used to collect together all the nodes that
     * have no parent; it is not given out to clients.
     *
     * @return the root node
     */
    public EditorNode getRoot() {
        return root;
    }

    /**
     * Removes the prefernece node at the given path.
     *
     * @param path the path
     * @return the node that was removed, or <code>null</code>
     *  if there was no node at the given path
     */
    public EditorNode remove(String path) {
        Assert.isNotNull(path);
        int index = path.lastIndexOf(separator);
        if (index == -1)
            return root.remove(path);
        // Make sure that the last character in the string isn't the "."
        Assert.isTrue(index < path.length() - 1, "Path can not end with a dot");//$NON-NLS-1$
        String parentPath = path.substring(0, index);
        String id = path.substring(index + 1);
        EditorNode parentNode = find(parentPath);
        if (parentNode == null)
            return null;
        return parentNode.remove(id);
    }

    /**
     * Removes the given prefreence node if it is managed by
     * this contribution manager.
     *
     * @param node the node to remove
     * @return <code>true</code> if the node was removed,
     *  and <code>false</code> otherwise
     */
    public boolean remove(EditorNode node) {
        Assert.isNotNull(node);

        return root.remove(node);
    }

    /**
     * Removes all contribution nodes known to this manager.
     */
    public void removeAll() {
        root = new EditorNode("");//$NON-NLS-1$
    }
   
    public EditorNode[] getRootSubNodes() {
      return getRoot().getSubNodes();
    }
   
    /**
     * Returns true if the specified node exists in the manager.
     *
     * @param nodeId Unique identified for a node
     * @return boolean
     */
    public boolean hasNode(String nodeId) {
        EditorNode[] nodes = getRoot().getSubNodes();
        for (int i = 0; i < nodes.length; i++) {
            if (nodes[i].getId().equalsIgnoreCase(nodeId))
                return true;
        }
        return false;
    }

    static boolean meetsRequirement(ILayer selectedLayer, String id, IConfigurationElement element, EditorNode node ) {
        String requires = element.getAttribute(OpenStyleEditorAction.ATT_REQUIRES);
        try {
            Object classInstance = EditorNode.createExtension(element, EditorNode.ATT_CLASS);
            // first try creating required class using extension classloading
            // if this fails use the same classloader as the configurator
        
            // Failed trying to recover by using the configurators class's class loader
            if (AdapterUtil.instance.canAdaptTo(requires, selectedLayer, classInstance.getClass().getClassLoader())) {
                SLDPlugin.trace("skipped "+id, null); //$NON-NLS-1$
                return true;
            }
            try{
                Object requiredClass = element.createExecutableExtension(OpenStyleEditorAction.ATT_REQUIRES);
                if ( AdapterUtil.instance.canAdaptTo(requires, selectedLayer, requiredClass.getClass().getClassLoader())) {
                    return true;
                }
               
            }catch( Exception ce ){
                SLDPlugin.trace("skipped "+id, null); //$NON-NLS-1$
               
            }
        } catch (Exception e) {
            SLDPlugin.log("extProcConfigurator skipped " //$NON-NLS-1$
                          + id + " (couldn't find " //$NON-NLS-1$
                          + requires + ")", null); //$NON-NLS-1$
        }
        return false;
    }

    /**
     * Creates the default {@link EditorPageManager} implementation and loads the style pages for the layer into
     * the manager.
     *
     * @param plugin the plug-in to send error messages to.
     * @param selectedLayer the layer to use to filter the style pages
     * @return the default {@link EditorPageManager} implementation and loads the style pages for the layer into
     * the manager.
     */
    public static EditorPageManager loadManager(Plugin plugin, ILayer selectedLayer) {
        final EditorPageManager[] manager = new EditorPageManager[] {new EditorPageManager('.')};
       
        ExtensionPointProcessor extProcPage = new StyleEditorPageExtensionProcessor(manager, selectedLayer);
        ExtensionPointUtil.process(plugin, StyleEditorPage.XPID, extProcPage);
   
        ExtensionPointProcessor extProcConfigurator = new StyleConfiguratorExtensionProcessor(manager, selectedLayer);
        ExtensionPointUtil.process(plugin, IStyleConfigurator.XPID, extProcConfigurator);
        return manager[0];
    }

}
TOP

Related Classes of org.locationtech.udig.style.sld.editor.EditorPageManager

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.