com.amazonaws.eclipse.explorer.dynamodb.AddLSIDialog.java Source code

Java tutorial

Introduction

Here is the source code for com.amazonaws.eclipse.explorer.dynamodb.AddLSIDialog.java

Source

/*
 * Copyright 2013 Amazon Technologies, Inc.
 *
 * 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://aws.amazon.com/apache2.0
 *
 * This file 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 com.amazonaws.eclipse.explorer.dynamodb;

import java.util.Arrays;
import java.util.LinkedList;

import org.eclipse.core.databinding.AggregateValidationStatus;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.beans.PojoObservables;
import org.eclipse.core.databinding.observable.ChangeEvent;
import org.eclipse.core.databinding.observable.IChangeListener;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.jface.viewers.Viewer;
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.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import com.amazonaws.eclipse.core.AwsToolkitCore;
import com.amazonaws.eclipse.databinding.ChainValidator;
import com.amazonaws.eclipse.databinding.NotEmptyValidator;
import com.amazonaws.eclipse.dynamodb.AbstractAddNewAttributeDialog;
import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.LocalSecondaryIndex;
import com.amazonaws.services.dynamodbv2.model.Projection;

public class AddLSIDialog extends TitleAreaDialog {

    /** Widget used as data-binding targets **/
    private Text attributeNameText;
    private Text indexNameText;
    private Combo attributeTypeCombo;
    private Combo projectionTypeCombo;
    private Button addAttributeButton;
    private Button okButton;

    /** The data objects that will be used to generate the service request **/
    private final LocalSecondaryIndex localSecondaryIndex;
    private final AttributeDefinition indexRangeKeyAttributeDefinition;

    private final DataBindingContext bindingContext = new DataBindingContext();

    /** The model value objects for data-binding **/
    private final IObservableValue indexNameModel;
    private final IObservableValue indexRangeKeyNameInKeySchemaDefinitionModel;
    private final IObservableValue indexRangeKeyNameInAttributeDefinitionsModel;
    private final IObservableValue indexRangeKeyAttributeTypeModel;
    private final IObservableValue projectionTypeModel;

    private final String primaryRangeKeyName;
    private final int primaryRangeKeyTypeComboIndex;

    private static final String[] DATA_TYPE_STRINGS = new String[] { "String", "Number", "Binary" };
    private static final String[] PROJECTED_ATTRIBUTES = new String[] { "All Attributes", "Table and Index Keys",
            "Specify Attributes" };

    public AddLSIDialog(Shell parentShell, CreateTableDataModel dataModel) {
        super(parentShell);
        // Initialize the variable necessary for data-binding
        localSecondaryIndex = new LocalSecondaryIndex();
        // The index range key to be defined by the user
        KeySchemaElement rangeKeySchemaDefinition = new KeySchemaElement().withAttributeName(null)
                .withKeyType(KeyType.RANGE);
        localSecondaryIndex.withKeySchema(
                new KeySchemaElement().withAttributeName(dataModel.getHashKeyName()).withKeyType(KeyType.HASH),
                rangeKeySchemaDefinition);
        localSecondaryIndex.setProjection(new Projection());
        // The attribute definition for the index range key
        indexRangeKeyAttributeDefinition = new AttributeDefinition();

        // Initialize IObservableValue objects that keep track of data variables
        indexNameModel = PojoObservables.observeValue(localSecondaryIndex, "indexName");
        indexRangeKeyNameInKeySchemaDefinitionModel = PojoObservables.observeValue(rangeKeySchemaDefinition,
                "attributeName");
        indexRangeKeyAttributeTypeModel = PojoObservables.observeValue(indexRangeKeyAttributeDefinition,
                "attributeType");
        indexRangeKeyNameInAttributeDefinitionsModel = PojoObservables
                .observeValue(indexRangeKeyAttributeDefinition, "attributeName");
        projectionTypeModel = PojoObservables.observeValue(localSecondaryIndex.getProjection(), "projectionType");

        // Get the information of the primary range key
        if (dataModel.getEnableRangeKey()) {
            primaryRangeKeyName = dataModel.getRangeKeyName();
            primaryRangeKeyTypeComboIndex = Arrays.<String>asList(DATA_TYPE_STRINGS)
                    .indexOf(dataModel.getRangeKeyType());
        } else {
            primaryRangeKeyName = null;
            primaryRangeKeyTypeComboIndex = -1;
        }

        setShellStyle(SWT.RESIZE);

    }

    @Override
    protected Control createContents(Composite parent) {
        Control contents = super.createContents(parent);
        setTitle("Add Local Secondary Index");
        setTitleImage(AwsToolkitCore.getDefault().getImageRegistry().get(AwsToolkitCore.IMAGE_AWS_LOGO));
        okButton = getButton(IDialogConstants.OK_ID);
        okButton.setEnabled(false);
        return contents;
    }

    @Override
    protected void configureShell(Shell shell) {
        super.configureShell(shell);
        shell.setText("Add Local Secondary Index");
        shell.setMinimumSize(400, 500);
    }

    @Override
    protected Control createDialogArea(Composite parent) {
        Composite composite = (Composite) super.createDialogArea(parent);
        GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);
        composite.setLayout(new GridLayout());
        composite = new Composite(composite, SWT.NULL);

        GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);
        composite.setLayout(new GridLayout(2, false));

        // Index range key attribute name
        new Label(composite, SWT.NONE | SWT.READ_ONLY).setText("Attribute to Index:");
        attributeNameText = new Text(composite, SWT.BORDER);
        bindingContext.bindValue(SWTObservables.observeText(attributeNameText, SWT.Modify),
                indexRangeKeyNameInKeySchemaDefinitionModel);
        ChainValidator<String> attributeNameValidationStatusProvider = new ChainValidator<String>(
                indexRangeKeyNameInKeySchemaDefinitionModel,
                new NotEmptyValidator("Please provide an attribute name"));
        bindingContext.addValidationStatusProvider(attributeNameValidationStatusProvider);
        bindingContext.bindValue(SWTObservables.observeText(attributeNameText, SWT.Modify),
                indexRangeKeyNameInAttributeDefinitionsModel);
        attributeNameText.addModifyListener(new ModifyListener() {

            public void modifyText(ModifyEvent e) {
                if (attributeNameText.getText().equals(primaryRangeKeyName) && attributeTypeCombo != null
                        && primaryRangeKeyTypeComboIndex > -1) {
                    attributeTypeCombo.select(primaryRangeKeyTypeComboIndex);
                    attributeTypeCombo.setEnabled(false);
                } else if (attributeTypeCombo != null) {
                    attributeTypeCombo.setEnabled(true);
                }

            }
        });
        GridDataFactory.fillDefaults().grab(true, false).applyTo(attributeNameText);

        // Index range key attribute type
        new Label(composite, SWT.NONE | SWT.READ_ONLY).setText("Attribute Type:");
        attributeTypeCombo = new Combo(composite, SWT.DROP_DOWN | SWT.READ_ONLY);
        attributeTypeCombo.setItems(DATA_TYPE_STRINGS);
        attributeTypeCombo.select(0);
        bindingContext.bindValue(SWTObservables.observeSelection(attributeTypeCombo),
                indexRangeKeyAttributeTypeModel);

        // Index name
        new Label(composite, SWT.NONE | SWT.READ_ONLY).setText("Index Name:");
        indexNameText = new Text(composite, SWT.BORDER);
        GridDataFactory.fillDefaults().grab(true, false).applyTo(indexNameText);
        bindingContext.bindValue(SWTObservables.observeText(indexNameText, SWT.Modify), indexNameModel);
        ChainValidator<String> indexNameValidationStatusProvider = new ChainValidator<String>(indexNameModel,
                new NotEmptyValidator("Please provide an index name"));
        bindingContext.addValidationStatusProvider(indexNameValidationStatusProvider);

        // Projection type
        new Label(composite, SWT.NONE | SWT.READ_ONLY).setText("Projected Attributes:");
        projectionTypeCombo = new Combo(composite, SWT.DROP_DOWN | SWT.READ_ONLY);
        projectionTypeCombo.setItems(PROJECTED_ATTRIBUTES);
        projectionTypeCombo.select(0);
        bindingContext.bindValue(SWTObservables.observeSelection(projectionTypeCombo), projectionTypeModel);
        projectionTypeCombo.addSelectionListener(new SelectionListener() {

            public void widgetSelected(SelectionEvent e) {
                if (projectionTypeCombo.getSelectionIndex() == 2) {
                    // Enable the list for adding non-key attributes to the projection
                    addAttributeButton.setEnabled(true);
                } else {
                    addAttributeButton.setEnabled(false);
                }
            }

            public void widgetDefaultSelected(SelectionEvent e) {
            }
        });

        // Non-key attributes in the projection
        final AttributeList attributeList = new AttributeList(composite);
        GridDataFactory.fillDefaults().grab(true, true).hint(SWT.DEFAULT, SWT.DEFAULT).applyTo(attributeList);
        addAttributeButton = new Button(composite, SWT.PUSH);
        addAttributeButton.setText("Add Attribute");
        addAttributeButton.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));
        addAttributeButton.setImage(AwsToolkitCore.getDefault().getImageRegistry().get(AwsToolkitCore.IMAGE_ADD));
        addAttributeButton.addSelectionListener(new SelectionListener() {

            public void widgetSelected(SelectionEvent e) {
                AddNewAttributeDialog newAttributeTable = new AddNewAttributeDialog();
                if (newAttributeTable.open() == 0) {
                    // lazy-initialize the list
                    if (null == localSecondaryIndex.getProjection().getNonKeyAttributes()) {
                        localSecondaryIndex.getProjection().setNonKeyAttributes(new LinkedList<String>());
                    }
                    localSecondaryIndex.getProjection().getNonKeyAttributes()
                            .add(newAttributeTable.getNewAttributeName());
                    attributeList.refresh();
                }
            }

            public void widgetDefaultSelected(SelectionEvent e) {
            }
        });

        addAttributeButton.setEnabled(false);

        // Finally provide aggregate status reporting for the entire wizard page
        final AggregateValidationStatus aggregateValidationStatus = new AggregateValidationStatus(bindingContext,
                AggregateValidationStatus.MAX_SEVERITY);

        aggregateValidationStatus.addChangeListener(new IChangeListener() {

            public void handleChange(ChangeEvent event) {
                Object value = aggregateValidationStatus.getValue();
                if (value instanceof IStatus == false)
                    return;
                IStatus status = (IStatus) value;
                if (status.getSeverity() == Status.ERROR) {
                    setErrorMessage(status.getMessage());
                    if (okButton != null) {
                        okButton.setEnabled(false);
                    }
                } else {
                    setErrorMessage(null);
                    if (okButton != null) {
                        okButton.setEnabled(true);
                    }
                }
            }
        });

        bindingContext.updateModels();
        return composite;
    }

    public LocalSecondaryIndex getLocalSecondaryIndex() {
        return localSecondaryIndex;
    }

    /**
     * Get the AttributeDefinition of the index range key as specified in this dialog.
     */
    public AttributeDefinition getIndexRangeKeyAttributeDefinition() {
        return indexRangeKeyAttributeDefinition;
    }

    private class AddNewAttributeDialog extends AbstractAddNewAttributeDialog {

        @Override
        public void validate() {
            if (getButton(0) == null)
                return;
            if (getNewAttributeName().length() == 0) {
                getButton(0).setEnabled(false);
                return;
            }
            getButton(0).setEnabled(true);
            return;
        }
    }

    /** The list widget for adding projected non-key attributes. **/
    private class AttributeList extends Composite {

        private ListViewer viewer;
        private AttributeListContentProvider attributeListContentProvider;

        public AttributeList(Composite parent) {
            super(parent, SWT.NONE);
            this.setLayout(new GridLayout());
            viewer = new ListViewer(this, SWT.BORDER | SWT.V_SCROLL | SWT.READ_ONLY);
            attributeListContentProvider = new AttributeListContentProvider();
            viewer.setContentProvider(attributeListContentProvider);
            viewer.setLabelProvider(new LabelProvider());
            GridDataFactory.fillDefaults().grab(true, true).applyTo(viewer.getList());
            viewer.getList().setVisible(true);
            MenuManager menuManager = new MenuManager("#PopupMenu");
            menuManager.setRemoveAllWhenShown(true);
            menuManager.addMenuListener(new IMenuListener() {

                public void menuAboutToShow(IMenuManager manager) {
                    if (viewer.getList().getSelectionCount() > 0) {

                        manager.add(new Action() {

                            @Override
                            public ImageDescriptor getImageDescriptor() {
                                return AwsToolkitCore.getDefault().getImageRegistry()
                                        .getDescriptor(AwsToolkitCore.IMAGE_REMOVE);
                            }

                            @Override
                            public void run() {
                                // In theory, this should never be null.
                                if (null != localSecondaryIndex.getProjection().getNonKeyAttributes()) {
                                    localSecondaryIndex.getProjection().getNonKeyAttributes()
                                            .remove(viewer.getList().getSelectionIndex());
                                }
                                refresh();
                            }

                            @Override
                            public String getText() {
                                return "Delete Attribute";
                            }
                        });
                    }
                }
            });
            viewer.getList().setMenu(menuManager.createContextMenu(viewer.getList()));
        }

        // Enforce to call getElements to update list
        public void refresh() {
            viewer.setInput(new Object());
        }
    }

    private class AttributeListContentProvider extends ObservableListContentProvider {

        @Override
        public void dispose() {
        }

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

        }

        @Override
        public Object[] getElements(Object inputElement) {
            return localSecondaryIndex.getProjection().getNonKeyAttributes() != null
                    ? localSecondaryIndex.getProjection().getNonKeyAttributes().toArray()
                    : new String[] {};
        }
    }
}