Package org.openiaml.docs.tools

Source Code of org.openiaml.docs.tools.ExportIAMLImagesJob

/**
*
*/
package org.openiaml.docs.tools;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
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.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
import org.eclipse.gmf.runtime.diagram.ui.image.ImageFileFormat;
import org.eclipse.gmf.runtime.diagram.ui.render.util.CopyToImageUtil;
import org.eclipse.gmf.runtime.diagram.ui.resources.editor.parts.DiagramDocumentEditor;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
import org.openiaml.docs.tools.InitialiseDiagram.InitializeDiagramException;
import org.openiaml.model.diagram.custom.helpers.DiagramRegistry;
import org.openiaml.model.model.ModelPackage;

/**
* @author jmwright
*
*/
public class ExportIAMLImagesJob extends AbstractIAMLDocJob {

  // the package we will search for (we can change this if necessary)
  private EPackage rootPackage = ModelPackage.eINSTANCE;
 
  private IProject project;
 
  public ExportIAMLImagesJob(IProject project) {
    super("Export IAML element images");
    this.project = project;
    setUser(true);    // we are a user job, so we should get some feedback
  }

  /**
   * Do the actual work.
   */
  @Override
  protected IStatus runActual(IProgressMonitor monitor) throws CoreException {
    // new task
    monitor.beginTask(this.getName(), 100);
   
    // find out the object we should search for
    monitor.subTask("Compiling list of EMF objects to search for");
    List<EClass> objects = getObjectsToSearchFor(rootPackage);
    if (objects.isEmpty()) {
      // no objects to search for
      return errorStatus("No EMF objects to search for; expected at least one.");
    }
    monitor.worked(10)// 10%
   
    // check that at least one exists
    monitor.subTask("Checking project for at least one EMF object");
    if (!checkAtLeastOneExists(objects)) {
      // failed
      return errorStatus("Could not find any matching root files for any EMF object in this project.");
    }
    monitor.worked(10)// 10%
   
    // finally, if we got all the way here, do the search
    IStatus status = doExport(objects, new SubProgressMonitor(monitor, 80));
    monitor.done();
   
    return status;
  }
 
  /* (non-Javadoc)
   * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
   */
  @Override
  protected IStatus run(final IProgressMonitor monitor) {
     
      Display.getDefault().syncExec(new Runnable() {
        @Override
        public void run() {
          try {
            IStatus status = runActual(monitor);
           
            if (!status.isOK()) {
            DocToolsPlugin.getInstance().getLog().log(status);
          }
          } catch (CoreException e) {
          IStatus error = new Status(Status.ERROR, DocToolsPlugin.PLUGIN_ID, "An exception occured: " + e.getMessage(), e);
          DocToolsPlugin.getInstance().getLog().log(error);
         
        }
        }
      });
     
    // can't get the real status yet
    return Status.OK_STATUS;
     
   
  }

  /**
   * For the given class: Try and find a corresponding model file;
   * initialise the diagram file and try to open it; export the
   * root image (and <em>only</em> the root); and then delete the diagram file.
   *
   * @see DiagramRegistry#initializeModelFile(IFile, IFile)
   * @see #exportDiagramThenClose(EClass, DiagramDocumentEditor, IProgressMonitor)
   */
  protected IStatus doExport(List<EClass> classes, IProgressMonitor monitor) throws CoreException {
   
    // count of images exported
    int exported = 0;
   
    // we collect up all uninitialisable diagrams, so we can
    // quickly see which ones were unable to open
    MultiStatus errorResult = new MultiStatus(DocToolsPlugin.PLUGIN_ID, Status.ERROR, "Could not export example images: multiple errors occured", null);
   
    for (EClass cls : classes) {
      monitor.beginTask("Exporting class " + cls.getName(), 105);
     
      monitor.subTask("Finding file for class " + cls.getName());
      IFile file = getFileFor(cls);
      if (getFileFor(cls) == null
        continue;    // skip
     
      monitor.worked(10);
     
      InitialiseDiagram init = new InitialiseDiagram();
      IFile diagram;
      try {
        diagram = init.initialize(project, file, true /* open new diagram */, new SubProgressMonitor(monitor, 50));
      } catch (InitializeDiagramException e) {
        // if we couldn't initialise it, skip it
        errorResult.add(errorStatus("Class '" + cls.getName() + "'", e));
        continue;
      }
     
      // the diagram should now be opened
      monitor.subTask("Exporting root image");
     
      // get the active workbench editor part
      // based on IamlDiagramEditorUtil#openDiagram()
      IWorkbenchPage page = PlatformUI.getWorkbench()
        .getActiveWorkbenchWindow().getActivePage();
      DiagramDocumentEditor editor = (DiagramDocumentEditor) page.getActiveEditor();
     
      // export only one image
      exportDiagramThenClose(cls, editor, new SubProgressMonitor(monitor, 40));
     
      // finally, delete the diagram file
      monitor.subTask("Deleting diagram file");
      diagram.delete(true, new SubProgressMonitor(monitor, 5));
      monitor.done();
     
      exported++;

    }
   
    // any errors in initialising?
    if (errorResult.getChildren().length != 0) {
      return errorResult;
    }
   
    // done
    if (exported == 0) {
      // we didn't export any! throw a warning
      return new Status(Status.WARNING, DocToolsPlugin.PLUGIN_ID, "Did not export any root element images");
    }

    return Status.OK_STATUS;
  }
 
  /**
   * For the currently open editor: export the image to PNG; then try and
   * force the editor closed (if supported).
   */
  protected void exportDiagramThenClose(EClass cls, DiagramDocumentEditor editor, IProgressMonitor monitor) throws CoreException {
    DiagramEditPart part = editor.getDiagramEditPart();
   
    // save this image
    // (even if there isn't anything in it)
    IProgressMonitor saveMonitor = new SubProgressMonitor(monitor, 2);
    saveMonitor.beginTask("Saving image for " + cls.getName(), 2);
   
    // issue 193: first save as png
    {
      IPath destination = generateImageDestination(cls, ".png");
      monitor.subTask("Saving PNG image " + destination.lastSegment());
      CopyToImageUtil img = getCopyToImageUtil();
      img.copyToImage(part, destination, ImageFileFormat.PNG, new SubProgressMonitor(monitor, 1));
      saveMonitor.worked(1);
    }

    // issue 193: then save as svg
    {
      IPath destination = generateImageDestination(cls, ".svg");
      monitor.subTask("Saving SVG image " + destination.lastSegment());
      CopyToImageUtil img = getCopyToImageUtil();
      img.copyToImage(part, destination, ImageFileFormat.SVG, new SubProgressMonitor(monitor, 1));
      saveMonitor.worked(1);
    }

    saveMonitor.done();
   
    // close the editor once we're done
    // (this is done asynchronously, so there might still be things going on in the
    // editor when the monitor is marked 'done')
   
    // if we have a closeBlocking method (Jevon extension), invoke that instead
    try {
      Method method = editor.getClass().getMethod("closeBlocking", new Class[] { boolean.class} );
      method.invoke(editor, new Object[] { false } );
      return;
    } catch (SecurityException e) {
      // ignore
    } catch (NoSuchMethodException e) {
      // ignore
    } catch (IllegalArgumentException e) {
      // ignore
    } catch (IllegalAccessException e) {
      // ignore
    } catch (InvocationTargetException e) {
      // ignore
    }
   
    // do normal close
    editor.close(false);
   
  }

  /**
   * Create a new {@link CopyToImageUtil}, which will be used
   * to export images.
   *
   * @see CopyToImageUtil#copyToImage(DiagramEditPart, IPath, ImageFileFormat, IProgressMonitor)
   * @return
   */
  protected CopyToImageUtil getCopyToImageUtil() {
    return new CopyToImageUtil();
  }
 
  /**
   * @param fileExtension the file extension to add, e.g. ".png"
   * @throws IllegalArgumentException if fileExtension does not start with '.'
   * @return
   */
  protected IPath generateImageDestination(EClass cls, String fileExtension) {
    if (!fileExtension.startsWith("."))
      throw new IllegalArgumentException("File extension needs to start with '.'");
    return project.getFile(cls.getName() + fileExtension).getLocation();
  }

  /**
   * @param classes the classes to search for
   * @return true if at least one exists; false otherwise
   * @throws CoreException
   */
  protected boolean checkAtLeastOneExists(List<EClass> classes) throws CoreException {
   
    for (EClass cls : classes) {
      if (getFileFor(cls) != null)
        return true// found one
    }

    // none found
    return false;
  }
 
  /**
   * Search for the matching file for the given class. Ignores
   * <code>.foo_diagram</code> files.
   *
   * @param cls
   * @return The file found <code>object_name.something</code>, or <code>null</code> if none was found
   * @throws CoreException
   */
  protected IFile getFileFor(EClass cls) throws CoreException {
    // get all the root files in this project
    IResource[] resources = project.members();
    for (IResource res : resources) {
      if (res instanceof IFile) {
        IFile file = (IFile) res;
       
        // ignore *.foo_diagram files
        if (file.getFileExtension().endsWith("_diagram"))
          continue;
       
        // does the name match (case-sensitive) any object name?
        if (file.getName().startsWith(cls.getName() + ".")) {
          return file;
        }
      }
    }
   
    // none found
    return null;
  }

  /**
   * Get all non-abstract, non-interface EClasses in this package and subpackages (recursive).
   *
   * @return A list of non-abstract, non-interface EClasses in this package and subpackages.
   */
  protected List<EClass> getObjectsToSearchFor(EPackage pkg) {
    List<EClass> result = new ArrayList<EClass>();
   
    for (EClassifier cf : pkg.getEClassifiers()) {
      if (cf instanceof EClass) {
        EClass cls = (EClass) cf;
        if (cls.isAbstract()) continue;
        if (cls.isInterface()) continue;
       
        // ok
        result.add(cls);
      }
    }
   
    // subpackages
    for (EPackage sub : pkg.getESubpackages()) {
      result.addAll(getObjectsToSearchFor(sub));
    }
   
    return result;
  }
 
}
TOP

Related Classes of org.openiaml.docs.tools.ExportIAMLImagesJob

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.