org.opentravel.schemas.wizards.NewPropertiesWizardPage.java Source code

Java tutorial

Introduction

Here is the source code for org.opentravel.schemas.wizards.NewPropertiesWizardPage.java

Source

/**
 * Copyright (C) 2014 OpenTravel Alliance (info@opentravel.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.opentravel.schemas.wizards;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.opentravel.schemas.modelObject.ModelObject;
import org.opentravel.schemas.node.ComponentNode;
import org.opentravel.schemas.node.FacetNode;
import org.opentravel.schemas.node.INode;
import org.opentravel.schemas.node.LibraryNode;
import org.opentravel.schemas.node.ModelNode;
import org.opentravel.schemas.node.Node;
import org.opentravel.schemas.node.NodeFactory;
import org.opentravel.schemas.node.NodeNameUtils;
import org.opentravel.schemas.node.PropertyNodeType;
import org.opentravel.schemas.node.properties.AttributeNode;
import org.opentravel.schemas.node.properties.ElementNode;
import org.opentravel.schemas.node.properties.PropertyNode;
import org.opentravel.schemas.trees.library.LibrarySorter;
import org.opentravel.schemas.trees.library.LibraryTreeLabelProvider;
import org.opentravel.schemas.trees.library.LibraryTreeWithPropertiesContentProvider;
import org.opentravel.schemas.widgets.ButtonBarManager;
import org.opentravel.schemas.widgets.WidgetFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author Agnieszka Janowska
 * 
 */
public class NewPropertiesWizardPage extends WizardPage {
    private static final Logger LOGGER = LoggerFactory.getLogger(NewPropertiesWizardPage.class);

    private class TextModifyListener implements ModifyListener {
        @Override
        public void modifyText(final ModifyEvent e) {
            setNodeName(nameText.getText());
            validate();
        }
    }

    private List<PropertyNode> newProperties;
    private final List<PropertyNodeType> propertyTypesOrder;

    private PropertyNode selectedNode;

    private final AtomicInteger counter = new AtomicInteger(1);

    // private ListViewer propertyTree;
    private TreeViewer libraryTree;
    private TreeViewer propertyTree;
    private Text nameText;
    private Text typeText;
    private Text descriptionText;
    private Combo propertyCombo;
    private Action copyAction;
    private Action newAction;
    private Action upAction;
    private Action downAction;
    private Action deleteAction;
    private Button typeButton;
    private final Node scopeNode;
    private final ComponentNode editedFacet;
    private final FormValidator validator;
    private ViewerFilter propertyFilter;
    private final LibraryNode library;
    private final TextModifyListener textModifyListener = new TextModifyListener();

    /**
     * @param pageName
     * @param title
     * @param titleImage
     * @param scope
     *            is a node that is the root of the tree of choices presented in the wizard
     */
    protected NewPropertiesWizardPage(final String pageName, final String title, final FormValidator validator,
            final List<PropertyNodeType> enabledTypes, final LibraryNode library, final Node scope) {
        super(pageName, title, null);
        this.validator = validator;
        propertyTypesOrder = new ArrayList<PropertyNodeType>(enabledTypes);
        this.scopeNode = scope;
        editedFacet = new FacetNode();
        this.library = library;
        this.setNewProperties(new LinkedList<PropertyNode>());
    }

    @Override
    public void createControl(final Composite parent) {
        final Composite container = new Composite(parent, SWT.BORDER);// parent;
        final GridLayout layout = new GridLayout();
        layout.numColumns = 5;
        container.setLayout(layout);

        final GridData listGD = new GridData();
        listGD.verticalAlignment = SWT.FILL;
        listGD.horizontalAlignment = SWT.FILL;
        listGD.grabExcessVerticalSpace = true;
        listGD.grabExcessHorizontalSpace = true;
        listGD.widthHint = 220;
        listGD.verticalSpan = 6;

        final GridData buttonGD = new GridData();
        buttonGD.horizontalAlignment = SWT.FILL;
        buttonGD.grabExcessVerticalSpace = true;
        buttonGD.verticalSpan = 6;

        final GridData rightPanelGD = new GridData();
        rightPanelGD.verticalAlignment = SWT.FILL;
        rightPanelGD.horizontalAlignment = SWT.FILL;
        rightPanelGD.grabExcessVerticalSpace = true;
        rightPanelGD.grabExcessHorizontalSpace = true;

        libraryTree = new TreeViewer(container);
        libraryTree.setContentProvider(new LibraryTreeWithPropertiesContentProvider(false));
        libraryTree.setLabelProvider(new LibraryTreeLabelProvider());
        libraryTree.setSorter(new LibrarySorter());
        libraryTree.setInput(scopeNode);
        libraryTree.getControl().setLayoutData(listGD);
        libraryTree.addSelectionChangedListener(new ISelectionChangedListener() {

            @Override
            public void selectionChanged(final SelectionChangedEvent event) {
                updateCopyState();
            }
        });
        libraryTree.addDoubleClickListener(new IDoubleClickListener() {

            @Override
            public void doubleClick(final DoubleClickEvent event) {
                final ISelection selection = event.getSelection();
                if (selection instanceof StructuredSelection) {
                    final StructuredSelection s = (StructuredSelection) selection;
                    final Object o = s.getFirstElement();
                    if (o instanceof PropertyNode) {
                        displayNewProperty(newProperty((PropertyNode) o));
                    } else if (o instanceof Node) {
                        final Node node = (Node) o;
                        newPropertyFromType(node);
                    }
                }

            }
        });
        if (propertyFilter != null) {
            libraryTree.addFilter(propertyFilter);
        }

        propertyTree = new TreeViewer(container);
        propertyTree.setContentProvider(new LibraryTreeWithPropertiesContentProvider(false));
        propertyTree.setLabelProvider(new LibraryTreeLabelProvider());
        propertyTree.setSorter(new LibrarySorter());
        propertyTree.setInput(editedFacet);
        propertyTree.getControl().setLayoutData(listGD);
        propertyTree.addSelectionChangedListener(new ISelectionChangedListener() {

            @Override
            public void selectionChanged(final SelectionChangedEvent event) {
                final Object selection = propertyTree.getSelection();
                if (selection instanceof IStructuredSelection) {
                    final Object first = ((IStructuredSelection) selection).getFirstElement();
                    if (first instanceof PropertyNode) {
                        final PropertyNode node = (PropertyNode) first;
                        setSelectedNode(node);
                        updateView();
                    }
                }
            }
        });

        final GridData generalGD = new GridData();
        generalGD.horizontalSpan = 2;
        generalGD.horizontalAlignment = SWT.FILL;
        generalGD.grabExcessHorizontalSpace = true;

        final GridData typeTextGD = new GridData();
        typeTextGD.horizontalSpan = 1;
        typeTextGD.horizontalAlignment = SWT.FILL;
        typeTextGD.grabExcessHorizontalSpace = true;

        final GridData multiTextGD = new GridData();
        multiTextGD.horizontalSpan = 3;
        multiTextGD.horizontalAlignment = SWT.FILL;
        multiTextGD.verticalAlignment = SWT.FILL;
        multiTextGD.grabExcessHorizontalSpace = true;
        multiTextGD.grabExcessVerticalSpace = true;

        final Composite rightPanel = container;

        final ButtonBarManager bbManager = new ButtonBarManager(SWT.FLAT);

        copyAction = new Action("Copy") {
            @Override
            public void run() {
                for (final PropertyNode o : getSelectedValidPropertiesFromLibraryTree()) {
                    displayNewProperty(newProperty(o));
                }
            }
        };
        copyAction.setToolTipText("Copy selected properties from left tree to the list of new properties");

        newAction = new Action("New") {
            @Override
            public void run() {
                displayNewProperty(newProperty());
            }

        };
        newAction.setToolTipText("Create new property");

        deleteAction = new Action("Delete") {
            @Override
            public void run() {
                final PropertyNode selected = getSelectedNode();
                deleteProperty(selected);
            }

        };
        upAction = new Action("Up") {
            @Override
            public void run() {
                final PropertyNode selected = getSelectedNode();
                int index = getNewProperties().indexOf(selected);
                if (index > 0) {
                    getNewProperties().remove(index--);
                    getNewProperties().add(index, selected);
                    selected.moveProperty(PropertyNode.UP);
                    propertyTree.refresh();
                    selectInList(selected);
                }
            }
        };
        downAction = new Action("Down") {
            @Override
            public void run() {
                final PropertyNode selected = getSelectedNode();
                int index = getNewProperties().indexOf(selected);
                if (index < getNewProperties().size() - 1) {
                    getNewProperties().remove(index++);
                    getNewProperties().add(index, selected);
                    selected.moveProperty(PropertyNode.DOWN);
                    propertyTree.refresh();
                    selectInList(selected);
                }
            }
        };

        bbManager.add(copyAction);
        bbManager.add(newAction);
        // bbManager.add(upAction);
        // bbManager.add(downAction);
        bbManager.add(deleteAction);

        final Composite bb = bbManager.createControl(rightPanel);
        final GridData bbgd = new GridData();
        bbgd.horizontalSpan = 3;
        bbgd.widthHint = 220;
        bb.setLayoutData(bbgd);

        final Label propertyLabel = new Label(rightPanel, SWT.NONE);
        propertyLabel.setText("Property:");
        propertyCombo = WidgetFactory.createCombo(rightPanel, SWT.DROP_DOWN | SWT.V_SCROLL | SWT.READ_ONLY);
        for (final PropertyNodeType propertyType : propertyTypesOrder) {
            propertyCombo.add(propertyType.getName());
        }
        propertyCombo.addModifyListener(new ModifyListener() {

            @Override
            public void modifyText(final ModifyEvent e) {
                final String selected = propertyCombo.getText();
                if (selected != null && !selected.isEmpty()) {
                    final PropertyNodeType type = PropertyNodeType.fromString(selected);
                    setPropertyType(type);
                    updateView();
                }
            }
        });
        propertyCombo.setLayoutData(generalGD);

        final Label nameLabel = new Label(rightPanel, SWT.NONE);
        nameLabel.setText("Name:");
        nameText = WidgetFactory.createText(rightPanel, SWT.SINGLE | SWT.BORDER);
        nameText.setLayoutData(generalGD);
        nameText.addModifyListener(textModifyListener);

        final Label typeLabel = new Label(rightPanel, SWT.NONE);
        typeLabel.setText("Type:");
        typeText = WidgetFactory.createText(rightPanel, SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY);
        typeText.setLayoutData(typeTextGD);
        typeButton = new Button(rightPanel, SWT.PUSH);
        typeButton.setText("...");
        typeButton.setToolTipText("Select a type for the new property.");
        typeButton.addSelectionListener(new SelectionListener() {

            @Override
            public void widgetSelected(final SelectionEvent e) {
                chooseTLType();
            }

            @Override
            public void widgetDefaultSelected(final SelectionEvent e) {
            }

        });

        final Label descriptionLabel = new Label(rightPanel, SWT.NONE);
        descriptionLabel.setText("Description:");
        final GridData gd = new GridData();
        gd.horizontalSpan = 2;
        descriptionLabel.setLayoutData(gd);
        descriptionText = WidgetFactory.createText(rightPanel, SWT.MULTI | SWT.BORDER);
        descriptionText.setLayoutData(multiTextGD);
        descriptionText.addModifyListener(new ModifyListener() {

            @Override
            public void modifyText(final ModifyEvent e) {
                setNodeDescription(descriptionText.getText());
            }

        });

        updateWidgetsState();
        setControl(container);
        setPageComplete(false);
    }

    private void displayNewProperty(final PropertyNode newNode) {
        if (newNode != null) {
            propertyTree.refresh();
            selectInList(newNode);
            updateView();
            chooseType();
            setFocusOnNameText();
        }
    }

    private PropertyNode newProperty(final PropertyNode o) {
        if (!propertyTypesOrder.contains(o.getPropertyType())) {
            setMessage(o.getPropertyType().getName() + "s are not allowed for this object", WARNING);
            return null;
        }
        final PropertyNode copy = (PropertyNode) NodeFactory.newComponentMember(editedFacet, o.cloneTLObj());
        copy.setAssignedType(o.getType());
        getNewProperties().add(copy);
        return copy;
    }

    private PropertyNode newProperty() {
        // parent is required by PropertyNode.changePropertyTo()
        final PropertyNode newNode = createPropertyNode(editedFacet);
        editedFacet.addProperty(newNode);
        getNewProperties().add(newNode);
        return newNode;
    }

    private PropertyNode createPropertyNode(ComponentNode parent) {
        final String name = "property" + counter.getAndIncrement();
        // TODO - if element is not enabled, use AttributeNode
        PropertyNode n = null;
        if (propertyTypesOrder.contains(PropertyNodeType.ELEMENT))
            n = new ElementNode(parent, name);
        else
            n = new AttributeNode(parent, name);
        n.setName(name);
        n.setLibrary(library);
        n.setDescription("");
        n.setAssignedType(ModelNode.getUnassignedNode(), false);
        return n;
    }

    // @SuppressWarnings("unused")
    // private PropertyNode createPropertyNode() {
    // final String name = "property" + counter.getAndIncrement();
    // final PropertyNode n = new PropertyNode(propertyTypesOrder.get(0));
    // n.setName(name);
    // n.setLibrary(library);
    // n.setDescription("");
    // n.setAssignedType(ModelNode.getUnassignedNode());
    // return n;
    // }

    private void newPropertyFromType(final Node node) {
        if (node.isAssignable()) {
            final PropertyNode newProperty = newProperty();
            newProperty.setAssignedType(node);
            String adjusted = NodeNameUtils.adjustCaseOfName(newProperty.getPropertyType(), node.getName());
            newProperty.setName(adjusted);
            displayNewProperty(newProperty);
        }
    }

    private void deleteProperty(final PropertyNode selected) {
        final int index = getNewProperties().indexOf(selected);
        getNewProperties().remove(selected);
        editedFacet.removeProperty(selected);
        propertyTree.refresh();
        if (getNewProperties().size() > 0) {
            selectInList(getNewProperties().get(index > 0 ? index - 1 : 0));
        }
    }

    private void chooseTLType() {
        final PropertyNode node = getSelectedNode();
        final TypeSelectionWizard wizard = new TypeSelectionWizard(node);

        wizard.run(getShell(), true); // let the user select type then assign it
        // Use the type name as the property name if the user has not already set one.
        if (wizard.getSelection() != null && (getSelectedNode().getName().startsWith("Property")
                || getSelectedNode().getName().startsWith("property")))
            getSelectedNode().setName(wizard.getSelection().getName());
        updateView();
        propertyTree.update(node, null);
    }

    private void chooseType() {
        if (propertyTypesOrder.size() == 1) {
            propertyCombo.select(0);
        }
    }

    private void setPropertyType(final PropertyNodeType type) {
        final PropertyNode node = getSelectedNode();
        if (node != null) {
            newProperties.remove(node);
            setSelectedNode(node.changePropertyRole(type));
            newProperties.add(getSelectedNode());
            nameText.removeModifyListener(textModifyListener);
            nameText.setText(getSelectedNode().getName());
            nameText.addModifyListener(textModifyListener);
        }
        propertyTree.refresh();
    }

    private void setNodeName(final String text) {
        final Node node = getSelectedNode();
        if (node != null) {
            node.setName(text);
            // LOGGER.debug("Set name on: " + node.getName());
            NodeNameUtils.fixName(node);
            LOGGER.debug("Set name on: " + node.getName());
            // TODO - figure out how to show the user the changed name
            propertyTree.update(node, null);
        }
    }

    private void setNodeDescription(final String text) {
        final Node node = getSelectedNode();
        if (node != null) {
            node.setDescription(text);
        }
    }

    private void setFocusOnNameText() {
        nameText.setFocus();
        final int wordLength = nameText.getText() == null ? 0 : nameText.getText().length();
        nameText.setSelection(0, wordLength);
    }

    public void updateView() {
        updateWidgetsState();
        final PropertyNode selectedNode = getSelectedNode();
        if (selectedNode != null) {
            nameText.setText(selectedNode.getName());
            final ModelObject<?> modelObject = selectedNode.getModelObject();
            typeText.setText(modelObject == null || modelObject.getTLType() == null ? ""
                    : modelObject.getTLType().getLocalName());
            descriptionText.setText(selectedNode.getDescription());
            final int index = propertyTypesOrder.indexOf(selectedNode.getPropertyType());
            if (index >= 0) {
                if (index != propertyCombo.getSelectionIndex()) {
                    propertyCombo.select(index);
                }
                if (selectedNode.getPropertyType() != PropertyNodeType.ATTRIBUTE
                        && selectedNode.getPropertyType() != PropertyNodeType.ELEMENT) {
                    typeText.setText("");
                }
            } else {
                propertyCombo.deselectAll();
            }
        } else {
            nameText.setText("");
            typeText.setText("");
            descriptionText.setText("");
            propertyCombo.deselectAll();
        }
        validate();
    }

    private void updateWidgetsState() {
        final INode selected = getSelectedNode();
        boolean enabled = false;
        if (selected != null) {
            enabled = true;
        }
        newAction.setEnabled(true);
        deleteAction.setEnabled(enabled);
        upAction.setEnabled(enabled);
        downAction.setEnabled(enabled);
        nameText.setEnabled(enabled);
        typeText.setEnabled(enabled);
        propertyCombo.setEnabled(enabled);
        descriptionText.setEnabled(enabled);
        updateCopyState();
        updateTypeButtonState();
    }

    private void updateCopyState() {
        final List<PropertyNode> selectedProps = getSelectedValidPropertiesFromLibraryTree();
        if (selectedProps.size() > 0) {
            copyAction.setEnabled(true);
        } else {
            copyAction.setEnabled(false);
        }
    }

    private void updateTypeButtonState() {
        final PropertyNode node = getSelectedNode();
        boolean enabled = false;
        if (node != null) {
            final PropertyNodeType propertyType = node.getPropertyType();
            if (propertyType == PropertyNodeType.ELEMENT || propertyType == PropertyNodeType.ATTRIBUTE) {
                enabled = true;
            }
        }
        typeButton.setEnabled(enabled);
    }

    private void validate() {
        boolean complete = true;
        String message = null;
        try {
            validator.validate();
        } catch (final ValidationException e) {
            message = e.getMessage();
            complete = false;
            LOGGER.debug("Validation output " + e.getMessage());
        }
        setPageComplete(complete);
        setMessage(message, ERROR);
        getWizard().getContainer().updateButtons();
    }

    /**
     * @return the last node selected from the property tree.
     */
    public PropertyNode getSelectedNode() {
        return selectedNode;
    }

    public void setSelectedNode(final PropertyNode selectedNode) {
        this.selectedNode = selectedNode;
    }

    private void selectInList(final PropertyNode newNode) {
        propertyTree.setSelection(null);
        propertyTree.setSelection(new StructuredSelection(newNode));
    }

    private List<PropertyNode> getSelectedValidPropertiesFromLibraryTree() {
        final List<PropertyNode> ret = new ArrayList<PropertyNode>();
        final ISelection selection = libraryTree.getSelection();
        if (selection instanceof StructuredSelection) {
            final StructuredSelection strSel = (StructuredSelection) selection;
            for (final Object o : strSel.toList()) {
                if (o instanceof PropertyNode) {
                    final PropertyNode p = (PropertyNode) o;
                    if (propertyTypesOrder.contains(p.getPropertyType())) {
                        ret.add(p);
                    }
                }
            }
        }
        return ret;
    }

    /**
     * @return the newProperties
     */
    public List<PropertyNode> getNewProperties() {
        return newProperties;
    }

    /**
     * @param newProperties
     *            the newProperties to set
     */
    public void setNewProperties(final List<PropertyNode> newProperties) {
        this.newProperties = newProperties;
    }

    public void setPropertyFilter(final ViewerFilter filter) {
        propertyFilter = filter;
    }

}