Compare commits
18 Commits
Author | SHA1 | Date |
---|---|---|
Speiger | d5a47ce568 | |
Speiger | d90a9ad71c | |
Speiger | b0792532b1 | |
Speiger | a63defacbb | |
Speiger | 6e5e91d0bd | |
Speiger | b60f4ff1fd | |
Speiger | 2fe297b708 | |
Speiger | 9c4c33c1eb | |
Speiger | 4a72afdb1c | |
Speiger | d4e3da23fa | |
Speiger | d3d1cb48b6 | |
Speiger | b979e9d9e8 | |
Speiger | 6f3f45d718 | |
Speiger | 8937d44428 | |
Speiger | b165524c36 | |
Speiger | 9aedebd317 | |
Speiger | c50e022ec2 | |
Speiger | 54e66d7f53 |
|
@ -1,5 +1,6 @@
|
|||
# ---> Gradle
|
||||
.gradle
|
||||
gradle.properties
|
||||
**/build/
|
||||
!src/**/build/
|
||||
|
||||
|
|
|
@ -1,2 +1,13 @@
|
|||
arguments=
|
||||
auto.sync=false
|
||||
build.scans.enabled=false
|
||||
connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER)
|
||||
connection.project.dir=
|
||||
eclipse.preferences.version=1
|
||||
gradle.user.home=
|
||||
java.home=
|
||||
jvm.arguments=
|
||||
offline.mode=false
|
||||
override.workspace.settings=false
|
||||
show.console.view=false
|
||||
show.executions.view=false
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
eclipse.preferences.version=1
|
||||
encoding/<project>=UTF-8
|
12
README.md
12
README.md
|
@ -6,6 +6,18 @@ It has a cache that keeps track of the input (if it was changed), and only cares
|
|||
|
||||
It is as bare bones as it can get but that also makes it flexible.
|
||||
|
||||
# How to install
|
||||
Using Gradle:
|
||||
```gradle
|
||||
repositories {
|
||||
maven {
|
||||
url = "https://maven.speiger.com/repository/main"
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
compile 'de.speiger:Simple-Code-Generator:1.1.4'
|
||||
}
|
||||
```
|
||||
|
||||
# How to create a Template Processor
|
||||
|
||||
|
|
33
build.gradle
33
build.gradle
|
@ -5,7 +5,8 @@ repositories {
|
|||
}
|
||||
|
||||
archivesBaseName = 'Simple Code Generator'
|
||||
version = '1.0.1'
|
||||
version = '1.3.0'
|
||||
apply plugin: 'maven'
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
options.encoding = 'UTF-8'
|
||||
|
@ -22,3 +23,33 @@ task srcJar(type: Jar) {
|
|||
artifacts {
|
||||
archives srcJar
|
||||
}
|
||||
|
||||
uploadArchives {
|
||||
repositories.mavenDeployer {
|
||||
repository(url: 'https://maven.speiger.com/repository/main') {
|
||||
authentication(userName: project.properties.mavenUser, password: project.properties.mavenPassword)
|
||||
}
|
||||
snapshotRepository(url: 'https://maven.speiger.com/repository/main') {
|
||||
authentication(userName: project.properties.mavenUser, password: project.properties.mavenPassword)
|
||||
}
|
||||
pom {
|
||||
version = project.version
|
||||
artifactId = project.archivesBaseName.replace(" ", "-")
|
||||
groupId = 'de.speiger'
|
||||
project {
|
||||
licenses {
|
||||
license {
|
||||
name = 'The Apache License, Version 2.0'
|
||||
url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
|
||||
}
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
id = 'speiger'
|
||||
name = 'Speiger'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
test=ddb9367ebd61888ab31a658dd6f6df86
|
|
@ -0,0 +1,53 @@
|
|||
Hello this is my test
|
||||
|
||||
#ignore
|
||||
TESTING should not be overriden
|
||||
#endignore
|
||||
|
||||
TESTING should be overriden
|
||||
|
||||
#if TEST0
|
||||
#ignore
|
||||
TESTING should not be overriden too
|
||||
#endignore
|
||||
|
||||
TESTING should be overriden too
|
||||
#endif
|
||||
#if TEST1
|
||||
|
||||
#ignore
|
||||
TESTING should not be overriden
|
||||
#endignore
|
||||
|
||||
TESTING should not be overriden
|
||||
#endif
|
||||
|
||||
#iterate
|
||||
#argument NUMBER 1 2 3 4 5 6 7 8 9
|
||||
Lets test number NUMBER
|
||||
#enditerate
|
||||
|
||||
#if TEST0
|
||||
Lets test a true condition.
|
||||
#iterate
|
||||
#argument NUMBER 1 2 3 4 5 6 7 8 9
|
||||
Lets test number NUMBER
|
||||
#enditerate
|
||||
#endif
|
||||
|
||||
#if TEST1
|
||||
Lets test a false condition.
|
||||
#iterate
|
||||
#argument NUMBER 1 2 3 4 5 6 7 8 9
|
||||
Lets test number NUMBER
|
||||
#enditerate
|
||||
#endif
|
||||
|
||||
Lets test stacked iterators
|
||||
#iterate
|
||||
#argument NUMBER1 1 2 3
|
||||
#iterate
|
||||
#argument NUMBER2 4 5 6
|
||||
Lets test numbers NUMBER1 NUMBER2
|
||||
#enditerate
|
||||
#enditerate
|
|
@ -0,0 +1,41 @@
|
|||
Hello this is my test
|
||||
|
||||
TESTING should not be overriden
|
||||
|
||||
Test2 should be overriden
|
||||
TESTING should not be overriden too
|
||||
|
||||
Test2 should be overriden too
|
||||
|
||||
Lets test number 1
|
||||
Lets test number 2
|
||||
Lets test number 3
|
||||
Lets test number 4
|
||||
Lets test number 5
|
||||
Lets test number 6
|
||||
Lets test number 7
|
||||
Lets test number 8
|
||||
Lets test number 9
|
||||
|
||||
Lets test a true condition.
|
||||
Lets test number 1
|
||||
Lets test number 2
|
||||
Lets test number 3
|
||||
Lets test number 4
|
||||
Lets test number 5
|
||||
Lets test number 6
|
||||
Lets test number 7
|
||||
Lets test number 8
|
||||
Lets test number 9
|
||||
|
||||
|
||||
Lets test stacked iterators
|
||||
Lets test numbers 1 4
|
||||
Lets test numbers 1 5
|
||||
Lets test numbers 1 6
|
||||
Lets test numbers 2 4
|
||||
Lets test numbers 2 5
|
||||
Lets test numbers 2 6
|
||||
Lets test numbers 3 4
|
||||
Lets test numbers 3 5
|
||||
Lets test numbers 3 6
|
|
@ -2,11 +2,12 @@ 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;
|
||||
import speiger.src.builder.misc.IdGenerator;
|
||||
import speiger.src.builder.processor.CompiledArguments;
|
||||
|
||||
public class ConditionedSegment
|
||||
{
|
||||
|
@ -26,23 +27,28 @@ public class ConditionedSegment
|
|||
segments.add(segment);
|
||||
}
|
||||
|
||||
public int build(Set<String> parsePool, StringBuilder builder, int baseIndex)
|
||||
public int build(CompiledArguments process, 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;
|
||||
if(segments.get(i).build(process, builder, baseIndex)) break;
|
||||
}
|
||||
return builder.length() - length;
|
||||
}
|
||||
|
||||
public static int parse(String fileName, String currentLine, List<String> lines, int currentIndex, int startIndex, List<ConditionedSegment> segments) throws IllegalStateException
|
||||
public static int parse(String fileName, String currentLine, List<String> lines, int currentIndex, int startIndex, IdGenerator ignoreCounter, List<ConditionedSegment> segments, List<PostSegment> postSegments) throws IllegalStateException
|
||||
{
|
||||
String ignoreSegmentId = ignoreCounter.getId();
|
||||
ConditionedSegment segment = new ConditionedSegment(startIndex);
|
||||
ICondition condition = ICondition.parse(currentLine);
|
||||
ICondition condition = currentLine == null ? null : ICondition.parse(currentLine);
|
||||
List<ConditionedSegment> childSegments = new ArrayList<>();
|
||||
StringJoiner segmentText = new StringJoiner("\n", "\n", "");
|
||||
StringJoiner segmentText = new StringJoiner("\n", (currentIndex <= 0 || includeStartNewLine(lines.get(currentIndex-1).trim())) ? "\n" : "", "");
|
||||
if(currentLine == null) {
|
||||
lines.set(currentIndex, ignoreSegmentId);
|
||||
}
|
||||
|
||||
for(int i = currentIndex+1;i<lines.size();i++)
|
||||
{
|
||||
String s = lines.get(i);
|
||||
|
@ -51,6 +57,7 @@ public class ConditionedSegment
|
|||
{
|
||||
if(trimmed.startsWith("#else if"))
|
||||
{
|
||||
if(currentLine == null) throw new IllegalStateException("#else if isn't working while in a ignore segment");
|
||||
segment.addSegment(new Segment(segmentText.toString(), condition, childSegments));
|
||||
condition = ICondition.parse(trimmed.substring(8).trim());
|
||||
childSegments = new ArrayList<>();
|
||||
|
@ -58,6 +65,7 @@ public class ConditionedSegment
|
|||
}
|
||||
else if(trimmed.startsWith("#else"))
|
||||
{
|
||||
if(currentLine == null) throw new IllegalStateException("#else isn't working while in a ignore segment");
|
||||
segment.addSegment(new Segment(segmentText.toString(), condition, childSegments));
|
||||
condition = ICondition.ALWAYS_TRUE;
|
||||
childSegments = new ArrayList<>();
|
||||
|
@ -65,13 +73,33 @@ public class ConditionedSegment
|
|||
}
|
||||
else if(trimmed.startsWith("#endif"))
|
||||
{
|
||||
if(currentLine == null) throw new IllegalStateException("#endif isn't working while in a ignore segment");
|
||||
segment.addSegment(new Segment(segmentText.toString(), condition, childSegments));
|
||||
segments.add(segment);
|
||||
return i - currentIndex;
|
||||
}
|
||||
else if(trimmed.startsWith("#endignore"))
|
||||
{
|
||||
postSegments.add(new PostSegment(segmentText.toString(), ignoreSegmentId));
|
||||
segments.add(segment);
|
||||
return i - currentIndex;
|
||||
}
|
||||
else if(trimmed.startsWith("#if"))
|
||||
{
|
||||
i += parse(fileName, trimmed.substring(3).trim(), lines, i, segmentText.length(), childSegments);
|
||||
if(currentLine == null) throw new IllegalStateException("#if isn't working while in a ignore segment");
|
||||
i += parse(fileName, trimmed.substring(3).trim(), lines, i, segmentText.length(), ignoreCounter, childSegments, postSegments);
|
||||
}
|
||||
else if(trimmed.startsWith("#ignore"))
|
||||
{
|
||||
if(currentLine == null) throw new IllegalStateException("#ignore lines can't be applied Recursively");
|
||||
ignoreCounter.appendId();
|
||||
int prev = i;
|
||||
i += parse(fileName, null, lines, i, segmentText.length(), ignoreCounter, childSegments, postSegments);
|
||||
segmentText.add(lines.get(prev));
|
||||
}
|
||||
else if(trimmed.startsWith("#iterate")) {
|
||||
SegmentIterator.iterateSegment(fileName, trimmed, lines, i, segmentText.length());
|
||||
i--;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -80,4 +108,8 @@ public class ConditionedSegment
|
|||
throw new IllegalStateException("Unclosed #If found in ["+fileName+"] at line ["+startIndex+"]");
|
||||
}
|
||||
|
||||
static boolean includeStartNewLine(String s)
|
||||
{
|
||||
return !s.startsWith("#") || s.equalsIgnoreCase("#endif") || s.equalsIgnoreCase("#endignore");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package speiger.src.builder.base;
|
||||
|
||||
public class PostSegment
|
||||
{
|
||||
String text;
|
||||
String identifier;
|
||||
|
||||
public PostSegment(String text, String identifier)
|
||||
{
|
||||
this.text = text;
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public String build(String input)
|
||||
{
|
||||
return input.replaceAll("\n"+identifier, text);
|
||||
}
|
||||
}
|
|
@ -2,9 +2,9 @@ package speiger.src.builder.base;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import speiger.src.builder.conditions.ICondition;
|
||||
import speiger.src.builder.processor.CompiledArguments;
|
||||
|
||||
public class Segment
|
||||
{
|
||||
|
@ -19,14 +19,14 @@ public class Segment
|
|||
this.segments = segments;
|
||||
}
|
||||
|
||||
public boolean build(Set<String> parsePool, StringBuilder builder, int index)
|
||||
public boolean build(CompiledArguments process, StringBuilder builder, int index)
|
||||
{
|
||||
if(condition.isValid(parsePool))
|
||||
if(condition.isValid(process))
|
||||
{
|
||||
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);
|
||||
offset += segments.get(i).build(process, builder, index+offset);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
package speiger.src.builder.base;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class SegmentIterator {
|
||||
public static void iterateSegment(String fileName, String currentLine, List<String> lines, int currentIndex, int startIndex) {
|
||||
List<String[]> arguments = new ArrayList<>();
|
||||
StringJoiner toIterate = new StringJoiner("\n");
|
||||
int skip = 0;
|
||||
int end = 1;
|
||||
for(int i = currentIndex+1;i<lines.size();i++, end++)
|
||||
{
|
||||
String s = lines.get(i);
|
||||
String trimmed = s.trim();
|
||||
if(trimmed.startsWith("#"))
|
||||
{
|
||||
if(trimmed.startsWith("#enditerate"))
|
||||
{
|
||||
skip--;
|
||||
if(skip < 0)
|
||||
{
|
||||
end++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(trimmed.startsWith("#iterate")) skip++;
|
||||
if(skip > 0)
|
||||
{
|
||||
toIterate.add(s);
|
||||
continue;
|
||||
}
|
||||
if(trimmed.startsWith("#argument"))
|
||||
{
|
||||
arguments.add(trimmed.substring(9).trim().split(" "));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
toIterate.add(s);
|
||||
}
|
||||
int size = arguments.get(0).length;
|
||||
for(int i = 1,m=arguments.size();i<m;i++) {
|
||||
if(arguments.get(i).length != size) throw new RuntimeException("Iteration arguments in file ["+fileName+"] are not equal size. Arugments="+arguments.stream().flatMap(Arrays::stream).collect(Collectors.toList()));
|
||||
}
|
||||
for(int i = 0;i<end;i++) {
|
||||
lines.remove(currentIndex);
|
||||
}
|
||||
String toInsert = toIterate.toString();
|
||||
for(int i = size-1;i>=1;i--) {
|
||||
String temp = toInsert;
|
||||
for(int j = 0;j<arguments.size();j++) {
|
||||
String[] argument = arguments.get(j);
|
||||
temp = temp.replace(argument[0], argument[i]);
|
||||
}
|
||||
lines.addAll(currentIndex, Arrays.asList(temp.split("\n", -1)));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,18 +10,22 @@ import java.util.StringJoiner;
|
|||
|
||||
import speiger.src.builder.mappers.IMapper;
|
||||
import speiger.src.builder.misc.FileUtils;
|
||||
import speiger.src.builder.misc.IdGenerator;
|
||||
import speiger.src.builder.processor.CompiledArguments;
|
||||
|
||||
public class Template
|
||||
{
|
||||
String fileName;
|
||||
String textFile;
|
||||
List<ConditionedSegment> segments;
|
||||
List<PostSegment> postSegments;
|
||||
|
||||
public Template(String fileName, String textFile, List<ConditionedSegment> segments)
|
||||
public Template(String fileName, String textFile, List<ConditionedSegment> segments, List<PostSegment> postSegments)
|
||||
{
|
||||
this.fileName = fileName;
|
||||
this.textFile = textFile;
|
||||
this.segments = segments;
|
||||
this.postSegments = postSegments;
|
||||
}
|
||||
|
||||
public String getFileName()
|
||||
|
@ -29,13 +33,14 @@ public class Template
|
|||
return fileName;
|
||||
}
|
||||
|
||||
public String build(Set<String> parsePool, List<IMapper> mappers, boolean printNoWork, Set<IMapper> done)
|
||||
public String build(CompiledArguments process, boolean printNoWork, Set<IMapper> done)
|
||||
{
|
||||
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);
|
||||
offset += segments.get(i).build(process, builder, offset);
|
||||
}
|
||||
List<IMapper> mappers = process.getMapper();
|
||||
String result = builder.toString();
|
||||
for(int i = 0,m=mappers.size();i<m;i++)
|
||||
{
|
||||
|
@ -53,13 +58,19 @@ public class Template
|
|||
result = mappers.get(i).apply(result);
|
||||
}
|
||||
}
|
||||
for(int i = 0,m=postSegments.size();i<m;i++)
|
||||
{
|
||||
result = postSegments.get(i).build(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Template parse(Path file) throws IOException
|
||||
{
|
||||
String fileName = FileUtils.getFileName(file.getFileName());
|
||||
List<ConditionedSegment> segments = new ArrayList<ConditionedSegment>();
|
||||
IdGenerator segmentIds = new IdGenerator();
|
||||
List<ConditionedSegment> segments = new ArrayList<>();
|
||||
List<PostSegment> postSegments = new ArrayList<>();
|
||||
StringJoiner joiner = new StringJoiner("\n");
|
||||
List<String> lines = Files.readAllLines(file);
|
||||
for(int i = 0;i<lines.size();i++)
|
||||
|
@ -70,7 +81,20 @@ public class Template
|
|||
{
|
||||
if(trimmed.startsWith("#if"))
|
||||
{
|
||||
i += ConditionedSegment.parse(fileName, s.trim().substring(3).trim(), lines, i, joiner.length(), segments);
|
||||
i += ConditionedSegment.parse(fileName, s.trim().substring(3).trim(), lines, i, joiner.length(), segmentIds, segments, postSegments);
|
||||
continue;
|
||||
}
|
||||
else if(trimmed.startsWith("#ignore"))
|
||||
{
|
||||
segmentIds.appendId();
|
||||
int prev = i;
|
||||
i += ConditionedSegment.parse(fileName, null, lines, i, joiner.length(), segmentIds, segments, postSegments);
|
||||
joiner.add(lines.get(prev));
|
||||
continue;
|
||||
}
|
||||
else if(trimmed.startsWith("#iterate")) {
|
||||
SegmentIterator.iterateSegment(fileName, trimmed, lines, i, joiner.length());
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
else if(trimmed.startsWith("#symlink"))
|
||||
|
@ -80,6 +104,6 @@ public class Template
|
|||
}
|
||||
joiner.add(s);
|
||||
}
|
||||
return new Template(fileName, joiner.toString(), segments);
|
||||
return new Template(fileName, joiner.toString(), segments, postSegments);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,28 +2,32 @@ package speiger.src.builder.conditions;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import speiger.src.builder.processor.CompiledArguments;
|
||||
|
||||
public class AndCondition implements ICondition
|
||||
{
|
||||
List<ICondition> conditions = new ArrayList<>();
|
||||
|
||||
public AndCondition() {}
|
||||
|
||||
public AndCondition(ICondition base)
|
||||
{
|
||||
conditions.add(base);
|
||||
addCondition(base);
|
||||
}
|
||||
|
||||
public void addCondition(ICondition e)
|
||||
{
|
||||
if(e == null) return;
|
||||
conditions.add(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(Set<String> parsePool)
|
||||
public boolean isValid(CompiledArguments args)
|
||||
{
|
||||
for(int i = 0,m=conditions.size();i<m;i++)
|
||||
{
|
||||
if(!conditions.get(i).isValid(parsePool))
|
||||
if(!conditions.get(i).isValid(args))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package speiger.src.builder.conditions;
|
||||
|
||||
import java.util.Set;
|
||||
import speiger.src.builder.processor.CompiledArguments;
|
||||
|
||||
public class FlagCondition implements ICondition
|
||||
{
|
||||
|
@ -14,8 +14,8 @@ public class FlagCondition implements ICondition
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(Set<String> parsePool)
|
||||
public boolean isValid(CompiledArguments args)
|
||||
{
|
||||
return parsePool.contains(flag) != inverted;
|
||||
return args.test(flag) != inverted;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,61 +1,74 @@
|
|||
package speiger.src.builder.conditions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import speiger.src.builder.misc.RegexUtil;
|
||||
import speiger.src.builder.processor.CompiledArguments;
|
||||
|
||||
public interface ICondition
|
||||
{
|
||||
public static final Set<Character> VALID_CHARACTERS = new HashSet<>(Arrays.asList('(', ')'));
|
||||
public static final ICondition ALWAYS_TRUE = T -> true;
|
||||
|
||||
public boolean isValid(Set<String> parsePool);
|
||||
public boolean isValid(CompiledArguments args);
|
||||
|
||||
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;
|
||||
public static ICondition parse(List<String> elements) {
|
||||
List<ICondition> conditions = new ArrayList<>();
|
||||
AndCondition activeAnd = null;
|
||||
for(int i = 0,m=elements.size();i<m;i++) {
|
||||
String entry = elements.get(i);
|
||||
if(entry.equalsIgnoreCase("(")) {
|
||||
int endIndex = RegexUtil.lastIndexOf(elements, i, "(", ")");
|
||||
if(endIndex == -1) throw new IllegalStateException("A Condition Closer [ ) ] is missing");
|
||||
ICondition result = parse(elements.subList(i+1, endIndex));
|
||||
if(activeAnd != null) activeAnd.addCondition(result);
|
||||
else conditions.add(result);
|
||||
i = endIndex+1;
|
||||
}
|
||||
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(entry.equalsIgnoreCase("&&")) {
|
||||
if(activeAnd != null) continue;
|
||||
if(i != 0) {
|
||||
ICondition prev = conditions.get(conditions.size()-1);
|
||||
if(prev instanceof AndCondition) activeAnd = (AndCondition)prev;
|
||||
else {
|
||||
activeAnd = new AndCondition(prev);
|
||||
conditions.set(conditions.size()-1, activeAnd);
|
||||
}
|
||||
}
|
||||
else {
|
||||
activeAnd = new AndCondition();
|
||||
conditions.add(activeAnd);
|
||||
}
|
||||
else if(!elements[i].equalsIgnoreCase("||"))
|
||||
{
|
||||
conditions.add(parseSimpleCondition(elements[i]));
|
||||
}
|
||||
else if(entry.equalsIgnoreCase("||")) {
|
||||
activeAnd = null;
|
||||
}
|
||||
else {
|
||||
if(activeAnd != null) activeAnd.addCondition(parseCondition(entry));
|
||||
else conditions.add(parseCondition(entry));
|
||||
}
|
||||
}
|
||||
switch(conditions.size())
|
||||
{
|
||||
case 0: return ALWAYS_TRUE;
|
||||
case 0: throw new IllegalStateException("Empty Conditions are not allowed");
|
||||
case 1: return conditions.get(0);
|
||||
default: return new OrCondition(conditions);
|
||||
}
|
||||
}
|
||||
|
||||
static ICondition parseSimpleCondition(String s)
|
||||
public static ICondition parse(String condition)
|
||||
{
|
||||
return parse(Arrays.asList(RegexUtil.ensureWhitespaces(condition, VALID_CHARACTERS).split(" ")));
|
||||
}
|
||||
|
||||
static ICondition parseCondition(String s)
|
||||
{
|
||||
ICondition numbers = NumberCondition.tryBuild(s);
|
||||
if(numbers != null) return numbers;
|
||||
return s.startsWith("!") ? new FlagCondition(s.substring(1), true) : new FlagCondition(s, false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
package speiger.src.builder.conditions;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import speiger.src.builder.processor.CompiledArguments;
|
||||
|
||||
public class NumberCondition implements ICondition
|
||||
{
|
||||
private static final Pattern SCANNER = Pattern.compile(Operation.buildReggex());
|
||||
String flag;
|
||||
Operation op;
|
||||
int number;
|
||||
boolean flipped;
|
||||
|
||||
public NumberCondition(String flag, Operation op, int number, boolean flipped)
|
||||
{
|
||||
this.flag = flag;
|
||||
this.op = op;
|
||||
this.number = number;
|
||||
this.flipped = flipped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(CompiledArguments args)
|
||||
{
|
||||
return op.matches(flipped ? number : args.get(flag), flipped ? args.get(flag) : number);
|
||||
}
|
||||
|
||||
public static NumberCondition tryBuild(String arg)
|
||||
{
|
||||
Matcher match = SCANNER.matcher(arg);
|
||||
if(!match.find()) return null;
|
||||
int start = match.start();
|
||||
int end = match.end();
|
||||
Operation op = Operation.byId(arg.substring(start, end));
|
||||
if(op == null) throw new IllegalArgumentException("Operation ["+arg.substring(start, end)+"] is unknown");
|
||||
String key = arg.substring(0, start);
|
||||
String value = arg.substring(end);
|
||||
int[] result = new int[1];
|
||||
if(parse(key, result)) return new NumberCondition(value, op, result[0], true);
|
||||
if(parse(value, result)) return new NumberCondition(key, op, result[0], false);
|
||||
throw new IllegalStateException("Neither key or value are parsable");
|
||||
}
|
||||
|
||||
|
||||
private static boolean parse(String arg, int[] output) {
|
||||
try { output[0] = Integer.parseInt(arg); }
|
||||
catch(Exception e) { return false;}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static enum Operation
|
||||
{
|
||||
EQUALS("=="),
|
||||
GREATER_EQUALS(">="),
|
||||
GREATER(">"),
|
||||
SMALLER_EQUALS("<="),
|
||||
SMALLER("<"),
|
||||
NOT_EQUALS("!="),
|
||||
BIT_EQUALS_ALL("&="),
|
||||
BIT_EQUALS_ANY("|="),
|
||||
BIT_EQUALS_NOT("~=");
|
||||
|
||||
static final Map<String, Operation> DATA = Arrays.stream(values()).collect(Collectors.toMap(Operation::getId, Function.identity()));
|
||||
String key;
|
||||
|
||||
private Operation(String key)
|
||||
{
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public static String buildReggex()
|
||||
{
|
||||
StringJoiner joiner = new StringJoiner("|\\", "\\", "");
|
||||
for(Operation entry : values())
|
||||
{
|
||||
joiner.add(entry.getId());
|
||||
}
|
||||
return joiner.toString();
|
||||
}
|
||||
|
||||
public String getId()
|
||||
{
|
||||
return key;
|
||||
}
|
||||
|
||||
public boolean matches(int key, int value)
|
||||
{
|
||||
switch(this)
|
||||
{
|
||||
case EQUALS: return key == value;
|
||||
case NOT_EQUALS: return key != value;
|
||||
case GREATER: return key > value;
|
||||
case GREATER_EQUALS: return key >= value;
|
||||
case SMALLER: return key < value;
|
||||
case SMALLER_EQUALS: return key <= value;
|
||||
case BIT_EQUALS_ALL: return (key & value) == value;
|
||||
case BIT_EQUALS_ANY: return (key & value) != 0;
|
||||
case BIT_EQUALS_NOT: return (key & value) == 0;
|
||||
default: return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static Operation byId(String key)
|
||||
{
|
||||
return DATA.get(key);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
package speiger.src.builder.conditions;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import speiger.src.builder.processor.CompiledArguments;
|
||||
|
||||
public class OrCondition implements ICondition
|
||||
{
|
||||
|
@ -13,11 +14,11 @@ public class OrCondition implements ICondition
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(Set<String> parsePool)
|
||||
public boolean isValid(CompiledArguments args)
|
||||
{
|
||||
for(int i = 0,m=conditions.size();i<m;i++)
|
||||
{
|
||||
if(conditions.get(i).isValid(parsePool))
|
||||
if(conditions.get(i).isValid(args))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package speiger.src.builder.mappers;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import speiger.src.builder.misc.RegexMatcher;
|
||||
import speiger.src.builder.misc.RegexUtil;
|
||||
|
||||
public class ArgumentMapper implements IMapper
|
||||
|
@ -49,7 +49,9 @@ public class ArgumentMapper implements IMapper
|
|||
@Override
|
||||
public String apply(String t)
|
||||
{
|
||||
Matcher matcher = pattern.matcher(t);
|
||||
RegexMatcher matcher = new RegexMatcher(pattern, t);
|
||||
try
|
||||
{
|
||||
if(matcher.find())
|
||||
{
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
@ -58,13 +60,23 @@ public class ArgumentMapper implements IMapper
|
|||
String text = RegexUtil.searchUntil(t, matcher.end()-1, braces.charAt(0), braces.charAt(1));
|
||||
if(!text.isEmpty())
|
||||
{
|
||||
RegexUtil.skip(matcher.appendReplacement(buffer, ""), text.length());
|
||||
matcher.appendReplacement(buffer, "").skip(text.length());
|
||||
buffer.append(String.format(replacement, (Object[])getString(text).split(argumentBreaker)));
|
||||
}
|
||||
}
|
||||
while(matcher.find());
|
||||
matcher.appendTail(buffer);
|
||||
return buffer.toString();
|
||||
return apply(buffer.toString());
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch(Error error)
|
||||
{
|
||||
System.out.println("Error with ["+pattern.pattern()+"] pattern");
|
||||
throw error;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package speiger.src.builder.mappers;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import speiger.src.builder.misc.RegexMatcher;
|
||||
import speiger.src.builder.misc.RegexUtil;
|
||||
|
||||
public class InjectMapper implements IMapper
|
||||
|
@ -47,7 +47,9 @@ public class InjectMapper implements IMapper
|
|||
@Override
|
||||
public String apply(String t)
|
||||
{
|
||||
Matcher matcher = pattern.matcher(t);
|
||||
RegexMatcher matcher = new RegexMatcher(pattern, t);
|
||||
try
|
||||
{
|
||||
if(matcher.find())
|
||||
{
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
@ -56,12 +58,22 @@ public class InjectMapper implements IMapper
|
|||
String text = RegexUtil.searchUntil(t, matcher.end()-1, braces.charAt(0), braces.charAt(1));
|
||||
if(!text.isEmpty())
|
||||
{
|
||||
RegexUtil.skip(matcher.appendReplacement(buffer, ""), text.length());
|
||||
matcher.appendReplacement(buffer, "").skip(text.length());
|
||||
buffer.append(String.format(replacement, getString(text)));
|
||||
}
|
||||
} while (matcher.find());
|
||||
matcher.appendTail(buffer);
|
||||
return buffer.toString();
|
||||
return apply(buffer.toString());
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch(Error error)
|
||||
{
|
||||
System.out.println("Error with ["+pattern.pattern()+"] pattern");
|
||||
throw error;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package speiger.src.builder.mappers;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import speiger.src.builder.misc.RegexMatcher;
|
||||
import speiger.src.builder.misc.RegexUtil;
|
||||
|
||||
public class LineMapper implements IMapper
|
||||
|
@ -30,7 +30,9 @@ public class LineMapper implements IMapper
|
|||
@Override
|
||||
public String apply(String t)
|
||||
{
|
||||
Matcher matcher = pattern.matcher(t);
|
||||
RegexMatcher matcher = new RegexMatcher(pattern, t);
|
||||
try
|
||||
{
|
||||
if(matcher.find())
|
||||
{
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
@ -42,11 +44,21 @@ public class LineMapper implements IMapper
|
|||
{
|
||||
matcher.appendReplacement(buffer, pattern.pattern());
|
||||
buffer.setLength(buffer.length() - (start - result[0]));
|
||||
RegexUtil.skip(matcher, result[1] - start);
|
||||
matcher.skip(result[1] - start);
|
||||
}
|
||||
} while (matcher.find());
|
||||
matcher.appendTail(buffer);
|
||||
return buffer.toString();
|
||||
return apply(buffer.toString());
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch(Error error)
|
||||
{
|
||||
System.out.println("Error with ["+pattern.pattern()+"] pattern");
|
||||
throw error;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,20 @@ public class SimpleMapper implements IMapper
|
|||
|
||||
@Override
|
||||
public String apply(String t)
|
||||
{
|
||||
try
|
||||
{
|
||||
return pattern.matcher(t).replaceAll(replacement);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch(Error error)
|
||||
{
|
||||
System.out.println("Error with ["+pattern.pattern()+"] pattern");
|
||||
throw error;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,9 +6,10 @@ import java.io.InputStream;
|
|||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class FileUtils
|
||||
{
|
||||
|
@ -40,9 +41,11 @@ public class FileUtils
|
|||
{
|
||||
try(BufferedWriter writer = Files.newBufferedWriter(dataFolder.resolve("cache.bin")))
|
||||
{
|
||||
for(Entry<String, String> entry : mappings.entrySet())
|
||||
List<String> keys = new ArrayList<String>(mappings.keySet());
|
||||
keys.sort(String.CASE_INSENSITIVE_ORDER);
|
||||
for(String s : keys)
|
||||
{
|
||||
writer.write(entry.getKey()+"="+entry.getValue());
|
||||
writer.write(s+"="+mappings.get(s));
|
||||
writer.newLine();
|
||||
}
|
||||
writer.flush();
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package speiger.src.builder.misc;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class IdGenerator
|
||||
{
|
||||
AtomicInteger integer = new AtomicInteger();
|
||||
|
||||
public void appendId()
|
||||
{
|
||||
integer.incrementAndGet();
|
||||
}
|
||||
|
||||
public String getId()
|
||||
{
|
||||
return "#ignoreLine"+integer.get()+"suffix";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package speiger.src.builder.misc;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class RegexMatcher
|
||||
{
|
||||
Matcher match;
|
||||
StringWrapper text;
|
||||
|
||||
public RegexMatcher(Pattern pattern, String text)
|
||||
{
|
||||
this.text = new StringWrapper(text);
|
||||
match = pattern.matcher(this.text);
|
||||
}
|
||||
|
||||
public boolean find()
|
||||
{
|
||||
return match.find();
|
||||
}
|
||||
|
||||
public int end()
|
||||
{
|
||||
return match.end()+text.getOffset();
|
||||
}
|
||||
|
||||
public RegexMatcher appendReplacement(StringBuffer sb, String replacement)
|
||||
{
|
||||
match.appendReplacement(sb, replacement);
|
||||
return this;
|
||||
}
|
||||
|
||||
public RegexMatcher appendTail(StringBuffer sb)
|
||||
{
|
||||
match.appendTail(sb);
|
||||
return this;
|
||||
}
|
||||
|
||||
public RegexMatcher skip(int amount)
|
||||
{
|
||||
text.offset(amount+match.end());
|
||||
match.reset();
|
||||
return this;
|
||||
}
|
||||
|
||||
public static class StringWrapper implements CharSequence
|
||||
{
|
||||
String s;
|
||||
int offset;
|
||||
|
||||
public StringWrapper(String s)
|
||||
{
|
||||
this.s = s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length()
|
||||
{
|
||||
return s.length() - offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char charAt(int index)
|
||||
{
|
||||
return s.charAt(index+offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence subSequence(int start, int end)
|
||||
{
|
||||
return s.subSequence(start+offset, end+offset);
|
||||
}
|
||||
|
||||
public void offset(int offset)
|
||||
{
|
||||
this.offset += offset;
|
||||
}
|
||||
|
||||
public int getOffset()
|
||||
{
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,25 +1,10 @@
|
|||
package speiger.src.builder.misc;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
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)
|
||||
|
@ -61,17 +46,31 @@ public class RegexUtil
|
|||
return new int[]{start, offset};
|
||||
}
|
||||
|
||||
static
|
||||
public static int lastIndexOf(List<String> list, int startIndex, String increase, String decrease)
|
||||
{
|
||||
try
|
||||
if(!list.get(startIndex).equalsIgnoreCase(increase)) return -1;
|
||||
int inc = 0;
|
||||
for(int i = startIndex;i<list.size();i++)
|
||||
{
|
||||
Field field = Matcher.class.getDeclaredField("lastAppendPosition");
|
||||
field.setAccessible(true);
|
||||
LAST_POS = field;
|
||||
String entry = list.get(i);
|
||||
if(entry.equalsIgnoreCase(increase)) inc++;
|
||||
else if(entry.equalsIgnoreCase(decrease)) {
|
||||
inc--;
|
||||
if(inc <= 0) return i;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static String ensureWhitespaces(String s, Set<Character> set) {
|
||||
StringBuilder builder = new StringBuilder(s);
|
||||
for(int i = s.length()-1;i>=0;i--) {
|
||||
char entry = builder.charAt(i);
|
||||
if(entry != ' ' && set.contains(entry)) {
|
||||
if(builder.charAt(i+1) != ' ') builder.insert(i+1, ' ');
|
||||
if(builder.charAt(i-1) != ' ') builder.insert(i, ' ');
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
|
@ -14,19 +14,21 @@ public class BuildTask implements Runnable
|
|||
Template template;
|
||||
TemplateProcess process;
|
||||
Set<IMapper>[] mappers;
|
||||
boolean silencedSuccess;
|
||||
|
||||
public BuildTask(Path basePath, Template template, TemplateProcess process, Set<IMapper>[] mappers)
|
||||
public BuildTask(Path basePath, Template template, TemplateProcess process, boolean silencedSuccess, Set<IMapper>[] mappers)
|
||||
{
|
||||
this.basePath = basePath;
|
||||
this.template = template;
|
||||
this.process = process;
|
||||
this.silencedSuccess = silencedSuccess;
|
||||
this.mappers = mappers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
String s = template.build(process.parsePool, process.mappers, mappers != null, mappers != null ? mappers[1] : null);
|
||||
String s = template.build(new CompiledArguments(process), mappers != null, mappers != null ? mappers[1] : null);
|
||||
if(mappers != null)
|
||||
{
|
||||
mappers[0].addAll(process.mappers);
|
||||
|
@ -44,7 +46,7 @@ public class BuildTask implements Runnable
|
|||
{
|
||||
writer.write(s);
|
||||
writer.flush();
|
||||
System.out.println("Created: "+process.fileName);
|
||||
if(!silencedSuccess) System.out.println("Created: "+process.fileName);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package speiger.src.builder.processor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import speiger.src.builder.mappers.IMapper;
|
||||
|
||||
public class CompiledArguments
|
||||
{
|
||||
List<IMapper> mapper;
|
||||
Set<String> flags;
|
||||
Map<String, Integer> flaggedValues;
|
||||
|
||||
public CompiledArguments(TemplateProcess process)
|
||||
{
|
||||
mapper = process.mappers;
|
||||
flags = process.parsePool;
|
||||
flaggedValues = process.parseValues;
|
||||
}
|
||||
|
||||
public List<IMapper> getMapper()
|
||||
{
|
||||
return mapper;
|
||||
}
|
||||
|
||||
public boolean test(String key)
|
||||
{
|
||||
return flags.contains(key);
|
||||
}
|
||||
|
||||
public int get(String key)
|
||||
{
|
||||
return flaggedValues.getOrDefault(key, 0);
|
||||
}
|
||||
}
|
|
@ -4,8 +4,10 @@ import java.nio.file.Path;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
|
@ -16,6 +18,7 @@ public class TemplateProcess
|
|||
UnaryOperator<Path> pathBuilder;
|
||||
String fileName;
|
||||
Set<String> parsePool = new HashSet<>();
|
||||
Map<String, Integer> parseValues = new HashMap<>();
|
||||
List<IMapper> mappers = new ArrayList<>();
|
||||
|
||||
public TemplateProcess(String fileName)
|
||||
|
@ -23,28 +26,45 @@ public class TemplateProcess
|
|||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public void setPathBuilder(UnaryOperator<Path> pathBuilder)
|
||||
public TemplateProcess setPathBuilder(UnaryOperator<Path> pathBuilder)
|
||||
{
|
||||
this.pathBuilder = pathBuilder;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void addFlags(String...flags)
|
||||
public TemplateProcess addFlags(String...flags)
|
||||
{
|
||||
parsePool.addAll(Arrays.asList(flags));
|
||||
return this;
|
||||
}
|
||||
|
||||
public void addFlags(Collection<String> flags)
|
||||
public TemplateProcess addFlags(Collection<String> flags)
|
||||
{
|
||||
parsePool.addAll(flags);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void addMapper(IMapper mapper)
|
||||
public TemplateProcess addValue(String key, int value)
|
||||
{
|
||||
parseValues.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TemplateProcess addValues(Map<String, Integer> values)
|
||||
{
|
||||
parseValues.putAll(values);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TemplateProcess addMapper(IMapper mapper)
|
||||
{
|
||||
mappers.add(mapper);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void addMappers(Collection<IMapper> mappers)
|
||||
public TemplateProcess addMappers(Collection<IMapper> mappers)
|
||||
{
|
||||
this.mappers.addAll(mappers);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.util.Set;
|
|||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -23,25 +24,79 @@ public abstract class TemplateProcessor
|
|||
Path sourceFolder;
|
||||
Path outputFolder;
|
||||
Path dataFolder;
|
||||
boolean silencedSuccess;
|
||||
boolean init = false;
|
||||
|
||||
public TemplateProcessor(Path sourceFolder, Path outputFolder, Path dataFolder)
|
||||
{
|
||||
this(false, sourceFolder, outputFolder, dataFolder);
|
||||
}
|
||||
|
||||
public TemplateProcessor(boolean silencedSuccess, Path sourceFolder, Path outputFolder, Path dataFolder)
|
||||
{
|
||||
this.silencedSuccess = silencedSuccess;
|
||||
this.sourceFolder = sourceFolder;
|
||||
this.outputFolder = outputFolder;
|
||||
this.dataFolder = dataFolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that is called before the initial run of the template processor.
|
||||
* It is only called once to basically initialize the program and then run as needed.
|
||||
*/
|
||||
protected abstract void init();
|
||||
|
||||
/**
|
||||
* Function that decides which file is going to be used and which not. Basically black/white list as needed
|
||||
* @param fileName FileName without folder structure. Since this is designed to have 0 duplicated file names.
|
||||
* @return true if it is valid to be processed or false if it isn't
|
||||
*/
|
||||
protected abstract boolean isFileValid(Path fileName);
|
||||
|
||||
/**
|
||||
* Main function that processes a filename to its target
|
||||
* @param fileName name of the file that should be processed without the type of file. (.template or .json etc etc)
|
||||
* @param process all modifications to the file that should be executed
|
||||
*/
|
||||
public abstract void createProcesses(String fileName, Consumer<TemplateProcess> process);
|
||||
|
||||
/**
|
||||
* Function that asks if the folder structure on the source folder should be kept or not
|
||||
* @return true if the source-structure should be kept or flattened.
|
||||
*/
|
||||
protected abstract boolean relativePackages();
|
||||
|
||||
/**
|
||||
* Function that tests if a Mapper was used or not. Useful for small scale projects that barely have any mappers
|
||||
* but sadly more like to cause not needed warnings for large scale projects.
|
||||
* @return true if it should be enabled
|
||||
*/
|
||||
protected abstract boolean debugUnusedMappers();
|
||||
|
||||
/**
|
||||
* Function called before the Template Processor runs.
|
||||
* But after init is called and All files are loaded in and the task queue is already ready.
|
||||
*/
|
||||
protected void beforeStart() {}
|
||||
|
||||
/**
|
||||
* Function that is called while the template generation is running and all after the File hashes for the memory are being generated.
|
||||
* If you have anything to do while the processor is running this would be the ideal time to do it.
|
||||
*/
|
||||
protected void whileProcessing() {}
|
||||
|
||||
/**
|
||||
* Function that is being called after the template processor is called and after the file cache has been updated
|
||||
* Basically just before "Saved Changes" is called.
|
||||
*/
|
||||
protected void afterFinish() {}
|
||||
|
||||
protected Path getSourceFolder() { return sourceFolder; }
|
||||
protected Path getOutputFolder() { return outputFolder; }
|
||||
protected Path getDataFolder() { return dataFolder; }
|
||||
protected boolean isSilencedSuccess() { return silencedSuccess; }
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public final boolean process(boolean force) throws IOException, InterruptedException
|
||||
{
|
||||
if(!init)
|
||||
|
@ -56,19 +111,24 @@ public abstract class TemplateProcessor
|
|||
System.out.println("Nothing has changed");
|
||||
return false;
|
||||
}
|
||||
AtomicLong[] counters = new AtomicLong[]{new AtomicLong(), new AtomicLong(), new AtomicLong()};
|
||||
final boolean relative = relativePackages();
|
||||
Set<IMapper>[] mappers = debugUnusedMappers() ? new Set[]{Collections.synchronizedSet(new HashSet<IMapper>()), Collections.synchronizedSet(new HashSet<IMapper>())} : null;
|
||||
Set<IMapper>[] mappers = debugUnusedMappers() ? new Set[]{Collections.synchronizedSet(new HashSet<>()), Collections.synchronizedSet(new HashSet<>())} : null;
|
||||
ThreadPoolExecutor service = (ThreadPoolExecutor)Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
|
||||
service.setKeepAliveTime(10, TimeUnit.MILLISECONDS);
|
||||
service.allowCoreThreadTimeOut(true);
|
||||
beforeStart();
|
||||
service.submit(() -> {
|
||||
for(int i = 0,m=pathsLeft.size();i<m;i++)
|
||||
{
|
||||
Path path = pathsLeft.get(i);
|
||||
try
|
||||
{
|
||||
long startTime = System.currentTimeMillis();
|
||||
Template template = Template.parse(path);
|
||||
createProcesses(FileUtils.getFileName(path), T -> service.execute(new BuildTask(relative ? outputFolder.resolve(sourceFolder.relativize(path).getParent()) : outputFolder, template, T, mappers)));
|
||||
counters[2].addAndGet(System.currentTimeMillis() - startTime);
|
||||
counters[1].addAndGet(1);
|
||||
createProcesses(FileUtils.getFileName(path), T -> {service.execute(new BuildTask(relative ? outputFolder.resolve(sourceFolder.relativize(path).getParent()) : outputFolder, template, T, silencedSuccess, mappers));counters[0].addAndGet(1);});
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
|
@ -83,6 +143,7 @@ public abstract class TemplateProcessor
|
|||
Path path = pathsLeft.get(i);
|
||||
existing.put(FileUtils.getFileName(path), FileUtils.getMD5String(path));
|
||||
}
|
||||
whileProcessing();
|
||||
while(service.getActiveCount() > 0)
|
||||
{
|
||||
Thread.sleep(10);
|
||||
|
@ -95,9 +156,10 @@ public abstract class TemplateProcessor
|
|||
System.out.println("Mapper ["+mapper.getSearchValue()+"] is not used in the Entire Build Process");
|
||||
}
|
||||
}
|
||||
System.out.println("Finished Tasks: "+(System.currentTimeMillis() - start)+"ms");
|
||||
System.out.println("Finished Building ["+counters[0].get()+"] Files from ["+counters[1].get()+"] in "+(System.currentTimeMillis() - start)+"ms (Template Parsing: "+counters[2].get()+"ms (avg: "+((counters[2].get() / Math.max(1D, counters[1].get())))+"ms)");
|
||||
FileUtils.saveMappings(existing, dataFolder);
|
||||
System.out.print("Saved Changes");
|
||||
afterFinish();
|
||||
System.out.println("Saved Changes");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
package example;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import speiger.src.builder.mappers.SimpleMapper;
|
||||
import speiger.src.builder.processor.TemplateProcess;
|
||||
import speiger.src.builder.processor.TemplateProcessor;
|
||||
|
||||
public class ExampleBuilder extends TemplateProcessor
|
||||
{
|
||||
|
||||
public static void main(String...args)
|
||||
{
|
||||
try
|
||||
{
|
||||
new ExampleBuilder().process(true);
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch(InterruptedException e)
|
||||
{
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public ExampleBuilder()
|
||||
{
|
||||
super(Paths.get("example/input"), Paths.get("example/output"), Paths.get("example"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isFileValid(Path fileName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createProcesses(String fileName, Consumer<TemplateProcess> process)
|
||||
{
|
||||
process.accept(new TemplateProcess(fileName+".txt").addFlags("TEST0").addMapper(new SimpleMapper("TESTING", "Test2")));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean relativePackages()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean debugUnusedMappers()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue