Package org.openiaml.model.custom.actions

Source Code of org.openiaml.model.custom.actions.GenerateCodeAction

package org.openiaml.model.custom.actions;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Display;
import org.openiaml.model.ModelLoader;
import org.openiaml.model.ModelLoader.ModelLoadException;
import org.openiaml.model.actions.QuestionDialogResult;
import org.openiaml.model.codegen.DefaultRuntimeProperties;
import org.openiaml.model.codegen.ICodeGenerator;
import org.openiaml.model.codegen.php.CheckModelInstance;
import org.openiaml.model.codegen.php.OawCodeGeneratorWithRuntime;
import org.openiaml.model.drools.CreateMissingElementsWithDrools;
import org.openiaml.model.drools.EcoreInferenceHandlerFactory;
import org.openiaml.model.inference.InferenceException;

/**
* Action to generate code from an .iaml file
*
* @see org.openiaml.model.codegen.php
* @author jmwright
*
*/
public class GenerateCodeAction extends IamlFileAction {
 
  private EObject model;
 
  /**
   * Get a helpful list of error messages from the given status.
   *
   * @param status
   * @return
   */
  private String getErrorMessage(IStatus status) {
    if (status.isMultiStatus()) {
      // get the first 4 errors
      MultiStatus multi = (MultiStatus) status;
      String result = "";
      for (int i = 0; i < 4 && i < multi.getChildren().length; i++) {
        result += (i == 0 ? "" : "\n") + multi.getChildren()[i].getMessage();
      }
      if (multi.getChildren().length > 4) {
        result += "\n(... " + (multi.getChildren().length - 4) + " more)";
      }
      return result;
    } else {
      return status.getMessage();
    }
  }
 
  /* (non-Javadoc)
   * @see org.openiaml.model.diagram.custom.actions.ProgressEnabledAction#execute(java.lang.Object, org.eclipse.core.runtime.IProgressMonitor)
   */
  @Override
  public IStatus doExecute(IFile o, IProgressMonitor monitor) throws InferenceException, IOException, CoreException {
    monitor.beginTask("Generating code for file '" + o.getName() + "'", 150);

    // first, load the model
    monitor.subTask("Loading model");
    try {
      model = ModelLoader.load(o);
    } catch (ModelLoadException e) {
      return errorStatus(e);
    }
    monitor.worked(10);
   
    // first, run OAW checks to check that the initial model instance is valid
    monitor.subTask("Checking initial model instance");
    CheckModelInstance check = new CheckModelInstance();
    final IStatus result = check.checkModel(model, o.getProject(), new SubProgressMonitor(monitor, 30));
    final QuestionDialogResult answer = new QuestionDialogResult();
   
    if (monitor.isCanceled())
      return Status.CANCEL_STATUS;

    if (!result.isOK()) {
      // log the result
      getDefaultPlugin().log(result);
     
      if (couldBePhantomEdges(result)) {
          // issue 132: automatically suggest the removal of phantom edges
         
        // get user confirmation
        Display.getDefault().syncExec(new Runnable() {
            @Override
            public void run() {
              answer.setResult(MessageDialog.openConfirm(null,
                "Possible phantom edges",
                "It appears that there may be phantom edges in your model:\n\n" +
                  getErrorMessage(result) +
                  "\n\nWould you like to automatically remove these edges?"));
            }
          });
       
        if (answer.getResult()) {
          // remove phantom edges
          RemovePhantomEdgesAction phantom = new RemovePhantomEdgesAction();
          phantom.doExecute(o, new SubProgressMonitor(monitor, 10));
         
          // refresh project
          if (o.getParent() != null) {
            o.getParent().refreshLocal(IFile.DEPTH_ONE, new SubProgressMonitor(monitor, 10));
          }
         
          // and execute again
          return doExecute(o, new SubProgressMonitor(monitor, 80));
        }
         
        }
     
      // get user confirmation
      Display.getDefault().syncExec(new Runnable() {
          @Override
          public void run() {
            answer.setResult(MessageDialog.openConfirm(null,
              "Initial validation failed",
              "An error occured when validating the initial model:\n\n" +
                getErrorMessage(result) +
                "\n\nWould you still like to continue with code generation?"));
          }
        });

      if (!answer.getResult()) {
        // user canceled
        return Status.CANCEL_STATUS;
      }
    }

    if (monitor.isCanceled())
      return Status.CANCEL_STATUS;

    // do inference on the model
    CreateMissingElementsWithDrools ce = new CreateMissingElementsWithDrools(new EcoreInferenceHandlerFactory(), false);
    ce.create(model, new SubProgressMonitor(monitor, 45));
   
    if (monitor.isCanceled())
      return Status.CANCEL_STATUS;

    // does a properties file exist?
    // (used to define the location of runtime libraries)
    IFile properties = null;
    IFile saveInferred = null;
    if (o.getParent() instanceof IFolder) {
      properties = ((IFolder) o.getParent()).getFile("runtime.properties");
      saveInferred = ((IFolder) o.getParent()).getFile(getSaveInferredModelFilename(o));
    } else if (o.getParent() instanceof IProject) {
      properties = ((IProject) o.getParent()).getFile("runtime.properties");
      saveInferred = ((IProject) o.getParent()).getFile(getSaveInferredModelFilename(o));
    }
   
    // load the properties file if it does
    Map<String,String> runtimeProperties = getDefaultProperties();
    if (properties != null && properties.exists()) {
      // read it
      runtimeProperties = readProperties(properties);
    }

    if (monitor.isCanceled())
      return Status.CANCEL_STATUS;
   
    // save a copy of the inferred model
    if (saveInferred != null) {
      monitor.subTask("Saving a copy of the inferred model");
      File tempJavaFile = File.createTempFile("temp-iaml", ".iaml");
      Map<?,?> options = model.eResource().getResourceSet().getLoadOptions();
      model.eResource().save(new FileOutputStream(tempJavaFile), options);
     
      // now load it into IFile
      IProgressMonitor sub = new SubProgressMonitor(monitor, 10);
      if (saveInferred.exists()) {
        saveInferred.setContents(new FileInputStream(tempJavaFile), true, false, sub);        
      } else {
        saveInferred.create(new FileInputStream(tempJavaFile), true, sub);       
      }
      sub.done();
    } else {
      monitor.worked(10);
    }
   
    if (monitor.isCanceled()) {
      return Status.CANCEL_STATUS;
    }
 
    // create code generator instance
    ICodeGenerator codegen = new OawCodeGeneratorWithRuntime();
    IStatus status = codegen.generateCode(model, o.getProject(), new SubProgressMonitor(monitor, 50), runtimeProperties);

    if (monitor.isCanceled())
      return Status.CANCEL_STATUS;

    // finished
    monitor.done();
   
    return status;
  }

  /**
   * Get a filename to save the inferred model to, or <code>null</code>
   * if none can be found.
   *
   * <p>By default, returns <code>file.inferred.iaml</code> for
   * a <code>file.iaml</code>. Doesn't check to see if the file
   * exists or not (assumed to overwrite).
   *
   * @param o
   * @return
   */
  private String getSaveInferredModelFilename(IFile o) {
    String name = o.getName();
    String[] bits = name.split("\\.");
    if (bits.length <= 1) {
      return null;
    }
   
    StringBuffer newName = new StringBuffer();
    for (int i = 0; i < bits.length - 1; i++) {
      newName.append(bits[i]).append(".");
    }
    newName.append("inferred.");
    newName.append(bits[bits.length-1]);
   
    return newName.toString();
  }

  /**
   * Could the given result status be due to phantom edges?
   *
   * @param result
   * @return
   */
  private boolean couldBePhantomEdges(IStatus result) {
    if (result.isMultiStatus()) {
      for (IStatus status : result.getChildren()) {
        if (couldBePhantomEdges(status))
          return true;
      }
    }
   
    if (result.getMessage().startsWith("A WireEdge must have a 'to'"))
      return true;
   
    if (result.getMessage().startsWith("A WireEdge must have a 'from'"))
      return true;

    return false;
  }

  /**
   * Read in an IFile into a Map.
   *
   * @param properties
   * @return
   * @throws CoreException
   * @throws IOException
   */
  protected Map<String, String> readProperties(IFile properties) throws IOException, CoreException {
   
    Properties p = new Properties();
    p.load(properties.getContents());
   
    Map<String,String> result = new HashMap<String,String>();
    for (Object key : p.keySet()) {
      result.put((String) key, (String) p.get(key));
    }
   
    return result;
   
  }

  /**
   * Get the default runtime properties.
   *
   * @see DefaultRuntimeProperties#getDefaultProperties()
   * @return
   */
  protected Map<String, String> getDefaultProperties() {
    return new DefaultRuntimeProperties().getDefaultProperties();
  }

  /* (non-Javadoc)
   * @see org.openiaml.model.diagram.custom.actions.ProgressEnabledAction#getErrorMessage(java.lang.Object, java.lang.String)
   */
  @Override
  public String getErrorMessage(IFile individual, String message) {
    return "Could not generate code for '" + individual.getName() + "': " + message;
  }

  /* (non-Javadoc)
   * @see org.openiaml.model.diagram.custom.actions.ProgressEnabledAction#getProgressMessage()
   */
  @Override
  public String getProgressMessage() {
    return "Generating code";
  }

  /* (non-Javadoc)
   * @see org.openiaml.model.diagram.custom.actions.IamlFileAction#getLoadedModel()
   */
  @Override
  protected EObject getLoadedModel() {
    return model;
  }

  /**
   * Issue 208: If the code generation process returns a Status higher than
   * {@link Status#ERROR}, then display the error message in a
   * dialog box.
   *
   * <p>{@inheritDoc}
   */
  @Override
  public IStatus execute(IFile o, IProgressMonitor monitor) {
    final IStatus status = super.execute(o, monitor);
   
    if (status.getSeverity() >= Status.ERROR) {
      // display in the UI thread
      // get user confirmation
      Display.getDefault().asyncExec(new Runnable() {
          @Override
          public void run() {
            ErrorDialog.openError(null,
                "Code generation failed",
                "Could not generate code: " + status.getMessage(),
                status);
          }
        });
   
    }
   
    return status;
  }

}
TOP

Related Classes of org.openiaml.model.custom.actions.GenerateCodeAction

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.