Package com.puppetlabs.geppetto.ui.wizard

Source Code of com.puppetlabs.geppetto.ui.wizard.NewPuppetProjectFromForgeWizard$PuppetProjectFromForgeCreationPage

/**
* Copyright (c) 2013 Puppet Labs, Inc. and other contributors, as listed below.
* All rights reserved. This program and the accompanying materials
* are 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:
*   Puppet Labs
*/
package com.puppetlabs.geppetto.ui.wizard;

import static com.puppetlabs.geppetto.common.Strings.trimToNull;
import static com.puppetlabs.geppetto.forge.Forge.METADATA_JSON_NAME;
import static com.puppetlabs.geppetto.forge.Forge.MODULEFILE_NAME;
import static com.puppetlabs.geppetto.ui.UIPlugin.getLocalString;
import static com.puppetlabs.geppetto.ui.util.ModuleUtil.getFullName;
import static com.puppetlabs.geppetto.ui.util.ModuleUtil.getText;
import static com.puppetlabs.geppetto.ui.util.ModuleUtil.getModuleVersion;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.SocketException;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
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.Text;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.dialogs.WizardNewProjectCreationPage;

import com.google.inject.Inject;
import com.puppetlabs.geppetto.diagnostic.Diagnostic;
import com.puppetlabs.geppetto.forge.ForgeService;
import com.puppetlabs.geppetto.forge.model.Metadata;
import com.puppetlabs.geppetto.forge.util.ModuleUtils;
import com.puppetlabs.geppetto.forge.v3.Modules;
import com.puppetlabs.geppetto.forge.v3.model.Module;
import com.puppetlabs.geppetto.semver.Version;
import com.puppetlabs.geppetto.semver.VersionRange;
import com.puppetlabs.geppetto.ui.UIPlugin;
import com.puppetlabs.geppetto.ui.dialog.ModuleListSelectionDialog;
import com.puppetlabs.geppetto.ui.util.ResourceUtil;

public class NewPuppetProjectFromForgeWizard extends NewPuppetModuleProjectWizard {

  protected class PuppetProjectFromForgeCreationPage extends NewPuppetModuleProjectWizard.PuppetProjectCreationPage {

    protected Text projectNameField;

    protected Text moduleField = null;

    protected PuppetProjectFromForgeCreationPage(String pageName) {
      super(pageName);
      setNeedsProgressMonitor(true);
    }

    @Override
    public void createControl(Composite parent) {
      parent = new Composite(parent, SWT.NONE);

      GridLayout gridLayout = new GridLayout();
      gridLayout.marginHeight = 0;
      gridLayout.marginWidth = 0;

      parent.setLayout(gridLayout);

      GridDataFactory.fillDefaults().applyTo(parent);

      Composite composite = new Composite(parent, SWT.NONE);

      gridLayout = new GridLayout(3, false);
      gridLayout.marginHeight = 10;
      gridLayout.marginWidth = 10;

      composite.setLayout(gridLayout);

      GridDataFactory.swtDefaults().align(SWT.FILL, SWT.FILL).grab(true, false).applyTo(composite);

      createModuleGroup(composite);

      super.createControl(parent);
      for(Control c1 : parent.getChildren())
        if(c1 instanceof Composite)
          for(Control c2 : ((Composite) c1).getChildren())
            if(c2 instanceof Composite)
              for(Control c3 : ((Composite) c2).getChildren())
                if(c3 instanceof Text && getProjectName().equals(((Text) c3).getText())) {
                  projectNameField = (Text) c3;
                  break;

                }
      setControl(parent);
    }

    protected void createModuleGroup(Composite parent) {
      Label moduleLabel = new Label(parent, SWT.NONE);
      moduleLabel.setText(getLocalString("_UI_Module_label")); //$NON-NLS-1$

      moduleField = new Text(parent, SWT.BORDER | SWT.READ_ONLY);
      moduleField.addMouseListener(new MouseAdapter() {

        @Override
        public void mouseDoubleClick(MouseEvent me) {
          promptForModuleSelection();
        }
      });

      GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true, false).applyTo(moduleField);

      Button resultTypeButton = new Button(parent, SWT.PUSH);
      resultTypeButton.setText(getLocalString("_UI_Select_label")); //$NON-NLS-1$
      resultTypeButton.addSelectionListener(new SelectionAdapter() {

        @Override
        public void widgetSelected(SelectionEvent se) {
          promptForModuleSelection();
        }
      });
    }

    protected Module[] getModuleChoices(final String keyword) {
      Module[] zeroModules = new Module[0];
      try {
        final Module[][] choicesResult = new Module[1][];
        choicesResult[0] = zeroModules;
        getContainer().run(true, true, new IRunnableWithProgress() {
          @Override
          public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
            monitor.beginTask("Fetching latest releases from the Forge", 55);
            try {
              final Exception[] te = new Exception[1];
              Thread t = new Thread() {
                @Override
                public void run() {
                  try {
                    List<Module> choices = moduleService.listAll(
                      new Modules.WithText(keyword), null, false);
                    int top = choices.size();
                    if(top > 0)
                      choicesResult[0] = choices.toArray(new Module[top]);
                  }
                  catch(SocketException e) {
                    // A user abort will cause a "Socket closed" exception We don't
                    // want to report that.
                    if(!"Socket closed".equals(e.getMessage()))
                      te[0] = e;
                  }
                  catch(Exception e) {
                    te[0] = e;
                  }
                }
              };
              t.start();
              int idx = 0;
              while(t.isAlive()) {
                t.join(1000);
                if(monitor.isCanceled()) {
                  moduleService.abortCurrentRequest();
                  throw new OperationCanceledException();
                }
                if(++idx <= 5)
                  monitor.worked(1);
              }
              if(te[0] != null)
                throw new InvocationTargetException(te[0]);
            }
            catch(RuntimeException e) {
              throw e;
            }
            catch(InvocationTargetException e) {
              throw e;
            }
            catch(Exception e) {
              throw new InvocationTargetException(e);
            }
            finally {
              monitor.done();
            }
          }
        });
        Module[] choices = choicesResult[0];
        if(choices.length > 0)
          return choices;
        MessageDialog.openConfirm(
          getShell(), getLocalString("_UI_No_modules_found"),
          getLocalString("_UI_No_module_matching_keyword", keyword));
      }
      catch(InvocationTargetException e) {
        Throwable t = e.getTargetException();
        StringBuilder builder = new StringBuilder();
        builder.append(t.getClass().getName());
        builder.append("\n");
        builder.append(t.getMessage());
        builder.append("\n\n(See the log view for technical details).");
        MessageDialog.openError(getShell(), "Error while communicating with the ForgeAPI.", //
          builder.toString()); //
        log.error("Error while communicating with the ForgeAPI", t);
      }
      catch(InterruptedException e) {
      }
      return zeroModules;
    }

    protected void promptForModuleSelection() {
      InputDialog askKeywordDialog = new InputDialog(
        getShell(), getLocalString("_UI_Keyword_Search_title"), getLocalString("_UI_Keyword_Search_message"),
        null, new IInputValidator() {
          @Override
          public String isValid(String newText) {
            newText = trimToNull(newText);
            if(newText != null) {
              if(newText.length() > 30)
                return getLocalString("_UI_Keyword_Search_max_length_exceeded", 30);
              Matcher m = OK_KEYWORD_CHARACTERS.matcher(newText);
              if(!m.matches())
                return getLocalString("_UI_Keyword_Search_bad_characters");
              m = KEYWORD_AT_LEAST_ONE_CHARACTER.matcher(newText);
              if(m.find())
                return null;
            }
            return getLocalString("_UI_Keyword_Search_at_least_one_character");
          }
        });

      if(askKeywordDialog.open() != Window.OK)
        return;

      Module[] choices = getModuleChoices(askKeywordDialog.getValue());
      if(choices.length == 0)
        return;

      ModuleListSelectionDialog dialog = new ModuleListSelectionDialog(getShell());
      dialog.setMultipleSelection(false);
      dialog.setElements(choices);

      if(module != null) {
        dialog.setInitialElementSelections(Collections.singletonList(module));
      }

      if(dialog.open() == Window.OK) {
        setModule((Module) dialog.getFirstResult());
      }
    }

    protected void setModule(Module selectedModule) {
      module = selectedModule;

      moduleField.setText(getText(module));
      projectNameField.setText(getFullName(module).getName());

      validatePage();
    }

    @Override
    public void setVisible(boolean visible) {
      super.setVisible(visible);

      if(visible) {
        moduleField.setFocus();
      }
    }

    @Override
    protected boolean validatePage() {

      if(module == null) {
        setErrorMessage(null);
        setMessage(getLocalString("_UI_ModuleCannotBeEmpty_message")); //$NON-NLS-1$
        return false;
      }

      if(super.validatePage()) {
        String preferredProjectName = getFullName(module).getName();

        if(!preferredProjectName.equals(getProjectName())) {
          setErrorMessage(null);
          setMessage(
            getLocalString("_UI_ProjectNameShouldMatchModule_message", preferredProjectName), WARNING); //$NON-NLS-1$
        }

        return true;
      }

      return false;
    }

  }

  @Inject
  private ForgeService forgeService;

  @Inject
  private Modules moduleService;

  private static final Pattern OK_KEYWORD_CHARACTERS = Pattern.compile("^[0-9A-Za-z_-]*$");

  private static final Pattern KEYWORD_AT_LEAST_ONE_CHARACTER = Pattern.compile("[A-Za-z]+");

  private static final Logger log = Logger.getLogger(NewPuppetProjectFromForgeWizard.class);

  protected Module module;

  @Override
  protected String getProjectCreationPageDescription() {
    return getLocalString("_UI_PuppetProjectFromForge_description"); //$NON-NLS-1$
  }

  @Override
  protected String getProjectCreationPageTitle() {
    return getLocalString("_UI_PuppetProjectFromForge_title"); //$NON-NLS-1$
  }

  @Override
  public void init(IWorkbench workbench, IStructuredSelection selection) {
    setDefaultPageImageDescriptor(UIPlugin.getImageDesc("full/wizban/NewPuppetProject.png")); //$NON-NLS-1$
    setWindowTitle(getLocalString("_UI_NewPuppetProjectFromForge_title")); //$NON-NLS-1$
  }

  @Override
  protected void initializeProjectContents(IProgressMonitor monitor) throws Exception {

    if(module == null)
      return;

    SubMonitor submon = SubMonitor.convert(monitor, "Generating project...", 100);
    try {
      Version v = getModuleVersion(module);
      VersionRange vr = v == null
          ? null
          : VersionRange.exact(v);

      File projectDir = project.getLocation().toFile();
      forgeService.install(getFullName(module), vr, projectDir, true, true);

      File moduleFile = new File(projectDir, MODULEFILE_NAME);
      boolean moduleFileExists = moduleFile.exists();
      if(moduleFileExists) {
        // Check if this file is viable.
        boolean renameModuleFile = false;
        Diagnostic chain = new Diagnostic();
        Metadata receiver = new Metadata();
        try {
          ModuleUtils.parseModulefile(moduleFile, receiver, chain);
          for(Diagnostic problem : chain)
            if(problem.getSeverity() >= Diagnostic.ERROR) {
              // Trust the metadata.json as the source and recreate the Modulefile
              renameModuleFile = true;
              break;
            }
        }
        catch(Exception e) {
          renameModuleFile = true;
        }

        if(renameModuleFile) {
          File renamedModuleFile = new File(projectDir, MODULEFILE_NAME + ".ignored");
          renamedModuleFile.delete();
          if(moduleFile.renameTo(renamedModuleFile))
            moduleFileExists = false;
        }
      }

      submon.worked(60);

      if(submon.isCanceled())
        throw new OperationCanceledException();

      // This will cause a build. The build will recreate the metadata.json file
      project.refreshLocal(IResource.DEPTH_INFINITE, submon.newChild(30));
      if(moduleFileExists) {
        IFile mdjsonFile = ResourceUtil.getFile(project.getFullPath().append(METADATA_JSON_NAME));
        if(mdjsonFile.exists())
          mdjsonFile.setDerived(true, null);
      }
    }
    finally {
      monitor.done();
    }
  }

  @Override
  protected WizardNewProjectCreationPage newProjectCreationPage(String pageName) {
    return new PuppetProjectFromForgeCreationPage(pageName);
  }

}
TOP

Related Classes of com.puppetlabs.geppetto.ui.wizard.NewPuppetProjectFromForgeWizard$PuppetProjectFromForgeCreationPage

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.