package com.prezi.grub.gradle;
import com.google.common.base.Charsets;
import com.google.common.collect.Maps;
import com.google.common.io.Files;
import com.prezi.grub.gradle.internal.GlobsUtils;
import groovy.text.GStringTemplateEngine;
import org.apache.commons.io.FileUtils;
import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.InputDirectory;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.TaskAction;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.Collection;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ProcessFiles extends DefaultTask {
public static final String VERBATIM_FILE = ".grubverbatim";
private File templateDirectory;
private File targetDirectory;
private File verbatimFile;
@InputDirectory
public File getTemplateDirectory() {
return templateDirectory;
}
public void setTemplateDirectory(Object templateDirectory) {
this.templateDirectory = getProject().file(templateDirectory);
}
@SuppressWarnings("UnusedDeclaration")
public void templateDirectory(Object templateDirectory) {
setTemplateDirectory(templateDirectory);
}
@SuppressWarnings("UnusedDeclaration")
public void template(Object templateDirectory) {
setTemplateDirectory(templateDirectory);
}
@OutputDirectory
public File getTargetDirectory() {
return targetDirectory;
}
public void setTargetDirectory(Object targetDirectory) {
this.targetDirectory = getProject().file(targetDirectory);
}
@SuppressWarnings("UnusedDeclaration")
public void targetDirectory(Object targetDirectory) {
setTargetDirectory(targetDirectory);
}
@SuppressWarnings("UnusedDeclaration")
public void target(Object targetDirectory) {
setTargetDirectory(targetDirectory);
}
@InputFile
@Optional
public File getVerbatimFile() {
File result = verbatimFile;
if (result == null) {
result = new File(getTemplateDirectory(), VERBATIM_FILE);
}
if (!result.exists()) {
result = null;
}
return result;
}
public void setVerbatimFile(Object verbatimFile) {
this.verbatimFile = getProject().file(verbatimFile);
}
@SuppressWarnings("UnusedDeclaration")
public void verbatimFile(Object verbatimFile) {
setVerbatimFile(verbatimFile);
}
@SuppressWarnings("UnusedDeclaration")
public void verbatim(Object verbatimFile) {
setVerbatimFile(verbatimFile);
}
private final GStringTemplateEngine engine = new GStringTemplateEngine();
@TaskAction
public void copy() throws Exception {
if (getTemplateDirectory().exists()) {
copyChildren(getTemplateDirectory(), getTargetDirectory());
}
}
private void copyChildren(File templateDir, File targetDir) throws Exception {
Collection<Pattern> verbatimPatterns = GlobsUtils.readGlobs(getVerbatimFile());
getLogger().info("Processing {} to {}", templateDir, targetDir);
String[] names = templateDir.list();
if (names == null) {
throw new IOException("Could not read files from " + templateDir);
}
String templateDirPath = templateDir.getAbsolutePath().replaceAll("\\\\", "/") + "/";
for (String childName : names) {
if (childName.equals(".") || childName.equals("..") || childName.equals(VERBATIM_FILE)) {
continue;
}
File templateChild = new File(templateDir, childName);
String targetName = engine.createTemplate(childName).make(createBindings()).toString();
File targetChild = new File(targetDir, targetName);
if (templateChild.isDirectory()) {
FileUtils.forceMkdir(targetChild);
copyChildren(templateChild, targetChild);
} else if (templateChild.isFile()) {
boolean verbatim = isVerbatim(verbatimPatterns, templateDirPath + childName);
if (verbatim) {
Files.copy(templateChild, targetChild);
} else {
Reader reader = Files.asCharSource(templateChild, Charsets.UTF_8).openStream();
try {
Writer writer = Files.asCharSink(targetChild, Charsets.UTF_8).openStream();
try {
engine.createTemplate(reader).make(createBindings()).writeTo(writer);
} finally {
writer.close();
}
} finally {
reader.close();
}
}
}
}
}
private static boolean isVerbatim(Collection<Pattern> verbatimPatterns, String childPath) {
for (Pattern verbatimPattern : verbatimPatterns) {
Matcher verbatimMatcher = verbatimPattern.matcher(childPath);
if (verbatimMatcher.matches()) {
return true;
}
}
return false;
}
private Map<String, Object> createBindings() {
Map<String, Object> binding = Maps.newHashMap();
binding.put("project", getProject());
for (Map.Entry<String, ?> entry : getProject().getProperties().entrySet()) {
binding.put(entry.getKey(), entry.getValue());
}
return binding;
}
}