Package org.ftlines.metagen.eclipse

Source Code of org.ftlines.metagen.eclipse.Build

package org.ftlines.metagen.eclipse;

import java.io.ByteArrayInputStream;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
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.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.ftlines.metagen.eclipse.model.ErrorCollector;

public class Build implements ErrorCollector {

  private final IJavaProject javaProject;
  private final IProject project;
  private final IProgressMonitor monitor;
  private final IClasspathEntry root;
  private final IPath rootPath;

  public Build(IJavaProject javaProject, IProgressMonitor monitor, IClasspathEntry root) {
    this.javaProject = javaProject;
    this.project = javaProject.getProject();
    this.monitor = monitor;
    this.root = root;
    this.rootPath = root.getPath().removeFirstSegments(1);
  }

  private IFile getFile(IResource resource) {
    return project.getFile(resource.getProjectRelativePath());
  }

  private ICompilationUnit getCompilationUnit(IResource resource) {
    String extension = resource.getFileExtension();
    String name = resource.getName();
    if ("java".equals(extension) && !"package-info".equals(name)) {
      IFile file = getFile(resource);
      return JavaCore.createCompilationUnitFrom(file);
    }
    return null;
  }

  private ASTNode parse(ICompilationUnit cu) throws JavaModelException {
    if (!cu.isConsistent()) {
      return cu.reconcile(AST.JLS4, true, null, monitor);
    } else {
      ASTParser parser = ASTParser.newParser(AST.JLS4);

      // TODO: it may be possible to convert SimpleNames and QualifiedNames to
      // fully qualified names, thereby avoiding full binding resolution.

      parser.setResolveBindings(true);
      parser.setSource(cu);

      monitor.subTask("Metagen: parsing AST of " + cu.getElementName());

      return parser.createAST(monitor);
    }

  }

  private IFile getMetaFile(ICompilationUnit cu) {
    IType type = cu.findPrimaryType();
    if (type == null) {
      // compilation unit without a type - like package-info.java
      return null;
    }

    String name = type.getFullyQualifiedName().replace('.', '/') + "Meta.java";
    IPath path = rootPath.append(name);
    IFile file = project.getFile(path);
    return file;
  }

  private IFile getMetaFile(IResource resource) {
    ICompilationUnit cu = getCompilationUnit(resource);
    if (cu == null) {
      return null;
    }
    return getMetaFile(cu);
  }

  public void deleteMetaFile(IResource resource) throws CoreException {
    IFile meta = getMetaFile(resource);
    if (meta != null && meta.exists()) {
      monitor.subTask("Metagen: deleting meta file of: " + resource.getName());
      meta.delete(true, monitor);
    }
  }

  public void generateMetaFile(IResource resource) throws CoreException {
    ICompilationUnit cu = getCompilationUnit(resource);
    if (cu == null) {
      return;
    }
    if (cu.getTypes().length == 0) {
      // compilation unit without a primary type, like package-info.java
      return;
    }

    monitor.subTask("Metagen: generating meta for: " + cu.getElementName());

    BeanUnit beanUnit = new BeanUnit(cu);
    if (beanUnit.canPossiblyGenerateMeta()) {
      ASTNode ast = parse(cu);
      beanUnit.discover(ast, this);
    }

    IFile metaFile = getMetaFile(cu);

    if (beanUnit.isEmpty()) {
      // no beans, cleanup in case there was an existing meta file

      if (metaFile.exists()) {
        metaFile.delete(true, monitor);
        cleanupEmptyPackages(metaFile);
      }
    } else {

      // we have something to generate, make sure the parent package exists

      ensurePackageExists(cu, metaFile);

      String source = beanUnit.generate(cu, metaFile);

      ByteArrayInputStream in = new ByteArrayInputStream(source.getBytes());

      if (metaFile.exists()) {
        metaFile.setContents(in, IResource.FORCE, monitor);
      } else {
        metaFile.create(in, true, monitor);
      }

      metaFile.setDerived(true, null);
    }
  }

  private void cleanupEmptyPackages(IFile metaFile) throws CoreException {
    IContainer container = metaFile.getParent();
    while (container.getType() == IResource.FOLDER && container.members().length == 0) {
      container.delete(true, monitor);
      container = container.getParent();
    }
  }

  private void ensurePackageExists(ICompilationUnit cu, IFile metaFile) throws CoreException {

    String[] segments = cu.getParent().getElementName().split("\\.");
    IFolder cursor = project.getFolder(rootPath);
    for (String segment : segments) {
      cursor = cursor.getFolder(segment);
      if (!cursor.exists()) {
        cursor.create(true, true, monitor);
        cursor.setDerived(true, monitor);
      }
    }
  }

  public void deleteAllMetaFiles() throws CoreException {
    IFolder resource = project.getFolder(rootPath);
    for (IResource member : resource.members()) {
      delete(member);
    }
  }

  private void delete(IResource resource) throws CoreException {
    if (resource.getType() == IResource.FOLDER) {
      IFolder folder = (IFolder) resource;
      for (IResource child : folder.members()) {
        delete(child);
      }
    }
    resource.delete(true, monitor);
  }

  private void addMarker(IResource file, String message, int lineNumber, int severity) throws CoreException {
    IMarker marker = file.createMarker(Builder.MARKER_TYPE);
    marker.setAttribute(IMarker.MESSAGE, message);
    marker.setAttribute(IMarker.SEVERITY, severity);
    if (lineNumber == -1) {
      lineNumber = 1;
    }
    marker.setAttribute(IMarker.LINE_NUMBER, lineNumber);
  }

  public void deleteMarkers(IResource file) {
    try {
      file.deleteMarkers(Builder.MARKER_TYPE, false, IResource.DEPTH_ZERO);
    } catch (CoreException ce) {
    }
  }

  public void deleteAllMarkers() throws CoreException {
    project.deleteMarkers(Builder.MARKER_TYPE, true, IResource.DEPTH_INFINITE);
  }

  @Override
  public void error(IResource resource, int line, String error) {
    try {
      addMarker(resource, error, line, IMarker.SEVERITY_ERROR);
    } catch (CoreException e) {
    }
  }
}
TOP

Related Classes of org.ftlines.metagen.eclipse.Build

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.