Uploading SourceCode and Documentation
This commit is contained in:
parent
ce515f07e4
commit
a189a3cea4
43
README.md
43
README.md
|
@ -1,2 +1,45 @@
|
||||||
# Simple-Code-Generator
|
# Simple-Code-Generator
|
||||||
|
|
||||||
|
This Tool is a very Simple Code Generator that can read a template file and segment it based on a Set of variables that can be defined.
|
||||||
|
Separate to that this tool can replace text via simple Regular Expression mapping.
|
||||||
|
It has a cache that keeps track of the input (if it was changed), and only cares that the file format is Text based.
|
||||||
|
|
||||||
|
It is as bare bones as it can get but that also makes it flexible.
|
||||||
|
|
||||||
|
|
||||||
|
# How to create a Template Processor
|
||||||
|
|
||||||
|
Create a class that extends TemplateProcessor.
|
||||||
|
And run the process method
|
||||||
|
SourceFolder: Is the folder that is traversed through and Files are given back.
|
||||||
|
OutputFolder: Is the folder where the Processed files get put into. If the "relativePackages" are set to true then the source folder structure is transferred.
|
||||||
|
DataFolder: Is the folder where the input cache is stored. It uses a MD5 generator to compare inputs. Right now only FileNames without extensions are stored in there. So no Duplicated FileName support for now.
|
||||||
|
|
||||||
|
##### Methods:
|
||||||
|
init: Is called when the Processes was started for the first time.
|
||||||
|
isFileValid: The Method that checks if a File can be used for a template.
|
||||||
|
relativePackages: If the Folder Structure from the SourceFolder should be transferred to the OutputFolder.
|
||||||
|
createProcesses: The Main Function that provides the FileName (without extension) and a consumer of how the file should be processed.
|
||||||
|
A TemplateProcess is a Collection of Variables that is used for File Segmentation and a List of UnaryOperators that allow to edit the build code.
|
||||||
|
A Simple sum up: Template Process is Tuple<Set<String>, List<UnaryOperator>> that also contains the new FileName.
|
||||||
|
|
||||||
|
```java
|
||||||
|
package test.example;
|
||||||
|
|
||||||
|
public class ExampleClass
|
||||||
|
{
|
||||||
|
#if METHOD_ONE
|
||||||
|
public void methodOne() {}
|
||||||
|
#else if METHOD_TWO && !SKIP
|
||||||
|
public void methodTwo() {}
|
||||||
|
#else
|
||||||
|
public void methodThree() {}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If the Variable "METHOD_ONE" is present only the code in the if is parsed into the template process.
|
||||||
|
If the Variable "METHOD_TWO" is present and the "SKIP" Variable is missing then the code in the else if block is parsed into the template process
|
||||||
|
Otherwise the else block is included.
|
||||||
|
Whenever a if is started, it has to end with a #endif, Even if the last condition is a else if or a else.
|
||||||
|
Recursion is supported and necessary
|
|
@ -0,0 +1,83 @@
|
||||||
|
package speiger.src.builder.base;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.StringJoiner;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import speiger.src.builder.conditions.ICondition;
|
||||||
|
|
||||||
|
public class ConditionedSegment
|
||||||
|
{
|
||||||
|
static final Pattern AND = Pattern.compile("(&&)");
|
||||||
|
static final Pattern OR = Pattern.compile("(||)");
|
||||||
|
|
||||||
|
int index;
|
||||||
|
List<Segment> segments = new ArrayList<>();
|
||||||
|
|
||||||
|
public ConditionedSegment(int index)
|
||||||
|
{
|
||||||
|
this.index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSegment(Segment segment)
|
||||||
|
{
|
||||||
|
segments.add(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int build(Set<String> parsePool, StringBuilder builder, int baseIndex)
|
||||||
|
{
|
||||||
|
baseIndex += index;
|
||||||
|
int length = builder.length();
|
||||||
|
for(int i = 0,m=segments.size();i<m;i++)
|
||||||
|
{
|
||||||
|
if(segments.get(i).build(parsePool, builder, baseIndex)) break;
|
||||||
|
}
|
||||||
|
return builder.length() - length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int parse(String currentLine, List<String> lines, int currentIndex, int startIndex, List<ConditionedSegment> segments) throws IllegalStateException
|
||||||
|
{
|
||||||
|
ConditionedSegment segment = new ConditionedSegment(startIndex);
|
||||||
|
ICondition condition = ICondition.parse(currentLine);
|
||||||
|
List<ConditionedSegment> childSegments = new ArrayList<>();
|
||||||
|
StringJoiner segmentText = new StringJoiner("\n", "\n", "");
|
||||||
|
for(int i = currentIndex+1;i<lines.size();i++)
|
||||||
|
{
|
||||||
|
String s = lines.get(i);
|
||||||
|
String trimmed = s.trim();
|
||||||
|
if(trimmed.startsWith("#"))
|
||||||
|
{
|
||||||
|
if(trimmed.startsWith("#else if"))
|
||||||
|
{
|
||||||
|
segment.addSegment(new Segment(segmentText.toString(), condition, childSegments));
|
||||||
|
condition = ICondition.parse(trimmed.substring(8).trim());
|
||||||
|
childSegments = new ArrayList<>();
|
||||||
|
segmentText = new StringJoiner("\n", "\n", "");
|
||||||
|
}
|
||||||
|
else if(trimmed.startsWith("#else"))
|
||||||
|
{
|
||||||
|
segment.addSegment(new Segment(segmentText.toString(), condition, childSegments));
|
||||||
|
condition = ICondition.ALWAYS_TRUE;
|
||||||
|
childSegments = new ArrayList<>();
|
||||||
|
segmentText = new StringJoiner("\n", "\n", "");
|
||||||
|
}
|
||||||
|
else if(trimmed.startsWith("#endif"))
|
||||||
|
{
|
||||||
|
segment.addSegment(new Segment(segmentText.toString(), condition, childSegments));
|
||||||
|
segments.add(segment);
|
||||||
|
return i - currentIndex;
|
||||||
|
}
|
||||||
|
else if(trimmed.startsWith("#if"))
|
||||||
|
{
|
||||||
|
i += parse(trimmed.substring(3).trim(), lines, i, segmentText.length(), childSegments);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
segmentText.add(s);
|
||||||
|
}
|
||||||
|
throw new IllegalStateException("Unclosed #If found!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package speiger.src.builder.base;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import speiger.src.builder.conditions.ICondition;
|
||||||
|
|
||||||
|
public class Segment
|
||||||
|
{
|
||||||
|
ICondition condition;
|
||||||
|
String text;
|
||||||
|
List<ConditionedSegment> segments = new ArrayList<>();
|
||||||
|
|
||||||
|
public Segment(String text, ICondition condition, List<ConditionedSegment> segments)
|
||||||
|
{
|
||||||
|
this.text = text;
|
||||||
|
this.condition = condition;
|
||||||
|
this.segments = segments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean build(Set<String> parsePool, StringBuilder builder, int index)
|
||||||
|
{
|
||||||
|
if(condition.isValid(parsePool))
|
||||||
|
{
|
||||||
|
builder.insert(index, text);
|
||||||
|
for(int i = 0,offset=0,m=segments.size();i<m;i++)
|
||||||
|
{
|
||||||
|
offset += segments.get(i).build(parsePool, builder, index+offset);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
package speiger.src.builder.base;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.StringJoiner;
|
||||||
|
import java.util.function.UnaryOperator;
|
||||||
|
|
||||||
|
import speiger.src.builder.misc.FileUtils;
|
||||||
|
|
||||||
|
public class Template
|
||||||
|
{
|
||||||
|
String fileName;
|
||||||
|
String textFile;
|
||||||
|
List<ConditionedSegment> segments;
|
||||||
|
|
||||||
|
public Template(String fileName, String textFile, List<ConditionedSegment> segments)
|
||||||
|
{
|
||||||
|
this.fileName = fileName;
|
||||||
|
this.textFile = textFile;
|
||||||
|
this.segments = segments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileName()
|
||||||
|
{
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String build(Set<String> parsePool, List<UnaryOperator<String>> mappers)
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder(textFile);
|
||||||
|
for(int i = 0,offset=0,m=segments.size();i<m;i++)
|
||||||
|
{
|
||||||
|
offset += segments.get(i).build(parsePool, builder, offset);
|
||||||
|
}
|
||||||
|
String result = builder.toString();
|
||||||
|
for(int i = 0,m=mappers.size();i<m;i++)
|
||||||
|
{
|
||||||
|
result = mappers.get(i).apply(result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Template parse(Path file) throws IOException
|
||||||
|
{
|
||||||
|
List<ConditionedSegment> segments = new ArrayList<ConditionedSegment>();
|
||||||
|
StringJoiner joiner = new StringJoiner("\n");
|
||||||
|
List<String> lines = Files.readAllLines(file);
|
||||||
|
for(int i = 0;i<lines.size();i++)
|
||||||
|
{
|
||||||
|
String s = lines.get(i);
|
||||||
|
String trimmed = s.trim();
|
||||||
|
if(trimmed.startsWith("#"))
|
||||||
|
{
|
||||||
|
if(trimmed.startsWith("#if"))
|
||||||
|
{
|
||||||
|
i += ConditionedSegment.parse(s.trim().substring(3).trim(), lines, i, joiner.length(), segments);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if(trimmed.startsWith("#symlink"))
|
||||||
|
{
|
||||||
|
return Template.parse(file.getParent().resolve(trimmed.substring(8).trim()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
joiner.add(s);
|
||||||
|
}
|
||||||
|
return new Template(FileUtils.getFileName(file.getFileName()), joiner.toString(), segments);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package speiger.src.builder.conditions;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class AndCondition implements ICondition
|
||||||
|
{
|
||||||
|
List<ICondition> conditions = new ArrayList<>();
|
||||||
|
|
||||||
|
public AndCondition(ICondition base)
|
||||||
|
{
|
||||||
|
conditions.add(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCondition(ICondition e)
|
||||||
|
{
|
||||||
|
conditions.add(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid(Set<String> parsePool)
|
||||||
|
{
|
||||||
|
for(int i = 0,m=conditions.size();i<m;i++)
|
||||||
|
{
|
||||||
|
if(!conditions.get(i).isValid(parsePool))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package speiger.src.builder.conditions;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class FlagCondition implements ICondition
|
||||||
|
{
|
||||||
|
String flag;
|
||||||
|
boolean inverted;
|
||||||
|
|
||||||
|
public FlagCondition(String flag, boolean inverted)
|
||||||
|
{
|
||||||
|
this.flag = flag;
|
||||||
|
this.inverted = inverted;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid(Set<String> parsePool)
|
||||||
|
{
|
||||||
|
return parsePool.contains(flag) != inverted;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package speiger.src.builder.conditions;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public interface ICondition
|
||||||
|
{
|
||||||
|
public static final ICondition ALWAYS_TRUE = T -> true;
|
||||||
|
|
||||||
|
public boolean isValid(Set<String> parsePool);
|
||||||
|
|
||||||
|
public static ICondition parse(String condition)
|
||||||
|
{
|
||||||
|
String[] elements = condition.split(" ");
|
||||||
|
List<ICondition> conditions = new ArrayList<ICondition>();
|
||||||
|
for(int i = 0;i<elements.length;i++)
|
||||||
|
{
|
||||||
|
if(elements[i].equalsIgnoreCase("&&"))
|
||||||
|
{
|
||||||
|
if(i==elements.length-1)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(condition.isEmpty())
|
||||||
|
{
|
||||||
|
conditions.add(new AndCondition(parseSimpleCondition(elements[++i])));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ICondition con = conditions.get(conditions.size() - 1);
|
||||||
|
if(con instanceof AndCondition)
|
||||||
|
{
|
||||||
|
((AndCondition)con).addCondition(parseSimpleCondition(elements[++i]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AndCondition replacement = new AndCondition(con);
|
||||||
|
replacement.addCondition(parseSimpleCondition(elements[++i]));
|
||||||
|
conditions.set(conditions.size()-1, replacement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(!elements[i].equalsIgnoreCase("||"))
|
||||||
|
{
|
||||||
|
conditions.add(parseSimpleCondition(elements[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch(conditions.size())
|
||||||
|
{
|
||||||
|
case 0: return ALWAYS_TRUE;
|
||||||
|
case 1: return conditions.get(0);
|
||||||
|
default: return new OrCondition(conditions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ICondition parseSimpleCondition(String s)
|
||||||
|
{
|
||||||
|
return s.startsWith("!") ? new FlagCondition(s.substring(1), true) : new FlagCondition(s, false);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package speiger.src.builder.conditions;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class OrCondition implements ICondition
|
||||||
|
{
|
||||||
|
List<ICondition> conditions;
|
||||||
|
|
||||||
|
public OrCondition(List<ICondition> conditions)
|
||||||
|
{
|
||||||
|
this.conditions = conditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid(Set<String> parsePool)
|
||||||
|
{
|
||||||
|
for(int i = 0,m=conditions.size();i<m;i++)
|
||||||
|
{
|
||||||
|
if(conditions.get(i).isValid(parsePool))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
package speiger.src.builder.mappers;
|
||||||
|
|
||||||
|
import java.util.function.UnaryOperator;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import speiger.src.builder.misc.RegexUtil;
|
||||||
|
|
||||||
|
public class ArgumentMapper implements UnaryOperator<String>
|
||||||
|
{
|
||||||
|
Pattern pattern;
|
||||||
|
String replacement;
|
||||||
|
String argumentBreaker;
|
||||||
|
String braces = "()";
|
||||||
|
boolean removeBraces;
|
||||||
|
|
||||||
|
public ArgumentMapper(String pattern, String replacement, String argumentBreaker)
|
||||||
|
{
|
||||||
|
this.pattern = Pattern.compile(pattern);
|
||||||
|
this.replacement = replacement;
|
||||||
|
this.argumentBreaker = argumentBreaker;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArgumentMapper setBraceType(String s)
|
||||||
|
{
|
||||||
|
if(s.length() != 2) throw new IllegalStateException("Start and End char only");
|
||||||
|
braces = s;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArgumentMapper removeBraces()
|
||||||
|
{
|
||||||
|
removeBraces = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apply(String t)
|
||||||
|
{
|
||||||
|
Matcher matcher = pattern.matcher(t);
|
||||||
|
if(matcher.find())
|
||||||
|
{
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
String text = RegexUtil.searchUntil(t, matcher.end()-1, braces.charAt(0), braces.charAt(1));
|
||||||
|
if(!text.isEmpty())
|
||||||
|
{
|
||||||
|
RegexUtil.skip(matcher.appendReplacement(buffer, ""), text.length());
|
||||||
|
buffer.append(String.format(replacement, (Object[])getString(text).split(argumentBreaker)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(matcher.find());
|
||||||
|
matcher.appendTail(buffer);
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getString(String s)
|
||||||
|
{
|
||||||
|
return removeBraces ? s.substring(1, s.length() - 1) : s;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package speiger.src.builder.mappers;
|
||||||
|
|
||||||
|
import java.util.function.UnaryOperator;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import speiger.src.builder.misc.RegexUtil;
|
||||||
|
|
||||||
|
public class InjectMapper implements UnaryOperator<String>
|
||||||
|
{
|
||||||
|
Pattern pattern;
|
||||||
|
String replacement;
|
||||||
|
String braces = "()";
|
||||||
|
boolean removeBraces;
|
||||||
|
|
||||||
|
public InjectMapper(String pattern, String replacement)
|
||||||
|
{
|
||||||
|
this.pattern = Pattern.compile(pattern);
|
||||||
|
this.replacement = replacement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InjectMapper setBraceType(String s)
|
||||||
|
{
|
||||||
|
if(s.length() != 2) throw new IllegalStateException("Start and End char only");
|
||||||
|
braces = s;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InjectMapper removeBraces()
|
||||||
|
{
|
||||||
|
removeBraces = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apply(String t)
|
||||||
|
{
|
||||||
|
Matcher matcher = pattern.matcher(t);
|
||||||
|
if(matcher.find())
|
||||||
|
{
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
String text = RegexUtil.searchUntil(t, matcher.end()-1, braces.charAt(0), braces.charAt(1));
|
||||||
|
if(!text.isEmpty())
|
||||||
|
{
|
||||||
|
RegexUtil.skip(matcher.appendReplacement(buffer, ""), text.length());
|
||||||
|
buffer.append(String.format(replacement, getString(text)));
|
||||||
|
}
|
||||||
|
} while (matcher.find());
|
||||||
|
matcher.appendTail(buffer);
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getString(String s)
|
||||||
|
{
|
||||||
|
return removeBraces ? s.substring(1, s.length() - 1) : s;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package speiger.src.builder.mappers;
|
||||||
|
|
||||||
|
import java.util.function.UnaryOperator;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import speiger.src.builder.misc.RegexUtil;
|
||||||
|
|
||||||
|
public class LineMapper implements UnaryOperator<String>
|
||||||
|
{
|
||||||
|
Pattern pattern;
|
||||||
|
|
||||||
|
public LineMapper(String pattern)
|
||||||
|
{
|
||||||
|
this.pattern = Pattern.compile(pattern, Pattern.LITERAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apply(String t)
|
||||||
|
{
|
||||||
|
Matcher matcher = pattern.matcher(t);
|
||||||
|
if(matcher.find())
|
||||||
|
{
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int start = matcher.end() - 1;
|
||||||
|
int[] result = RegexUtil.findFullLine(t, start);
|
||||||
|
if(result != null)
|
||||||
|
{
|
||||||
|
matcher.appendReplacement(buffer, pattern.pattern());
|
||||||
|
buffer.setLength(buffer.length() - (start - result[0]));
|
||||||
|
RegexUtil.skip(matcher, result[1] - start);
|
||||||
|
}
|
||||||
|
} while (matcher.find());
|
||||||
|
matcher.appendTail(buffer);
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package speiger.src.builder.mappers;
|
||||||
|
|
||||||
|
import java.util.function.UnaryOperator;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class SimpleMapper implements UnaryOperator<String>
|
||||||
|
{
|
||||||
|
Pattern pattern;
|
||||||
|
String replacement;
|
||||||
|
|
||||||
|
public SimpleMapper(String pattern, String replacement)
|
||||||
|
{
|
||||||
|
this.pattern = Pattern.compile(pattern, Pattern.LITERAL);
|
||||||
|
this.replacement = replacement;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apply(String t)
|
||||||
|
{
|
||||||
|
return pattern.matcher(t).replaceAll(replacement);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
package speiger.src.builder.misc;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
public class FileUtils
|
||||||
|
{
|
||||||
|
public static boolean isValid(Path path, Map<String, String> existing)
|
||||||
|
{
|
||||||
|
String s = existing.get(getFileName(path));
|
||||||
|
return s == null || !s.equals(FileUtils.getMD5String(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<String, String> loadMappings(Path dataFolder) throws IOException
|
||||||
|
{
|
||||||
|
Map<String, String> result = new LinkedHashMap<>();
|
||||||
|
dataFolder = dataFolder.resolve("cache.bin");
|
||||||
|
if(Files.exists(dataFolder))
|
||||||
|
{
|
||||||
|
for(String s : Files.readAllLines(dataFolder))
|
||||||
|
{
|
||||||
|
String[] array = s.split("=");
|
||||||
|
if(array.length == 2)
|
||||||
|
{
|
||||||
|
result.put(array[0], array[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void saveMappings(Map<String, String> mappings, Path dataFolder)
|
||||||
|
{
|
||||||
|
try(BufferedWriter writer = Files.newBufferedWriter(dataFolder.resolve("cache.bin")))
|
||||||
|
{
|
||||||
|
for(Entry<String, String> entry : mappings.entrySet())
|
||||||
|
{
|
||||||
|
writer.write(entry.getKey()+"="+entry.getValue());
|
||||||
|
writer.newLine();
|
||||||
|
}
|
||||||
|
writer.flush();
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String getFileName(Path path)
|
||||||
|
{
|
||||||
|
String name = path.getFileName().toString();
|
||||||
|
int index = name.indexOf(".");
|
||||||
|
return index == -1 ? name : name.substring(0, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getMD5String(Path path)
|
||||||
|
{
|
||||||
|
try(InputStream stream = Files.newInputStream(path))
|
||||||
|
{
|
||||||
|
MessageDigest digest = MessageDigest.getInstance("MD5");
|
||||||
|
byte[] byteArray = new byte[2048];
|
||||||
|
int bytesCount = 0;
|
||||||
|
while((bytesCount = stream.read(byteArray)) != -1)
|
||||||
|
{
|
||||||
|
digest.update(byteArray, 0, bytesCount);
|
||||||
|
}
|
||||||
|
byte[] bytes = digest.digest();
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for(int i = 0;i < bytes.length;i++)
|
||||||
|
{
|
||||||
|
sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
package speiger.src.builder.misc;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
|
||||||
|
public class RegexUtil
|
||||||
|
{
|
||||||
|
static Field LAST_POS;
|
||||||
|
|
||||||
|
public static Matcher skip(Matcher matcher, int amount)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LAST_POS.setInt(matcher, LAST_POS.getInt(matcher) + amount);
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return matcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String searchUntil(String text, int startIndex, char increase, char decrease)
|
||||||
|
{
|
||||||
|
if(text.charAt(startIndex + 1) != increase)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
int inc = 0;
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
for(int i = startIndex + 1;i<text.length();i++)
|
||||||
|
{
|
||||||
|
char current = text.charAt(i);
|
||||||
|
if(current == '\\' && i < text.length() - 1 && text.charAt(i+1) == 'n')
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
else if(current == increase)
|
||||||
|
{
|
||||||
|
inc++;
|
||||||
|
}
|
||||||
|
else if(current == decrease)
|
||||||
|
{
|
||||||
|
inc--;
|
||||||
|
if(inc <= 0)
|
||||||
|
{
|
||||||
|
return builder.append(decrease).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.append(current);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int[] findFullLine(String s, int startIndex)
|
||||||
|
{
|
||||||
|
int offset = s.indexOf("\n", startIndex);
|
||||||
|
if(offset == -1) return null;
|
||||||
|
int start = s.lastIndexOf("\n", startIndex);
|
||||||
|
if(start == -1) return null;
|
||||||
|
return new int[]{start, offset};
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Field field = Matcher.class.getDeclaredField("lastAppendPosition");
|
||||||
|
field.setAccessible(true);
|
||||||
|
LAST_POS = field;
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package speiger.src.builder.processor;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
import speiger.src.builder.base.Template;
|
||||||
|
|
||||||
|
public class BuildTask implements Runnable
|
||||||
|
{
|
||||||
|
Path basePath;
|
||||||
|
Template template;
|
||||||
|
TemplateProcess process;
|
||||||
|
|
||||||
|
public BuildTask(Path basePath, Template template, TemplateProcess process)
|
||||||
|
{
|
||||||
|
this.basePath = basePath;
|
||||||
|
this.template = template;
|
||||||
|
this.process = process;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
String s = template.build(process.parsePool, process.mappers);
|
||||||
|
Path path = (process.pathBuilder != null ? process.pathBuilder.apply(basePath) : basePath).resolve(process.fileName);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Files.createDirectories(path.getParent());
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
try(BufferedWriter writer = Files.newBufferedWriter(path))
|
||||||
|
{
|
||||||
|
writer.write(s);
|
||||||
|
writer.flush();
|
||||||
|
System.out.println("Created: "+process.fileName);
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package speiger.src.builder.processor;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.UnaryOperator;
|
||||||
|
|
||||||
|
public class TemplateProcess
|
||||||
|
{
|
||||||
|
UnaryOperator<Path> pathBuilder;
|
||||||
|
String fileName;
|
||||||
|
Set<String> parsePool = new HashSet<>();
|
||||||
|
List<UnaryOperator<String>> mappers = new ArrayList<>();
|
||||||
|
|
||||||
|
public TemplateProcess(String fileName)
|
||||||
|
{
|
||||||
|
this.fileName = fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPathBuilder(UnaryOperator<Path> pathBuilder)
|
||||||
|
{
|
||||||
|
this.pathBuilder = pathBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addFlags(String...flags)
|
||||||
|
{
|
||||||
|
parsePool.addAll(Arrays.asList(flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addFlags(Collection<String> flags)
|
||||||
|
{
|
||||||
|
parsePool.addAll(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addMapper(UnaryOperator<String> mapper)
|
||||||
|
{
|
||||||
|
mappers.add(mapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addMappers(Collection<UnaryOperator<String>> mappers)
|
||||||
|
{
|
||||||
|
this.mappers.addAll(mappers);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
package speiger.src.builder.processor;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import speiger.src.builder.base.Template;
|
||||||
|
import speiger.src.builder.misc.FileUtils;
|
||||||
|
|
||||||
|
public abstract class TemplateProcessor
|
||||||
|
{
|
||||||
|
Path sourceFolder;
|
||||||
|
Path outputFolder;
|
||||||
|
Path dataFolder;
|
||||||
|
boolean init = false;
|
||||||
|
|
||||||
|
public TemplateProcessor(Path sourceFolder, Path outputFolder, Path dataFolder)
|
||||||
|
{
|
||||||
|
this.sourceFolder = sourceFolder;
|
||||||
|
this.outputFolder = outputFolder;
|
||||||
|
this.dataFolder = dataFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void init();
|
||||||
|
|
||||||
|
protected abstract boolean isFileValid(Path fileName);
|
||||||
|
|
||||||
|
public abstract void createProcesses(String fileName, Consumer<TemplateProcess> process);
|
||||||
|
|
||||||
|
protected abstract boolean relativePackages();
|
||||||
|
|
||||||
|
public final boolean process(boolean force) throws IOException, InterruptedException
|
||||||
|
{
|
||||||
|
if(!init)
|
||||||
|
{
|
||||||
|
init = true;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
Map<String, String> existing = FileUtils.loadMappings(dataFolder);
|
||||||
|
List<Path> pathsLeft = Files.walk(sourceFolder).filter(Files::isRegularFile).filter(T -> isFileValid(T.getFileName())).filter(T -> force || FileUtils.isValid(T, existing)).collect(Collectors.toList());
|
||||||
|
if(pathsLeft.isEmpty() && !force)
|
||||||
|
{
|
||||||
|
System.out.println("Nothing has changed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final boolean relative = relativePackages();
|
||||||
|
ThreadPoolExecutor service = (ThreadPoolExecutor)Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
|
||||||
|
service.setKeepAliveTime(10, TimeUnit.MILLISECONDS);
|
||||||
|
service.allowCoreThreadTimeOut(true);
|
||||||
|
service.submit(() -> {
|
||||||
|
for(int i = 0,m=pathsLeft.size();i<m;i++)
|
||||||
|
{
|
||||||
|
Path path = pathsLeft.get(i);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Template template = Template.parse(path);
|
||||||
|
createProcesses(FileUtils.getFileName(path), T -> service.execute(new BuildTask(relative ? outputFolder.resolve(sourceFolder.relativize(path).getParent()) : outputFolder, template, T)));
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
System.out.println("Started Tasks");
|
||||||
|
for(int i = 0,m=pathsLeft.size();i<m;i++)
|
||||||
|
{
|
||||||
|
Path path = pathsLeft.get(i);
|
||||||
|
existing.put(FileUtils.getFileName(path), FileUtils.getMD5String(path));
|
||||||
|
}
|
||||||
|
while(service.getActiveCount() > 0)
|
||||||
|
{
|
||||||
|
Thread.sleep(10);
|
||||||
|
}
|
||||||
|
System.out.println("Finished Tasks: "+(System.currentTimeMillis() - start)+"ms");
|
||||||
|
FileUtils.saveMappings(existing, dataFolder);
|
||||||
|
System.out.print("Saved Changes");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue