/*******************************************************************************
* Copyright (c) 2009, 2010 Fraunhofer IWU and others.
* 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:
* Fraunhofer IWU - initial API and implementation
*******************************************************************************/
package net.enilink.komma.generator.java.merge;
import java.io.File;
import java.io.FileInputStream;
import java.util.Map;
import org.eclipse.core.resources.IProject;
import org.eclipse.emf.codegen.merge.java.JControlModel;
import org.eclipse.emf.codegen.merge.java.JMerger;
import org.eclipse.emf.codegen.merge.java.facade.ast.ASTFacadeHelper;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.formatter.CodeFormatter;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.text.edits.TextEdit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Receives the java output of a generate action and the target location. Reads
* the current source from there and merges the generation output and the
* current content.
*
*/
public class SourceMerger {
private final Logger log = LoggerFactory.getLogger(SourceMerger.class);
private JControlModel jControlModel;
private CodeFormatter codeFormatter;
public String forType() {
return "java";
}
/**
* Does the merge operation and returns the new content if the content has
* really changed, otherwise null is returned.
*/
public String merge(File targetFile, String content) {
try {
final String newSource;
if (targetFile.exists()) {
log.debug("Current source exists, use JMerge");
final JControlModel jControlModel = getJControlModel();
final JMerger jMerger = new JMerger(jControlModel);
jMerger.setFixInterfaceBrace(jControlModel.getFacadeHelper()
.fixInterfaceBrace());
try {
jMerger.setSourceCompilationUnit(jMerger
.createCompilationUnitForContents(content));
} catch (Exception e) { // something wrong in the code itself
throw new Exception("Syntax error in generated source for "
+ targetFile.getName() + " :"
+ getExceptionMessage(e)
+ "\nSource>>>>>>>>>>>>>>>>>>>>>>>>>\n" + content,
e);
}
try {
jMerger.setTargetCompilationUnit(jMerger
.createCompilationUnitForInputStream(new FileInputStream(
targetFile)));
} catch (Exception e) { // something wrong in the code itself
throw new Exception("Syntax error in current source for "
+ targetFile.getName() + " :"
+ getExceptionMessage(e), e);
} catch (Throwable t) {
throw new Exception("Syntax error in current source for "
+ targetFile.getName() + " :"
+ getExceptionMessage(t), t);
}
final String oldSource = jMerger
.getTargetCompilationUnitContents();
jMerger.merge();
String mergedContent = jMerger
.getTargetCompilationUnitContents();
System.err.println("old: \n" + oldSource);
System.err.println("new: \n" + mergedContent);
TextEdit edit = getCodeFormatter().format(
CodeFormatter.K_COMPILATION_UNIT, mergedContent, 0,
mergedContent.length(), 0, "\n");
newSource = edit.toString();
// TODO: check if target is read only!
jControlModel.getFacadeHelper().reset();
if (newSource.equals(oldSource)) {
return null; // nothing changed
}
return newSource;
} else {
log.debug("Current source does not exist, create one");
TextEdit edit = getCodeFormatter().format(
CodeFormatter.K_COMPILATION_UNIT, content, 0,
content.length(), 0, "\n");
return edit.toString();
}
} catch (Exception e) {
// catch them all
throw new RuntimeException(
"Exception while merging and saving source file "
+ targetFile.getName(), e);
}
}
/** Returns the local path for the type of content */
public String getLocalPath(IProject project) {
return "/src";
}
/** Determine the compile errors */
private String getExceptionMessage(Throwable t) {
// if (t.getCause() instanceof DiagnosticException) {
// final DiagnosticException d = (DiagnosticException) t.getCause();
// final StringBuilder message = new StringBuilder(d.getDiagnostic()
// .getMessage());
// for (Diagnostic cd : d.getDiagnostic().getChildren()) {
// message.append("\n\t").append(cd.getMessage());
// }
// return message.toString();
// } else {
return t.getMessage();
// }
}
/** @return the jMerge control model */
private JControlModel getJControlModel() {
if (jControlModel == null) {
jControlModel = new JControlModel();
jControlModel.initialize(new ASTFacadeHelper(), this.getClass()
.getResource("merge.xml").toExternalForm());
}
return jControlModel;
}
private CodeFormatter getCodeFormatter() {
if (codeFormatter == null) {
@SuppressWarnings("unchecked")
final Map<Object, Object> options = DefaultCodeFormatterConstants
.getEclipseDefaultSettings();
options.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_5);
options.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM,
JavaCore.VERSION_1_5);
options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_5);
codeFormatter = ToolFactory.createCodeFormatter(options);
}
return codeFormatter;
}
}