blob: 02f26e11eee32a64f74889cf96d84b177cb33ea7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008 The University of York.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* Contributors:
* Louis Rose - initial API and implementation
******************************************************************************/
package org.eclipse.epsilon.egl;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import org.eclipse.epsilon.common.util.UriUtil;
import org.eclipse.epsilon.egl.exceptions.EglRuntimeException;
import org.eclipse.epsilon.egl.execute.context.IEglContext;
import org.eclipse.epsilon.egl.formatter.NullFormatter;
import org.eclipse.epsilon.egl.incremental.IncrementalitySettings;
import org.eclipse.epsilon.egl.merge.output.LocatedRegion;
import org.eclipse.epsilon.egl.output.Writer;
import org.eclipse.epsilon.egl.spec.EglTemplateSpecification;
import org.eclipse.epsilon.egl.spec.EglTemplateSpecificationFactory;
import org.eclipse.epsilon.egl.status.ProtectedRegionWarning;
import org.eclipse.epsilon.egl.traceability.OutputFile;
import org.eclipse.epsilon.egl.util.FileUtil;
public class EglFileGeneratingTemplate extends EglPersistentTemplate {
private File target;
private String targetName;
private OutputFile currentOutputFile;
private String existingContents;
private String newContents;
private String positiveMessage;
private OutputMode outputMode;
private static enum OutputMode {
WRITE, MERGE, APPEND;
}
// For tests
protected EglFileGeneratingTemplate(URI path, IEglContext context, URI outputRoot) throws Exception {
this(new EglTemplateSpecificationFactory(new NullFormatter(), new IncrementalitySettings()).fromResource(path.toString(), path), context, outputRoot, outputRoot.getPath());
}
public EglFileGeneratingTemplate(EglTemplateSpecification spec, IEglContext context, URI outputRoot, String outputRootPath) throws Exception {
super(spec, context, outputRoot, outputRootPath);
}
public File append(String path) throws EglRuntimeException {
try {
final File target = resolveFile(path);
if (!isProcessed()) {
process();
}
this.target = target;
this.targetName = name(path);
this.existingContents = FileUtil.readIfExists(target);
this.outputMode = OutputMode.APPEND;
prepareNewContents();
writeNewContentsIfDifferentFromExistingContents();
return target;
} catch (URISyntaxException e) {
throw new EglRuntimeException("Could not resolve path: " + target, e, module);
} catch (IOException ex) {
throw new EglRuntimeException("Could not generate to: " + target, ex, module);
}
}
@Override
protected void doGenerate(File target, String targetName, boolean overwrite, boolean merge) throws EglRuntimeException {
try {
this.target = target;
this.targetName = targetName;
this.existingContents = FileUtil.readIfExists(target);
this.outputMode = (merge && target.exists()) ? OutputMode.MERGE : OutputMode.WRITE;
prepareNewContents();
writeNewContentsIfDifferentFromExistingContents();
} catch (URISyntaxException e) {
throw new EglRuntimeException("Could not resolve path: " + target, e, module);
} catch (IOException ex) {
throw new EglRuntimeException("Could not generate to: " + target, ex, module);
}
}
private void prepareNewContents() throws EglRuntimeException {
switch (outputMode) {
case APPEND:
if (existingContents != null) {
newContents = existingContents + FileUtil.NEWLINE + getContents();
} else {
newContents = getContents();
}
positiveMessage = "Successfully appended to ";
break;
case MERGE:
newContents = merge(existingContents);
positiveMessage = "Protected regions preserved in ";
break;
case WRITE:
newContents = getContents();
positiveMessage = "Successfully wrote to ";
break;
default:
throw new EglRuntimeException("Unsupported output mode " + outputMode, new IllegalStateException());
}
}
private void writeNewContentsIfDifferentFromExistingContents() throws URISyntaxException, IOException {
if (isOverwriteUnchangedFiles() || !newContents.equals(existingContents)) {
write();
addMessage(positiveMessage + targetName);
} else {
addMessage("Content unchanged for " + targetName);
}
}
private boolean isOverwriteUnchangedFiles() {
return getIncrementalitySettings().isOverwriteUnchangedFiles();
}
private void write() throws IOException, URISyntaxException {
new Writer(target, newContents).write();
currentOutputFile = template.addOutputFile(targetName, UriUtil.fileToUri(target));
if (outputMode == OutputMode.MERGE) {
for (LocatedRegion pr : module.getContext().getPartitioner().partition(newContents).getLocatedRegions()) {
currentOutputFile.addProtectedRegion(pr.getId(), pr.isEnabled(), pr.getOffset());
}
}
}
@Override
protected void addProtectedRegionWarning(ProtectedRegionWarning warning) {
super.addProtectedRegionWarning(new ProtectedRegionWarning(warning.getId(), target.getAbsolutePath()));
}
}