org.jboss.tools.vpe.editor.template.VpeEditAnyDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.tools.vpe.editor.template.VpeEditAnyDialog.java

Source

/*******************************************************************************
 * Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc.
 * Distributed under license by Red Hat, Inc. All rights reserved.
 * This program is 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:
 *     Exadel, Inc. and Red Hat, Inc. - initial API and implementation
 ******************************************************************************/
package org.jboss.tools.vpe.editor.template;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
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.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.jboss.tools.common.model.ui.ModelUIImages;
import org.jboss.tools.jst.css.CSSPlugin;
import org.jboss.tools.jst.css.dialog.CSSStyleDialog;
import org.jboss.tools.jst.css.dialog.common.Util;
import org.jboss.tools.jst.jsp.util.Constants;
import org.jboss.tools.vpe.VpePlugin;
import org.jboss.tools.vpe.editor.Message;
import org.jboss.tools.vpe.editor.template.expression.VpeExpressionBuilder;
import org.jboss.tools.vpe.editor.template.expression.VpeExpressionBuilderException;
import org.jboss.tools.vpe.messages.VpeUIMessages;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;

/**
 * Class which presents dialog for any template
 * @author mareshkau
 *
 */
public class VpeEditAnyDialog extends TitleAreaDialog {

    /*
     * Current template
     */
    private VpeAnyData data;
    /*
     * List of already created templates
     */
    List<VpeAnyData> tagsList;
    Map<String, VpeAnyData> tagsNamesSet = new HashMap<String, VpeAnyData>();
    Text tagName;
    Text tagUri;
    private String previousUri = Constants.EMPTY;
    private Button childrenCheckbox;
    private Text txtTagForDisplay;
    private Text txtValue;
    private Text txtStyle;
    private VpeEditAnyDialogValidator templateVerifier;

    public VpeEditAnyDialog(Shell shell, VpeAnyData data, List<VpeAnyData> tagsList) {
        super(shell);
        this.data = data;
        this.tagsList = tagsList;
        if (null != tagsList) {
            for (VpeAnyData tag : tagsList) {
                tagsNamesSet.put(tag.getName(), tag);
            }
        }
        setHelpAvailable(false);
    }

    @Override
    protected Control createDialogArea(Composite parent) {
        /*
         * Setting dialog Title, Message, Image.
         */
        getShell().setText(VpeUIMessages.TEMPLATE);
        setTitle(VpeUIMessages.TAG_ATTRIBUTES);
        setTitleImage(ModelUIImages.getImage(ModelUIImages.WIZARD_DEFAULT)); //image is managed by registry
        setMessage(VpeUIMessages.USER_SPECIFIED_TAG_DIALOG_DESCRIPTION);

        /*
         * Create validator
         */
        templateVerifier = new VpeEditAnyDialogValidator();

        /*
         * Create composites.
         */
        Composite topComposite = (Composite) super.createDialogArea(parent);
        ((GridData) topComposite.getLayoutData()).widthHint = 300;

        final Composite composite = new Composite(topComposite, SWT.NONE);
        GridLayout gridLayout = new GridLayout(3, false);
        gridLayout.marginWidth = 50;
        gridLayout.marginHeight = 20;
        gridLayout.horizontalSpacing = 5;
        composite.setLayout(gridLayout);
        composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

        composite.setBackground(parent.getBackground());
        composite.setForeground(parent.getForeground());
        composite.setFont(parent.getFont());

        /*
         * Create Tag Name label
         */
        Label tagNameLabel = new Label(composite, SWT.NONE);
        tagNameLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.NONE, false, false, 1, 1));
        tagNameLabel.setText(VpeUIMessages.TAG_NAME);

        /*
         * Create Tag Name value
         */
        tagName = new Text(composite, SWT.BORDER);
        tagName.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false, 2, 1));
        String text = Constants.EMPTY;
        if ((data != null) && (data.getName() != null)) {
            text = data.getName();
        }
        tagName.setText(text);
        tagName.addModifyListener(templateVerifier);

        /*
         * Create Tag URI label
         */
        Label tagUriLabel = new Label(composite, SWT.NONE);
        tagUriLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.NONE, false, false, 1, 1));
        tagUriLabel.setText(VpeUIMessages.TAG_URI);

        /*
         * Create Tag URI value
         */
        tagUri = new Text(composite, SWT.BORDER);
        tagUri.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false, 2, 1));
        text = Constants.EMPTY;
        if ((data != null) && (data.getUri() != null)) {
            text = data.getUri();
        }
        tagUri.setText(text);
        tagUri.addModifyListener(templateVerifier);

        /*
         * Create Tag for display label
         */
        Label tagForDisplayLabel = new Label(composite, SWT.NONE);
        tagForDisplayLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.NONE, false, false, 1, 1));
        tagForDisplayLabel.setText(VpeUIMessages.TAG_FOR_DISPLAY);

        /*
        * Create Tag for display value
        */
        txtTagForDisplay = new Text(composite, SWT.BORDER);
        txtTagForDisplay.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false, 2, 1));
        text = Constants.EMPTY;
        if ((data != null) && (data.getTagForDisplay() != null)) {
            text = data.getTagForDisplay();
        }
        txtTagForDisplay.setText(text);
        txtTagForDisplay.addModifyListener(templateVerifier);

        /*
         * Create Children label
         */
        Label childrenCheckboxLabel = new Label(composite, SWT.NONE);
        childrenCheckboxLabel.setLayoutData(new GridData(SWT.LEFT, SWT.NONE, false, false, 1, 1));
        childrenCheckboxLabel.setText(VpeUIMessages.CHILDREN);

        /*
         * Create check box for Children
         */
        childrenCheckbox = new Button(composite, SWT.CHECK);
        childrenCheckbox.setLayoutData(new GridData(SWT.LEFT, SWT.NONE, true, false, 2, 1));
        childrenCheckbox.setSelection(data.isChildren());

        /*
         * Create value label
         */
        Label lblValue = new Label(composite, SWT.NONE);
        lblValue.setLayoutData(new GridData(SWT.RIGHT, SWT.NONE, false, false, 1, 1));
        lblValue.setText(VpeUIMessages.VALUE);

        /*
         * Create value
         */
        txtValue = new Text(composite, SWT.BORDER);
        txtValue.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false, 2, 1));
        text = Constants.EMPTY;
        if ((data != null) && (data.getValue() != null)) {
            text = data.getValue();
        }
        txtValue.setText(text);
        txtValue.addModifyListener(templateVerifier);

        /*
         * Create style label
         */
        Label lbStyle = new Label(composite, SWT.NONE);
        lbStyle.setLayoutData(new GridData(SWT.RIGHT, SWT.NONE, false, false, 1, 1));
        lbStyle.setText(VpeUIMessages.TAG_STYLE);

        /*
         * Create style value
         */
        txtStyle = new Text(composite, SWT.BORDER);
        txtStyle.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false, 1, 1));
        text = Constants.EMPTY;
        if ((data != null) && (data.getStyle() != null)) {
            text = data.getStyle();
        }
        txtStyle.setText(text);

        /*
         * Create style button
         */
        Button button = new Button(composite, SWT.PUSH);
        button.setLayoutData(new GridData(SWT.LEFT, SWT.NONE, false, false, 1, 1));
        button.setToolTipText(VpeUIMessages.EDIT_STYLE_TIP);
        ImageDescriptor colorDesc = CSSPlugin.getImageDescriptor(Util.IMAGE_COLORLARGE_FILE_LOCATION);
        Image im = colorDesc.createImage();
        button.setImage(im);

        button.addDisposeListener(new DisposeListener() {
            public void widgetDisposed(DisposeEvent e) {
                Button button = (Button) e.getSource();
                button.getImage().dispose();
            }
        });
        button.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent event) {
                CSSStyleDialog cssDialog = new CSSStyleDialog(composite.getShell(), txtStyle.getText());
                if (cssDialog.open() == Window.OK) {
                    txtStyle.setText(cssDialog.getStyle());
                }
            }
        });

        return composite;
    }

    @Override
    public void create() {
        super.create();
        templateVerifier.validateAll(false);
    }

    @Override
    protected void okPressed() {
        boolean isChanged = false;
        if ((data.isChildren() != childrenCheckbox.getSelection())
                || isChanged(data, data.getName(), tagName.getText())
                || isChanged(data, data.getUri(), tagUri.getText())
                || isChanged(data, data.getTagForDisplay(), txtTagForDisplay.getText())
                || isChanged(data, data.getValue(), txtValue.getText())
                || isChanged(data, data.getStyle(), txtStyle.getText())) {
            isChanged = true;
        }

        data.setChanged(isChanged);

        data.setChildren(childrenCheckbox.getSelection());
        data.setName(tagName.getText().trim());
        data.setUri(tagUri.getText().trim());
        data.setTagForDisplay(txtTagForDisplay.getText().trim());
        data.setValue(txtValue.getText().trim());
        data.setStyle(txtStyle.getText());

        super.okPressed();
    }

    private boolean isChanged(VpeAnyData data, String oldValue, String newValue) {
        boolean isChanged = false;
        if (oldValue == null) {
            oldValue = Constants.EMPTY;
        }
        if (newValue == null) {
            newValue = Constants.EMPTY;
        }
        if (data.isCaseSensitive()) {
            isChanged = !oldValue.trim().equals(newValue.trim());
        } else {
            isChanged = !oldValue.trim().equalsIgnoreCase(newValue.trim());
        }
        return isChanged;
    }

    /**
     * Sets the message for this dialog with an indication of what type of
     * message it is.
     * <p>
     * @param message the message, or <code>null</code> to clear the message
     */
    public void setMessage(IMessageProvider message) {
        if (message == null) {
            setMessage(null, IMessageProvider.NONE);
        } else {
            setMessage(message.getMessage(), message.getMessageType());
        }
    }

    /**
     * Validator of {@link VpeEditAnyDialog}.
     * 
     * @author yradtsevich
     */
    private class VpeEditAnyDialogValidator implements ModifyListener {
        /**
         * Used to validate tag-names.
         */
        private Document xmlDocument = null;

        public VpeEditAnyDialogValidator() {
            try {
                xmlDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
            } catch (ParserConfigurationException e) {
                VpePlugin.getPluginLog().logError(e);
            }
        }

        /**
         * Validates tag name.
         * <p>
         * Prefix should exist. 
         * <p>
         * Otherwise template won't be saved correctly to auto-templates.xml.
         * 
         * @return message is validation failed, null otherwise.
         */
        private IMessageProvider validateTagName() {
            Message message = null;
            String name = tagName.getText().trim();
            String[] parts = name.split(":"); //$NON-NLS-1$
            Pattern p = Pattern.compile("([a-zA-Z]+\\d*)+"); //$NON-NLS-1$
            /*
             * Reset editable property for template URI
             * after it has been disabled.
             */
            if (!tagUri.getEditable()) {
                tagUri.removeModifyListener(templateVerifier);
                if ((null != data) && (null != data.getName())
                        && data.getName().split(":")[0].equalsIgnoreCase(parts[0])) { //$NON-NLS-1$
                    /*
                     * Restore initial URI
                     */
                    previousUri = data.getUri();
                }
                tagUri.setText(previousUri);
                tagUri.setEditable(true);
                tagUri.addModifyListener(templateVerifier);
            }
            /*
             * Check if tag's name is correct
             */
            if (parts.length != 2 || name.startsWith(":") //$NON-NLS-1$
                    || name.endsWith(":")) { //$NON-NLS-1$
                message = new Message(MessageFormat.format(VpeUIMessages.TAG_NAME_IS_NOT_VALID, name),
                        IMessageProvider.ERROR);
            } else if ((parts[0].length() == 0) || (parts[1].length() == 0) || (!p.matcher(parts[0]).matches())
                    || (!p.matcher(parts[1]).matches())) {
                /*
                 * Matcher will accept only word characters with optional numbers.
                 */
                message = new Message(MessageFormat.format(VpeUIMessages.TAG_NAME_IS_NOT_VALID, name),
                        IMessageProvider.ERROR);
            } else if (tagsNamesSet.keySet().contains(name) && (!tagsList.contains(data)
                    || (tagsList.contains(data) && !data.getName().equalsIgnoreCase(name)))) {
                /*
                 * Find duplicate tag names.
                 */
                message = new Message(MessageFormat.format(VpeUIMessages.TAG_NAME_ALREADY_EXISTS, name),
                        IMessageProvider.ERROR);
            } else {
                /*
                 * Inform that URI for the specified taglib namespace
                 * is already defined in another templates.
                 */
                for (String templateName : tagsNamesSet.keySet()) {
                    if (parts[0].equalsIgnoreCase(templateName.split(":")[0]) //$NON-NLS-1$
                            && (!tagsList.contains(data) || (tagsList.contains(data)
                                    && !data.getName().split(":")[0].equalsIgnoreCase(parts[0])))) { //$NON-NLS-1$
                        message = new Message(
                                MessageFormat.format(VpeUIMessages.URI_TAGLIB_NAMESPACE_ALREADY_DEFINED, parts[0],
                                        tagsNamesSet.get(templateName).getUri()),
                                IMessageProvider.WARNING);
                        /*
                         * Set the URI and disable this field.
                         * Remove the listener to avoid dead lock
                         */
                        tagUri.removeModifyListener(templateVerifier);
                        previousUri = tagUri.getText();
                        tagUri.setText(tagsNamesSet.get(templateName).getUri());
                        tagUri.setEditable(false);
                        tagUri.addModifyListener(templateVerifier);
                        break;
                    }
                }
            }
            return message;
        }

        /**
         * Validates {@link VpeEditAnyDialog#txtTagForDisplay} field.
         *
         * @return {@code null} if it is valid or an instance of {@code IMessageProvider} if
         * it contains any error.
         */
        private IMessageProvider validateTagForDisplay() {
            if (xmlDocument != null) {
                try {
                    xmlDocument.createElement(txtTagForDisplay.getText());
                } catch (DOMException e) {
                    /*
                     * https://jira.jboss.org/browse/JBIDE-6599
                     * Changing warning message.
                     */
                    return new Message(MessageFormat.format(VpeUIMessages.TAG_FOR_DISPLAY_IS_NOT_VALID,
                            txtTagForDisplay.getText()), IMessageProvider.ERROR);
                }
            }

            return null;
        }

        /**
         * Validates {@link VpeEditAnyDialog#txtValue} field.
         *
         * @return {@code null} if it is valid or an instance of {@code IMessageProvider} if
         * it contains any error.
         */
        private IMessageProvider validateValue() {

            try {
                VpeExpressionBuilder.buildCompletedExpression(txtValue.getText(), true);
            } catch (VpeExpressionBuilderException e) {
                return new Message(MessageFormat.format(VpeUIMessages.VALUE_IS_NOT_VALID, e.getMessage()),
                        IMessageProvider.ERROR);
            }

            return null;
        }

        /**
         * Validates all fields of {@link VpeEditAnyDialog} and changes the view of
         * dialog according to validation results.
         * 
         * @param updateMessage if it is {@code true}, the dialog's message will be updated.
         */
        void validateAll(boolean updateMessage) {
            /*
             * Initialize the message with the description
             */
            IMessageProvider message = new Message(VpeUIMessages.USER_SPECIFIED_TAG_DIALOG_DESCRIPTION,
                    IMessageProvider.NONE);
            List<IMessageProvider> statuses = new ArrayList<IMessageProvider>();
            /*
             * Get messages from all validators
             */
            statuses.add(validateTagForDisplay());
            statuses.add(validateValue());
            statuses.add(validateTagName());
            /*
             * Find the message with the most severe status
             */
            for (IMessageProvider status : statuses) {
                if (null != status) {
                    message = message.getMessageType() >= status.getMessageType() ? message : status;
                }
            }
            String messageText = message.getMessage();
            switch (message.getMessageType()) {
            case IMessageProvider.NONE:
                setMessage(messageText, IMessageProvider.NONE);
                setErrorMessage(null);
                break;

            case IMessageProvider.WARNING:
                setMessage(messageText, IMessageProvider.WARNING);
                setErrorMessage(null);
                break;

            case IMessageProvider.INFORMATION:
                setMessage(messageText, IMessageProvider.INFORMATION);
                setErrorMessage(null);
                break;

            default:
                /*
                 * Set ERROR message
                 */
                if (messageText.length() == 0) {
                    messageText = null;
                }
                setMessage(null, IMessageProvider.NONE);
                setErrorMessage(messageText);
                break;
            } // end switch

            Button okButton = getButton(IDialogConstants.OK_ID);
            if ((message == null) || (message.getMessageType() <= IMessageProvider.WARNING)) {
                okButton.setEnabled(true);
            } else {
                okButton.setEnabled(false);
            }

            if (updateMessage) {
                VpeEditAnyDialog.this.setMessage(message);
            }
        }

        /**
         * Fired when a field is modified.
         */
        public void modifyText(ModifyEvent e) {
            validateAll(true);
        }
    }
}