Compare commits
18 Commits
Author | SHA1 | Date | |
---|---|---|---|
d5a47ce568 | |||
d90a9ad71c | |||
b0792532b1 | |||
a63defacbb | |||
6e5e91d0bd | |||
b60f4ff1fd | |||
2fe297b708 | |||
9c4c33c1eb | |||
4a72afdb1c | |||
d4e3da23fa | |||
d3d1cb48b6 | |||
b979e9d9e8 | |||
6f3f45d718 | |||
8937d44428 | |||
b165524c36 | |||
9aedebd317 | |||
c50e022ec2 | |||
54e66d7f53 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -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
|
||||
|
2
.settings/org.eclipse.core.resources.prefs
Normal file
2
.settings/org.eclipse.core.resources.prefs
Normal file
@ -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
|
||||
|
||||
|
77
build.gradle
77
build.gradle
@ -1,24 +1,55 @@
|
||||
apply plugin: 'java-library'
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
|
||||
archivesBaseName = 'Simple Code Generator'
|
||||
version = '1.0.1'
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
options.encoding = 'UTF-8'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
}
|
||||
|
||||
task srcJar(type: Jar) {
|
||||
from sourceSets.main.allSource
|
||||
classifier = 'sources'
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives srcJar
|
||||
apply plugin: 'java-library'
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
|
||||
archivesBaseName = 'Simple Code Generator'
|
||||
version = '1.3.0'
|
||||
apply plugin: 'maven'
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
options.encoding = 'UTF-8'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
}
|
||||
|
||||
task srcJar(type: Jar) {
|
||||
from sourceSets.main.allSource
|
||||
classifier = 'sources'
|
||||
}
|
||||
|
||||
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'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1
example/cache.bin
Normal file
1
example/cache.bin
Normal file
@ -0,0 +1 @@
|
||||
test=ddb9367ebd61888ab31a658dd6f6df86
|
53
example/input/test.template
Normal file
53
example/input/test.template
Normal file
@ -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
|
41
example/output/test.txt
Normal file
41
example/output/test.txt
Normal file
@ -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");
|
||||
}
|
||||
}
|
||||
|
18
src/main/java/speiger/src/builder/base/PostSegment.java
Normal file
18
src/main/java/speiger/src/builder/base/PostSegment.java
Normal file
@ -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;
|
||||
}
|
||||
|
61
src/main/java/speiger/src/builder/base/SegmentIterator.java
Normal file
61
src/main/java/speiger/src/builder/base/SegmentIterator.java
Normal file
@ -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 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);
|
||||
public boolean isValid(CompiledArguments args);
|
||||
|
||||
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;
|
||||
}
|
||||
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,22 +49,34 @@ public class ArgumentMapper implements IMapper
|
||||
@Override
|
||||
public String apply(String t)
|
||||
{
|
||||
Matcher matcher = pattern.matcher(t);
|
||||
if(matcher.find())
|
||||
RegexMatcher matcher = new RegexMatcher(pattern, t);
|
||||
try
|
||||
{
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
do
|
||||
if(matcher.find())
|
||||
{
|
||||
String text = RegexUtil.searchUntil(t, matcher.end()-1, braces.charAt(0), braces.charAt(1));
|
||||
if(!text.isEmpty())
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
do
|
||||
{
|
||||
RegexUtil.skip(matcher.appendReplacement(buffer, ""), text.length());
|
||||
buffer.append(String.format(replacement, (Object[])getString(text).split(argumentBreaker)));
|
||||
String text = RegexUtil.searchUntil(t, matcher.end()-1, braces.charAt(0), braces.charAt(1));
|
||||
if(!text.isEmpty())
|
||||
{
|
||||
matcher.appendReplacement(buffer, "").skip(text.length());
|
||||
buffer.append(String.format(replacement, (Object[])getString(text).split(argumentBreaker)));
|
||||
}
|
||||
}
|
||||
while(matcher.find());
|
||||
matcher.appendTail(buffer);
|
||||
return apply(buffer.toString());
|
||||
}
|
||||
while(matcher.find());
|
||||
matcher.appendTail(buffer);
|
||||
return 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,21 +47,33 @@ public class InjectMapper implements IMapper
|
||||
@Override
|
||||
public String apply(String t)
|
||||
{
|
||||
Matcher matcher = pattern.matcher(t);
|
||||
if(matcher.find())
|
||||
RegexMatcher matcher = new RegexMatcher(pattern, t);
|
||||
try
|
||||
{
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
do
|
||||
if(matcher.find())
|
||||
{
|
||||
String text = RegexUtil.searchUntil(t, matcher.end()-1, braces.charAt(0), braces.charAt(1));
|
||||
if(!text.isEmpty())
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
do
|
||||
{
|
||||
RegexUtil.skip(matcher.appendReplacement(buffer, ""), text.length());
|
||||
buffer.append(String.format(replacement, getString(text)));
|
||||
}
|
||||
} while (matcher.find());
|
||||
matcher.appendTail(buffer);
|
||||
return buffer.toString();
|
||||
String text = RegexUtil.searchUntil(t, matcher.end()-1, braces.charAt(0), braces.charAt(1));
|
||||
if(!text.isEmpty())
|
||||
{
|
||||
matcher.appendReplacement(buffer, "").skip(text.length());
|
||||
buffer.append(String.format(replacement, getString(text)));
|
||||
}
|
||||
} while (matcher.find());
|
||||
matcher.appendTail(buffer);
|
||||
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,23 +30,35 @@ public class LineMapper implements IMapper
|
||||
@Override
|
||||
public String apply(String t)
|
||||
{
|
||||
Matcher matcher = pattern.matcher(t);
|
||||
if(matcher.find())
|
||||
RegexMatcher matcher = new RegexMatcher(pattern, t);
|
||||
try
|
||||
{
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
do
|
||||
if(matcher.find())
|
||||
{
|
||||
int start = matcher.end() - 1;
|
||||
int[] result = RegexUtil.findFullLine(t, start);
|
||||
if(result != null)
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
do
|
||||
{
|
||||
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();
|
||||
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]));
|
||||
matcher.skip(result[1] - start);
|
||||
}
|
||||
} while (matcher.find());
|
||||
matcher.appendTail(buffer);
|
||||
return apply(buffer.toString());
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch(Error error)
|
||||
{
|
||||
System.out.println("Error with ["+pattern.pattern()+"] pattern");
|
||||
throw error;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
@ -29,6 +29,19 @@ public class SimpleMapper implements IMapper
|
||||
@Override
|
||||
public String apply(String t)
|
||||
{
|
||||
return pattern.matcher(t).replaceAll(replacement);
|
||||
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();
|
||||
|
18
src/main/java/speiger/src/builder/misc/IdGenerator.java
Normal file
18
src/main/java/speiger/src/builder/misc/IdGenerator.java
Normal file
@ -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";
|
||||
}
|
||||
}
|
84
src/main/java/speiger/src/builder/misc/RegexMatcher.java
Normal file
84
src/main/java/speiger/src/builder/misc/RegexMatcher.java
Normal file
@ -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()
|
||||