/*******************************************************************************
* Copyright (c) 2006-2012
* Software Technology Group, Dresden University of Technology
* DevBoost GmbH, Berlin, Amtsgericht Charlottenburg, HRB 140026
*
* 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:
* Software Technology Group - TU Dresden, Germany;
* DevBoost GmbH - Berlin, Germany
* - initial API and implementation
******************************************************************************/
package de.devboost.emfcustomize.builder;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
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.resources.IResourceVisitor;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.codegen.ecore.genmodel.GenClass;
import org.eclipse.emf.codegen.ecore.genmodel.GenModel;
import org.eclipse.emf.codegen.ecore.genmodel.GenPackage;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.plugin.EcorePlugin;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.emftext.language.java.JavaClasspath;
import org.emftext.language.java.resource.java.mopp.JavaResource;
import de.devboost.emfcustomize.EcoreModelRefactorer;
import de.devboost.emfcustomize.GeneratedFactoryRefactorer;
import de.devboost.emfcustomize.ResourceSaver;
public class EMFCustomizeBuilder {
public boolean isBuildingNeeded(URI uri) {
if (isCustomCodeFile(uri)) {
//react on changes in custom code
return true;
}
if (isFactoryCodeFile(uri)) {
//react on re-generated factory
return true;
}
return false;
}
private boolean isCustomCodeFile(URI uri) {
return isJavaFileWithSuffix(uri, GeneratedFactoryRefactorer.CUSTOM_CLASS_SUFFIX);
}
private boolean isFactoryCodeFile(URI uri) {
return isJavaFileWithSuffix(uri, GeneratedFactoryRefactorer.FACTORY_CLASS_SUFFIX);
}
private boolean isJavaFileWithSuffix(URI uri, String suffix) {
boolean isJavaFile = "java".equals(uri.fileExtension());
String lastSegment = uri.trimFileExtension().lastSegment();
boolean hasSuffix = lastSegment.endsWith(suffix);
return isJavaFile && hasSuffix;
}
public List<Resource> build(Resource resource, IFile iFile) {
ResourceSet resourceSet = resource.getResourceSet();
String possibleGenModelName = resource.getURI().trimSegments(2).lastSegment();
if (possibleGenModelName == null) {
possibleGenModelName = "";
}
GenModel genModel = findGenModel(iFile.getProject(), possibleGenModelName, resourceSet);
resourceSet.getURIConverter().getURIMap().putAll(
EcorePlugin.computePlatformURIMap());
if (genModel == null) {
return Collections.emptyList();
}
if (isCustomCodeFile(resource.getURI())) {
// new strategy: adjust factory only when a custom class file is built for having the chance to determine which GenClass is needed
String className = iFile.getFullPath().removeFileExtension().lastSegment();
int index = className.indexOf(GeneratedFactoryRefactorer.CUSTOM_CLASS_SUFFIX);
if(index != -1){
className = className.substring(0, index);
}
List<GenClass> genClasses = getGenClassByName(genModel, className);
if(genClasses.size() > 1){
return Collections.emptyList();
}
GenClass genClass = genClasses.get(0);
//propagate EOperations
GenPackage genPackage = genClass.getGenPackage();
new EcoreModelRefactorer().propagateEOperations((JavaResource) resource, genClass);
genModel.reconcile();
try {
Resource ecoreModelResource = genPackage.getEcorePackage().eResource();
Resource genModelResource = genModel.eResource();
new ResourceSaver().saveResource(genModelResource);
new ResourceSaver().saveResource(ecoreModelResource);
} catch (IOException e1) {
e1.printStackTrace();
}
// adjust factory
adjustFactory(iFile, resourceSet);
return new GeneratedFactoryRefactorer().refactorFactory(genModel, genClass, URI.createPlatformResourceURI("/", true), false);
// return Collections.emptyList();
}
// else {
// return new GeneratedFactoryRefactorer().refactorFactory(genModel, URI.createPlatformResourceURI("/", true), false);
// }
return Collections.emptyList();
}
private List<GenClass> getGenClassByName(GenModel genModel, String name){
List<GenClass> genClassCandidates = new ArrayList<GenClass>();
List<GenPackage> genPackages = genModel.getAllGenPackagesWithClassifiers();
for (GenPackage genPackage : genPackages) {
EList<GenClass> genClasses = genPackage.getGenClasses();
for (GenClass genClass : genClasses) {
if(genClass.getName().equals(name)){
genClassCandidates.add(genClass);
}
}
}
return genClassCandidates;
}
private void adjustFactory(IFile iFile, ResourceSet resourceSet) {
//adjust factory for generation gap pattern
IJavaProject javaProject = JavaCore.create(iFile.getProject());
try {
for (IClasspathEntry cpEntry : javaProject.getRawClasspath()) {
if (cpEntry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
//to register newly generated code;
updateClaspath(new File(iFile.getWorkspace().getRoot().getLocation().toString() +
cpEntry.getPath().toString()), "", resourceSet);
}
}
} catch (JavaModelException e) {
e.printStackTrace();
}
}
private GenModel findGenModel(IProject project, final String name, ResourceSet rs) {
final List<IFile> genModelResources = new ArrayList<IFile>();
try {
project.accept(new IResourceVisitor() {
@Override
public boolean visit(IResource resource) throws CoreException {
if (resource instanceof IFile && resource.getName().toLowerCase().equals(
name.toLowerCase() + ".genmodel")) {
genModelResources.add(0, (IFile) resource);
} else if (resource instanceof IFile && resource.getName().endsWith(".genmodel")) {
genModelResources.add((IFile) resource);
}
return true;
}
});
} catch (CoreException e) {
e.printStackTrace();
}
if (genModelResources.isEmpty()) {
return null;
}
IFile genModelFile =genModelResources.get(0);
URI genModelURI = URI.createPlatformResourceURI(genModelFile.getFullPath().toString(), true);
Resource genModelResource = rs.getResource(genModelURI, true);
return (GenModel) genModelResource.getContents().get(0);
}
private void updateClaspath(File parent, String fullPackageName, ResourceSet resourceSet) {
if (!parent.exists()) {
return;
}
JavaClasspath cp = JavaClasspath.get(resourceSet);
for (File child : parent.listFiles()) {
if (!child.getName().startsWith(".")) {
if (child.isDirectory()) {
updateClaspath(child, fullPackageName + child.getName() + ".", resourceSet);
} else if (child.getName().endsWith(".java")) {
String className = child.getName();
className = className.substring(0, className.lastIndexOf("."));
URI uri = URI.createFileURI(child.getAbsolutePath());
cp.registerClassifier(fullPackageName, className, uri);
}
}
}
}
public IStatus handleDeletion(URI uri) {
return Status.OK_STATUS;
}
}