com.microsoft.azuretools.azureexplorer.forms.createrediscache.CreateRedisCacheForm.java Source code

Java tutorial

Introduction

Here is the source code for com.microsoft.azuretools.azureexplorer.forms.createrediscache.CreateRedisCacheForm.java

Source

/**
 * Copyright (c) Microsoft Corporation
 * <p/>
 * All rights reserved.
 * <p/>
 * MIT License
 * <p/>
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
 * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 * <p/>
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
 * the Software.
 * <p/>
 * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
 * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.microsoft.azuretools.azureexplorer.forms.createrediscache;

import java.io.IOException;
import java.net.URL;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

import javax.swing.JOptionPane;

import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.fieldassist.FieldDecoration;
import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
import org.eclipse.swt.SWT;
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.graphics.Point;
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.Link;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;

import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.microsoft.azure.management.Azure;
import com.microsoft.azure.management.resources.Location;
import com.microsoft.azure.management.resources.ResourceGroup;
import com.microsoft.azuretools.authmanage.AuthMethodManager;
import com.microsoft.azuretools.authmanage.models.SubscriptionDetail;
import com.microsoft.azuretools.azurecommons.helpers.RedisCacheUtil;
import com.microsoft.azuretools.azurecommons.rediscacheprocessors.ProcessingStrategy;
import com.microsoft.azuretools.azurecommons.rediscacheprocessors.ProcessorBase;
import com.microsoft.azuretools.azureexplorer.messages.MessageHandler;
import com.microsoft.azuretools.core.Activator;
import com.microsoft.azuretools.core.components.AzureTitleAreaDialogWrapper;
import com.microsoft.azuretools.sdkmanage.AzureManager;
import com.microsoft.azuretools.utils.AzureModel;
import com.microsoft.azuretools.utils.AzureModelController;
import com.microsoft.tooling.msservices.components.DefaultLoader;

public class CreateRedisCacheForm extends AzureTitleAreaDialogWrapper {

    private static Activator LOG = Activator.getDefault();
    protected final AzureManager azureManager;
    private List<SubscriptionDetail> selectedSubscriptions;
    private List<Location> sortedLocations;
    private List<String> sortedGroups;
    private SubscriptionDetail currentSub;
    private boolean noSSLPort = false;
    private boolean newResGrp = true;
    private boolean loaded = false;
    private final LinkedHashMap<String, String> skus;

    private String dnsNameValue = null;
    private String selectedLocationValue = null;
    private String selectedResGrpValue = null;
    private String selectedPriceTierValue = null;

    private Combo cbSubs;
    private Combo cbUseExisting;
    private Combo cbLocations;
    private Combo cbPricetiers;

    private Button chkUnblockPort;
    private Button rdoUseExisting;
    private Button rdoCreateNew;
    private Button btnOK;

    private Text txtDnsName;
    private Text txtNewResGrpName;

    private ControlDecoration decoratorDnsName;

    private Runnable onCreate;

    private ResourceBundle resourceBundle = null;

    // const variable
    private static final Integer LAYOUT_SPACING = 10;
    private static final Integer INITIAL_WIDTH = 600;
    private static final Integer INITIAL_HEIGHT = 450;
    private static final Integer REDIS_CACHE_MAX_NAME_LENGTH = 63;
    private static final String MODULE_NAME = "rediscache";
    private static final String SUBS_COMBO_ITEMS_FORMAT = "%s (%s)";
    private static final String DNS_NAME_REGEX = "^[A-Za-z0-9]+(-[A-Za-z0-9]+)*$";

    // const for widgets
    private static final String DIALOG_TITLE = "DIALOG_TITLE";
    private static final String DIALOG_MESSAGE = "DIALOG_MESSAGE";
    private static final String LABEL_DNS_NAME = "LABEL_DNS_NAME";
    private static final String LABEL_DNS_SUFFIX = "LABEL_DNS_SUFFIX";
    private static final String LABEL_SUBSCRIPTION = "LABEL_SUBSCRIPTION";
    private static final String LABEL_RESOURCE_GRP = "LABEL_RESOURCE_GRP";
    private static final String RADIOBUTTON_USE_EXIST_GRP = "RADIOBUTTON_USE_EXIST_GRP";
    private static final String RADIOBUTTON_NEW_GRP = "RADIOBUTTON_NEW_GRP";
    private static final String LABEL_LOCTION = "LABEL_LOCTION";
    private static final String LABEL_PRICING = "LABEL_PRICING";
    private static final String LINK_PRICE = "LINK_PRICE";
    private static final String CHECKBOX_SSL = "CHECKBOX_SSL";

    // const for creating information
    private static final String LOADING_LOCATION_AND_GRPS = "LOADING_LOCATION_AND_GRPS";
    private static final String LOADING = "LOADING";
    private static final String DECORACTOR_DNS = "DECORACTOR_DNS";
    private static final String CREATING_INDICATOR_FORMAT = "CREATING_INDICATOR_FORMAT";

    // const for error
    private static final String CREATING_ERROR_INDICATOR_FORMAT = "CREATING_ERROR_INDICATOR_FORMAT";
    private static final String OPEN_BROWSER_ERROR = "OPEN_BROWSER_ERROR";
    private static final String LOAD_LOCATION_AND_RESOURCE_ERROR = "LOAD_LOCATION_AND_RESOURCE_ERROR";

    /**
     * Create the dialog.
     * 
     * @param parentShell
     * @throws IOException
     */
    public CreateRedisCacheForm(Shell parentShell) throws IOException {
        super(parentShell);
        azureManager = AuthMethodManager.getInstance().getAzureManager();
        List<SubscriptionDetail> allSubs = azureManager.getSubscriptionManager().getSubscriptionDetails();
        selectedSubscriptions = allSubs.stream().filter(SubscriptionDetail::isSelected)
                .collect(Collectors.toList());
        if (selectedSubscriptions.size() > 0) {
            currentSub = selectedSubscriptions.get(0);
        }
        skus = RedisCacheUtil.initSkus();
    }

    /**
     * Create contents of the dialog.
     * 
     * @param parent
     */
    @Override
    protected Control createDialogArea(Composite parent) {
        resourceBundle = MessageHandler.getResourceBundle(MODULE_NAME);
        if (resourceBundle == null) {
            return null;
        }
        setTitle(MessageHandler.getResourceString(resourceBundle, DIALOG_TITLE));
        setMessage(MessageHandler.getResourceString(resourceBundle, DIALOG_MESSAGE));
        Composite area = (Composite) super.createDialogArea(parent);
        Composite container = new Composite(area, SWT.NONE);
        GridLayout glContainer = new GridLayout(4, false);
        glContainer.horizontalSpacing = LAYOUT_SPACING;
        glContainer.verticalSpacing = LAYOUT_SPACING;
        container.setLayout(glContainer);
        container.setLayoutData(new GridData(GridData.FILL_BOTH));

        Label lblDnsName = new Label(container, SWT.NONE);
        lblDnsName.setText(MessageHandler.getResourceString(resourceBundle, LABEL_DNS_NAME));

        txtDnsName = new Text(container, SWT.BORDER);
        txtDnsName.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));

        decoratorDnsName = new ControlDecoration(txtDnsName, SWT.CENTER);
        decoratorDnsName.setDescriptionText(MessageHandler.getResourceString(resourceBundle, DECORACTOR_DNS));
        FieldDecoration fieldDecoration = FieldDecorationRegistry.getDefault()
                .getFieldDecoration(FieldDecorationRegistry.DEC_ERROR);
        if (fieldDecoration != null) {
            Image image = fieldDecoration.getImage();
            decoratorDnsName.setImage(image);
        }

        Label lblDnsSuffix = new Label(container, SWT.NONE);
        lblDnsSuffix.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
        lblDnsSuffix.setText(MessageHandler.getResourceString(resourceBundle, LABEL_DNS_SUFFIX));

        Label lblSubscription = new Label(container, SWT.NONE);
        lblSubscription.setText(MessageHandler.getResourceString(resourceBundle, LABEL_SUBSCRIPTION));

        cbSubs = new Combo(container, SWT.READ_ONLY);
        cbSubs.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));

        Label lblResourceGroup = new Label(container, SWT.NONE);
        lblResourceGroup.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1));
        lblResourceGroup.setText(MessageHandler.getResourceString(resourceBundle, LABEL_RESOURCE_GRP));

        rdoCreateNew = new Button(container, SWT.RADIO);
        rdoCreateNew.setText(MessageHandler.getResourceString(resourceBundle, RADIOBUTTON_NEW_GRP));
        rdoCreateNew.setSelection(true);

        txtNewResGrpName = new Text(container, SWT.BORDER);
        txtNewResGrpName.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));
        txtNewResGrpName.setEnabled(true);

        rdoUseExisting = new Button(container, SWT.RADIO);
        rdoUseExisting.setText(MessageHandler.getResourceString(resourceBundle, RADIOBUTTON_USE_EXIST_GRP));
        rdoUseExisting.setSelection(false);

        cbUseExisting = new Combo(container, SWT.READ_ONLY);
        cbUseExisting.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));
        cbUseExisting.add(MessageHandler.getResourceString(resourceBundle, LOADING));
        cbUseExisting.select(0);
        cbUseExisting.setEnabled(false);

        Label lblLocation = new Label(container, SWT.NONE);
        lblLocation.setText(MessageHandler.getResourceString(resourceBundle, LABEL_LOCTION));

        cbLocations = new Combo(container, SWT.READ_ONLY);
        cbLocations.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));
        cbLocations.add(MessageHandler.getResourceString(resourceBundle, LOADING));
        cbLocations.select(0);
        cbLocations.setEnabled(false);

        Label lblPricingTier = new Label(container, SWT.READ_ONLY);
        lblPricingTier.setText(MessageHandler.getResourceString(resourceBundle, LABEL_PRICING));

        cbPricetiers = new Combo(container, SWT.READ_ONLY);
        cbPricetiers.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));

        if (skus.keySet().size() > 0) {
            for (String price : skus.keySet()) {
                cbPricetiers.add(price);
            }
            cbPricetiers.select(0);
            selectedPriceTierValue = cbPricetiers.getText();
        }

        Link lnkPrice = new Link(container, SWT.NONE);
        lnkPrice.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1));
        lnkPrice.setText(MessageHandler.getResourceString(resourceBundle, LINK_PRICE));
        lnkPrice.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent event) {
                try {
                    PlatformUI.getWorkbench().getBrowserSupport().getExternalBrowser().openURL(new URL(event.text));
                } catch (Exception ex) {
                    LOG.log(MessageHandler.getCommonStr(OPEN_BROWSER_ERROR), ex);
                }
            }
        });

        chkUnblockPort = new Button(container, SWT.CHECK);
        chkUnblockPort.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1));
        chkUnblockPort.setText(MessageHandler.getResourceString(resourceBundle, CHECKBOX_SSL));

        this.setHelpAvailable(false);

        txtDnsName.addModifyListener(new ModifyListener() {

            @Override
            public void modifyText(ModifyEvent arg0) {
                dnsNameValue = txtDnsName.getText();
                if (dnsNameValue.length() > REDIS_CACHE_MAX_NAME_LENGTH || !dnsNameValue.matches(DNS_NAME_REGEX)) {
                    decoratorDnsName.show();
                } else {
                    decoratorDnsName.hide();
                }
                validateFields();
            }
        });

        for (SubscriptionDetail sub : selectedSubscriptions) {
            cbSubs.add(String.format(SUBS_COMBO_ITEMS_FORMAT, sub.getSubscriptionName(), sub.getSubscriptionId()));
        }

        cbSubs.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                currentSub = selectedSubscriptions.get(cbSubs.getSelectionIndex());
                if (loaded) {
                    fillLocationsAndResourceGrps(currentSub);
                }
                validateFields();
            }
        });
        if (selectedSubscriptions.size() > 0) {
            cbSubs.select(0);
        }

        rdoCreateNew.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                txtNewResGrpName.setEnabled(true);
                cbUseExisting.setEnabled(false);
                newResGrp = true;
                selectedResGrpValue = txtNewResGrpName.getText();
                validateFields();
            }
        });

        rdoUseExisting.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                txtNewResGrpName.setEnabled(false);
                cbUseExisting.setEnabled(true);
                if (loaded) {
                    newResGrp = false;
                    selectedResGrpValue = sortedGroups.get(cbUseExisting.getSelectionIndex());
                    validateFields();
                }

            }
        });

        txtNewResGrpName.addModifyListener(new ModifyListener() {
            @Override
            public void modifyText(ModifyEvent arg0) {
                selectedResGrpValue = txtNewResGrpName.getText();
                validateFields();
            }
        });

        cbUseExisting.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                selectedResGrpValue = cbUseExisting.getText();
                validateFields();
            }
        });

        cbLocations.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                selectedLocationValue = sortedLocations.get(cbLocations.getSelectionIndex()).name();
                validateFields();
            }
        });

        cbPricetiers.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                selectedPriceTierValue = cbPricetiers.getText();
                validateFields();
            }
        });

        chkUnblockPort.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                Button btn = (Button) e.getSource();
                if (btn.getSelection()) {
                    noSSLPort = true;
                } else {
                    noSSLPort = false;
                }
            }
        });

        DefaultLoader.getIdeHelper().runInBackground(null,
                MessageHandler.getResourceString(resourceBundle, LOADING_LOCATION_AND_GRPS), false, true,
                MessageHandler.getResourceString(resourceBundle, LOADING_LOCATION_AND_GRPS), new Runnable() {
                    @Override
                    public void run() {
                        try {
                            AzureModelController.updateSubscriptionMaps(null);
                            DefaultLoader.getIdeHelper().invokeLater(new Runnable() {
                                @Override
                                public void run() {
                                    fillLocationsAndResourceGrps(currentSub);
                                    cbLocations.setEnabled(true);
                                    loaded = true;
                                    validateFields();
                                }
                            });
                        } catch (Exception ex) {
                            LOG.log(MessageHandler.getCommonStr(LOAD_LOCATION_AND_RESOURCE_ERROR), ex);
                        }
                    }
                });

        return area;
    }

    /**
     * Create contents of the button bar.
     * 
     * @param parent
     */
    @Override
    protected void createButtonsForButtonBar(Composite parent) {
        createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, false);
        createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
        btnOK = getButton(IDialogConstants.OK_ID);
        btnOK.setEnabled(false);
    }

    /**
     * Return the initial size of the dialog.
     */
    @Override
    protected Point getInitialSize() {
        return new Point(INITIAL_WIDTH, INITIAL_HEIGHT);
    }

    @Override
    protected boolean isResizable() {
        return true;
    }

    @Override
    protected void okPressed() {
        try {
            if (!RedisCacheUtil.doValidate(azureManager, currentSub, dnsNameValue, selectedLocationValue,
                    selectedResGrpValue, selectedPriceTierValue)) {
                return;
            }
            Azure azure = azureManager.getAzure(currentSub.getSubscriptionId());
            ProcessingStrategy processor = RedisCacheUtil.doGetProcessor(azure, skus, dnsNameValue,
                    selectedLocationValue, selectedResGrpValue, selectedPriceTierValue, noSSLPort, newResGrp);
            ExecutorService executor = Executors.newSingleThreadExecutor();
            ListeningExecutorService executorService = MoreExecutors.listeningDecorator(executor);
            ListenableFuture<Void> futureTask = executorService.submit(new CreateRedisCacheCallable(processor));
            final ProcessingStrategy processorInner = processor;
            Futures.addCallback(futureTask, new FutureCallback<Void>() {
                @Override
                public void onSuccess(Void arg0) {
                    if (onCreate != null) {
                        onCreate.run();
                    }
                }

                @Override
                public void onFailure(Throwable throwable) {
                    JOptionPane.showMessageDialog(null, throwable.getMessage(),
                            String.format(MessageHandler.getResourceString(resourceBundle,
                                    CREATING_ERROR_INDICATOR_FORMAT), dnsNameValue),
                            JOptionPane.ERROR_MESSAGE, null);
                    try {
                        processorInner.notifyCompletion();
                    } catch (InterruptedException ex) {
                        LOG.log("Error occurred while notifyCompletion in RedisCache.", ex);
                    }
                }
            });
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(null, ex.getMessage(),
                    String.format(MessageHandler.getResourceString(resourceBundle, CREATING_ERROR_INDICATOR_FORMAT),
                            dnsNameValue),
                    JOptionPane.ERROR_MESSAGE, null);
            LOG.log(String.format(MessageHandler.getResourceString(resourceBundle, CREATING_ERROR_INDICATOR_FORMAT),
                    dnsNameValue), ex);
        }
        super.okPressed();
    }

    private void fillLocationsAndResourceGrps(SubscriptionDetail selectedSub) {
        cbLocations.removeAll();
        List<Location> locations = AzureModel.getInstance().getSubscriptionToLocationMap().get(selectedSub);
        if (locations != null) {
            sortedLocations = locations.stream().sorted(Comparator.comparing(Location::displayName))
                    .collect(Collectors.toList());
            for (Location location : sortedLocations) {
                cbLocations.add(location.displayName());
            }
            if (sortedLocations.size() > 0) {
                cbLocations.select(0);
                selectedLocationValue = sortedLocations.get(0).name();
            }
        }
        cbUseExisting.removeAll();
        List<ResourceGroup> groups = AzureModel.getInstance().getSubscriptionToResourceGroupMap().get(selectedSub);
        if (groups != null) {
            sortedGroups = groups.stream().map(ResourceGroup::name).sorted().collect(Collectors.toList());
            for (String group : sortedGroups) {
                cbUseExisting.add(group);
            }
            if (sortedGroups.size() > 0) {
                cbUseExisting.select(0);
                if (rdoUseExisting.getSelection()) {
                    newResGrp = false;
                    selectedResGrpValue = sortedGroups.get(0);
                }
            }
        }
    }

    private void validateFields() {
        boolean allFieldsCompleted = loaded && !(dnsNameValue == null || dnsNameValue.isEmpty()
                || dnsNameValue.length() > REDIS_CACHE_MAX_NAME_LENGTH || !dnsNameValue.matches(DNS_NAME_REGEX)
                || selectedLocationValue == null || selectedLocationValue.isEmpty() || selectedResGrpValue == null
                || selectedResGrpValue.isEmpty() || selectedPriceTierValue == null
                || selectedPriceTierValue.isEmpty());

        btnOK.setEnabled(allFieldsCompleted);
    }

    @Override
    public Map<String, String> toProperties() {
        final Map<String, String> properties = new HashMap<>();
        if (currentSub != null) {
            if (currentSub.getSubscriptionName() != null)
                properties.put("SubscriptionName", currentSub.getSubscriptionName());
            if (currentSub.getSubscriptionId() != null)
                properties.put("SubscriptionId", currentSub.getSubscriptionId());
        }
        return properties;
    }

    public void setOnCreate(Runnable onCreate) {
        this.onCreate = onCreate;
    }

    class CreateRedisCacheCallable implements Callable<Void> {
        private ProcessingStrategy processor;

        public CreateRedisCacheCallable(ProcessingStrategy processor) {
            this.processor = processor;
        }

        public Void call() throws Exception {
            DefaultLoader.getIdeHelper().runInBackground(null,
                    String.format(MessageHandler.getResourceString(resourceBundle, CREATING_INDICATOR_FORMAT),
                            ((ProcessorBase) processor).DNSName()),
                    false, true,
                    String.format(MessageHandler.getResourceString(resourceBundle, CREATING_INDICATOR_FORMAT),
                            ((ProcessorBase) processor).DNSName()),
                    new Runnable() {
                        @Override
                        public void run() {
                            try {
                                processor.waitForCompletion("PRODUCE");
                            } catch (InterruptedException ex) {
                                LOG.log(String.format(MessageHandler.getResourceString(resourceBundle,
                                        CREATING_ERROR_INDICATOR_FORMAT), dnsNameValue), ex);
                            }
                        }
                    });
            // consume
            processor.process().notifyCompletion();
            return null;
        }
    }
}