summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin J. Culkin <bjculkin@mix.wvu.edu>2019-06-11 22:28:51 -0300
committerBenjamin J. Culkin <bjculkin@mix.wvu.edu>2019-06-11 22:28:51 -0300
commiteba653d0d712e43676e28f93b7cba217cb56cecc (patch)
tree1d5849556c99a5bbcc955e217296e5fdf9f990e6
parent71c35c0ffba04e7c7932ffa06b9528b2a5efb48d (diff)
Initial commit p2
The rest of the files, for initial upload to github
-rw-r--r--.gitignore1
-rw-r--r--README.md7
-rw-r--r--data/test/test1.rp0
-rw-r--r--data/test/test2.rp2
-rw-r--r--data/test/test3.rp8
-rw-r--r--data/test/test4.rp11
-rw-r--r--data/test/test5.rp11
-rw-r--r--pom.xml139
-rw-r--r--src/main/java/bjc/replpair/App.java13
-rw-r--r--src/main/java/bjc/replpair/ReplError.java56
-rw-r--r--src/main/java/bjc/replpair/ReplPair.java531
-rw-r--r--src/main/java/bjc/replpair/StageStatus.java21
-rw-r--r--src/test/java/bjc/replpair/AppTest.java20
-rw-r--r--src/test/java/bjc/replpair/ReplPairTest.java104
14 files changed, 825 insertions, 99 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2f7896d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+target/
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d148335
--- /dev/null
+++ b/README.md
@@ -0,0 +1,7 @@
+Everge
+======
+
+Everge is a simple regex-based text macro tool written in Java.
+
+Currently, there is no end-user based interface, but the code should be easy
+enough to figure out.
diff --git a/data/test/test1.rp b/data/test/test1.rp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/data/test/test1.rp
diff --git a/data/test/test2.rp b/data/test/test2.rp
new file mode 100644
index 0000000..bae42c5
--- /dev/null
+++ b/data/test/test2.rp
@@ -0,0 +1,2 @@
+test1
+test2
diff --git a/data/test/test3.rp b/data/test/test3.rp
new file mode 100644
index 0000000..cfddebb
--- /dev/null
+++ b/data/test/test3.rp
@@ -0,0 +1,8 @@
+a
+A
+
+b
+B
+
+c
+C
diff --git a/data/test/test4.rp b/data/test/test4.rp
new file mode 100644
index 0000000..58ffbf1
--- /dev/null
+++ b/data/test/test4.rp
@@ -0,0 +1,11 @@
+ab
+d
+
+a
+b
+
+b
+c
+
+c
+a
diff --git a/data/test/test5.rp b/data/test/test5.rp
new file mode 100644
index 0000000..72abd4a
--- /dev/null
+++ b/data/test/test5.rp
@@ -0,0 +1,11 @@
+//p/-1//ab
+d
+
+a
+b
+
+b
+c
+
+c
+a
diff --git a/pom.xml b/pom.xml
index b152aa3..bb04278 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,75 +1,82 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
- <groupId>bjc</groupId>
- <artifactId>replpair</artifactId>
- <version>1.0-SNAPSHOT</version>
+ <groupId>bjc</groupId>
+ <artifactId>everge</artifactId>
+ <version>1.0-SNAPSHOT</version>
- <name>replpair</name>
- <!-- FIXME change it to the project's website -->
- <url>http://www.example.com</url>
+ <name>everge</name>
+ <url>http://www.github.com/bculkin2442/everge</url>
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <maven.compiler.source>1.7</maven.compiler.source>
- <maven.compiler.target>1.7</maven.compiler.target>
- </properties>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <maven.compiler.source>1.8</maven.compiler.source>
+ <maven.compiler.target>1.8</maven.compiler.target>
+ </properties>
- <dependencies>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.11</version>
- <scope>test</scope>
- </dependency>
- </dependencies>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.11</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
- <build>
- <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
- <plugins>
- <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
- <plugin>
- <artifactId>maven-clean-plugin</artifactId>
- <version>3.1.0</version>
- </plugin>
- <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
- <plugin>
- <artifactId>maven-resources-plugin</artifactId>
- <version>3.0.2</version>
- </plugin>
- <plugin>
- <artifactId>maven-compiler-plugin</artifactId>
- <version>3.8.0</version>
- </plugin>
- <plugin>
- <artifactId>maven-surefire-plugin</artifactId>
- <version>2.22.1</version>
- </plugin>
- <plugin>
- <artifactId>maven-jar-plugin</artifactId>
- <version>3.0.2</version>
- </plugin>
- <plugin>
- <artifactId>maven-install-plugin</artifactId>
- <version>2.5.2</version>
- </plugin>
- <plugin>
- <artifactId>maven-deploy-plugin</artifactId>
- <version>2.8.2</version>
- </plugin>
- <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
- <plugin>
- <artifactId>maven-site-plugin</artifactId>
- <version>3.7.1</version>
- </plugin>
- <plugin>
- <artifactId>maven-project-info-reports-plugin</artifactId>
- <version>3.0.0</version>
- </plugin>
- </plugins>
- </pluginManagement>
- </build>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <version>3.1.0</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>3.0.2</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.8.0</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.22.1</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>3.0.2</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-install-plugin</artifactId>
+ <version>2.5.2</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <version>2.8.2</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-site-plugin</artifactId>
+ <version>3.7.1</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-project-info-reports-plugin</artifactId>
+ <version>3.0.0</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+
+ <resources>
+ <resource>
+ <directory>data/</directory>
+
+ <includes>
+ <include>**/*.rp</include>
+ <include>**/*.txt</include>
+ </includes>
+ </resource>
+ </resources>
+ </build>
</project>
diff --git a/src/main/java/bjc/replpair/App.java b/src/main/java/bjc/replpair/App.java
deleted file mode 100644
index 22fe770..0000000
--- a/src/main/java/bjc/replpair/App.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package bjc.replpair;
-
-/**
- * Hello world!
- *
- */
-public class App
-{
- public static void main( String[] args )
- {
- System.out.println( "Hello World!" );
- }
-}
diff --git a/src/main/java/bjc/replpair/ReplError.java b/src/main/java/bjc/replpair/ReplError.java
new file mode 100644
index 0000000..9d0fe02
--- /dev/null
+++ b/src/main/java/bjc/replpair/ReplError.java
@@ -0,0 +1,56 @@
+package bjc.replpair;
+
+/**
+ * Represents an error encountered parsing ReplPairs
+ *
+ * @author Ben Culkin
+ */
+public class ReplError {
+ /**
+ * The line the error occured on.
+ */
+ public int line;
+ /**
+ * The number of pairs we have processed so far.
+ */
+ public int numPairs;
+
+ /**
+ * The text of the line we errored on.
+ */
+ public String txt;
+ /**
+ * The message of the error.
+ */
+ public String msg;
+
+ /**
+ * Create a new ReplPair parse error.
+ *
+ * @param lne
+ * The line the error occured on.
+ * @param nPairs
+ * The number of pairs processed up to this point.
+ * @param msg
+ * The message detailing the error.
+ * @param txt
+ * The text that caused the error.
+ */
+ public ReplError(int lne, int nPairs, String msg, String txt) {
+ line = lne;
+ numPairs = nPairs;
+
+ this.txt = txt;
+ this.msg = msg;
+ }
+
+ @Override
+ public String toString() {
+ String errString;
+ if (txt == null) errString = "No associated line";
+ else if (txt.equals("")) errString = "Text of line was empty";
+ else errString = "Text of line was: " + txt;
+
+ return String.format("line %d, pair %d:%s\n\t%s", line, numPairs, msg, errString);
+ }
+}
diff --git a/src/main/java/bjc/replpair/ReplPair.java b/src/main/java/bjc/replpair/ReplPair.java
new file mode 100644
index 0000000..14ecb49
--- /dev/null
+++ b/src/main/java/bjc/replpair/ReplPair.java
@@ -0,0 +1,531 @@
+package bjc.replpair;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
+import java.util.function.UnaryOperator;
+
+/**
+ * String pairs for replacements.
+ *
+ * @author Ben Culkin
+ */
+public class ReplPair implements Comparable<ReplPair>, UnaryOperator<String> {
+ private int lno;
+
+ /**
+ * The priority for this replacement.
+ */
+ public int priority;
+
+ /**
+ * The name of this replacement.
+ *
+ * Defaults to the 'find' string.
+ */
+ public String name;
+ /**
+ * The string to look for.
+ */
+ public String find;
+
+ /**
+ * The string to replace it with.
+ */
+ public String replace;
+
+ private StageStatus stat = StageStatus.BOTH;
+
+ /**
+ * Create a new blank replacement pair.
+ */
+ public ReplPair() {
+ this("", "", 1, null);
+ }
+
+ /**
+ * Create a new replacement pair with a priority of 1.
+ *
+ * @param f
+ * The string to find.
+ * @param r
+ * The string to replace.
+ */
+ public ReplPair(String f, String r) {
+ this(f, r, 1);
+ }
+
+ /**
+ * Create a new named replacement pair with a priority of 1.
+ *
+ * @param f
+ * The string to find.
+ * @param r
+ * The string to replace.
+ * @param n
+ * The name of the replacement pair.
+ */
+ public ReplPair(String f, String r, String n) {
+ this(f, r, 1, n);
+ }
+
+ /**
+ * Create a new replacement pair with a set priority.
+ *
+ * @param f
+ * The string to find.
+ * @param r
+ * The string to replace.
+ * @param p
+ * The priority for the replacement.
+ */
+ public ReplPair(String f, String r, int p) {
+ this(f, r, p, f);
+ }
+
+ /**
+ * Create a new replacement pair with a set priority and name.
+ *
+ * @param f
+ * The string to find.
+ * @param r
+ * The string to replace.
+ * @param n
+ * The name of the replacement pair.
+ * @param p
+ * The priority for the replacement.
+ */
+ public ReplPair(String f, String r, int p, String n) {
+ find = f;
+ replace = r;
+
+ name = n;
+
+ priority = p;
+ }
+ /**
+ * Read a list of replacement pairs from an input source.
+ *
+ * @param scn
+ * The source to read the replacements from.
+ * @return
+ * The list of replacements.
+ */
+ public static List<ReplPair> readList(Scanner scn) {
+ List<ReplPair> lst = new ArrayList<>();
+
+ return readList(lst, scn);
+ }
+
+ /**
+ * Read a list of replacement pairs from an input source, adding them to
+ * an existing list.
+ *
+ * @param detals
+ * The list to add the replacements to.
+ * @param scn
+ * The source to read the replacements from.
+ * @return
+ * The list of replacements.
+ */
+ public static List<ReplPair> readList(List<ReplPair> detals, Scanner scn) {
+ List<ReplError> errList = new ArrayList<>();
+
+ List<ReplPair> rplPar = readList(detals, scn, errList);
+
+ if (errList.size() != 0) {
+ String errString;
+ if (errList.size() == 0) errString = "An error";
+ else errString = "Errors";
+
+ throw new IllegalArgumentException(String.format("%s occured parsing replacement pairs:\n%s", errString, errList));
+ }
+
+ return rplPar;
+ }
+
+ /**
+ * Read a list of replacement pairs from an input source, adding them to
+ * an existing list.
+ *
+ * @param detals
+ * The list to add the replacements to.
+ * @param scn
+ * The source to read the replacements from.
+ * @param errs
+ * The list to stick errors in.
+ * @return
+ * The list of replacements.
+ */
+ public static List<ReplPair> readList(List<ReplPair> detals, Scanner scn, List<ReplError> errs) {
+ int lno = 0;
+ int pno = 0;
+
+ int defPrior = 1;
+ int defStage = 1;
+
+ boolean defMulti = false;
+
+ StageStatus defStatus = StageStatus.BOTH;
+
+ List<List<ReplPair>> stages = new ArrayList<>();
+ stages.add(new ArrayList<ReplPair>());
+
+ // For every line in the source...
+ while (scn.hasNextLine()) {
+ String name = scn.nextLine().trim();
+ lno += 1;
+
+ // If its commented or blank, skip it
+ if (name.equals("")) continue;
+ if (name.startsWith("#")) continue;
+
+ // Global control. Process it.
+ if (name.startsWith("|//")) {
+ name = name.substring(3);
+
+ // Split out each control
+ String[] bits = name.split(";");
+
+ for (String bit : bits) {
+ String bitHead = bit.toUpperCase();
+ String bitBody = bit;
+
+ int idx = bit.indexOf('/');
+ if (idx != -1) {
+ bitHead = bit.substring(0, idx).toUpperCase();
+ bitBody = bit.substring(idx + 1);
+ }
+
+ switch (bitHead) {
+ case "P":
+ try {
+ defPrior = Integer.parseInt(bitBody);
+ } catch (NumberFormatException nfex) {
+ String errMsg = String.format("'%s' is not a valid priority (must be an integer)", bitBody);
+ errs.add(new ReplError(lno, pno, errMsg, name));
+ }
+ break;
+ case "S":
+ try {
+ int tmpStage = Integer.parseInt(bitBody);
+ if (tmpStage < 0) {
+ String errMsg = String.format("'%s' is not a valid stage (must be a positive integer)", bitBody);
+ errs.add(new ReplError(lno, pno, errMsg, name));
+
+ break;
+ }
+ defStage = tmpStage;
+ } catch (NumberFormatException nfex) {
+ String errMsg = String.format("'%s' is not a valid stage (must be a positive integer)", bitBody);
+ errs.add(new ReplError(lno, pno, errMsg, name));
+ }
+ break;
+ case "MT":
+ defMulti = true;
+ break;
+ case "MF":
+ defMulti = false;
+ break;
+ case "M":
+ defMulti = Boolean.parseBoolean(bitBody);
+ break;
+ case "I":
+ defStatus = StageStatus.INTERNAL;
+ break;
+ case "E":
+ defStatus = StageStatus.EXTERNAL;
+ break;
+ case "B":
+ defStatus = StageStatus.BOTH;
+ break;
+ default:
+ errs.add(new ReplError(lno, pno, String.format("Invalid control name '%s'", bitHead), name));
+ break;
+ }
+ }
+
+ continue;
+ }
+
+ ReplPair rp = new ReplPair();
+ rp.priority = defPrior;
+ rp.stat = defStatus;
+ rp.lno = lno;
+
+ int stage = defStage;
+
+ boolean isMulti = defMulti;
+
+ // Name has attached controls, process them.
+ if (name.startsWith("//")) {
+ name = name.substring(2);
+
+ int idx = name.indexOf("//");
+ if (idx == -1) {
+ String msg = "Did not find control terminator (//) in name where it should be";
+
+ errs.add(new ReplError(lno, pno, msg, name));
+ continue;
+ }
+
+ String contName = name.substring(0, idx);
+ String actName = name.substring(idx + 2);
+
+ // Split out each control
+ String[] bits = contName.split(";");
+
+ for (String bit : bits) {
+ String bitHead = bit.toUpperCase();
+ String bitBody = bit;
+
+ idx = bit.indexOf('/');
+ if (idx != -1) {
+ bitHead = bit.substring(0, idx).toUpperCase();
+ bitBody = bit.substring(idx + 1);
+ }
+
+ switch (bitHead) {
+ case "N":
+ rp.name = bitBody;
+ break;
+ case "P":
+ try {
+ rp.priority = Integer.parseInt(bitBody);
+ } catch (NumberFormatException nfex) {
+ String errMsg = String.format("'%s' is not a valid priority (must be an integer)", bitBody);
+ errs.add(new ReplError(lno, pno, errMsg, name));
+ }
+ break;
+ case "S":
+ try {
+ int tmpStage = Integer.parseInt(bitBody);
+ if (tmpStage < 0) {
+ String errMsg = String.format("'%s' is not a valid stage (must be a positive integer)", bitBody);
+ errs.add(new ReplError(lno, pno, errMsg, name));
+
+ break;
+ }
+ stage = tmpStage;
+ } catch (NumberFormatException nfex) {
+ String errMsg = String.format("'%s' is not a valid stage (must be a positive integer)", bitBody);
+ errs.add(new ReplError(lno, pno, errMsg, name));
+ }
+ break;
+ case "MT":
+ isMulti = true;
+ break;
+ case "MF":
+ isMulti = false;
+ break;
+ case "M":
+ isMulti = Boolean.parseBoolean(bitBody);
+ break;
+ case "I":
+ rp.stat = StageStatus.INTERNAL;
+ break;
+ case "E":
+ rp.stat = StageStatus.EXTERNAL;
+ break;
+ case "B":
+ rp.stat = StageStatus.BOTH;
+ break;
+ default:
+ errs.add(new ReplError(lno, pno, String.format("Unknown control name '%s'", bitHead), name));
+ break;
+ }
+ }
+
+ // Multi-line name with a trailer
+ if (isMulti) {
+ String tmp = actName;
+
+ while (tmp.endsWith("\\")) {
+ boolean incNL = tmp.endsWith("|\\");
+
+ if (!scn.hasNextLine()) break;
+
+ tmp = scn.nextLine().trim();
+
+ if (tmp.equals("")) continue;
+ if (tmp.startsWith("#")) continue;
+
+ actName = String.format("%s%s%s", actName, incNL ? "\n" : "", tmp);
+ }
+ }
+
+ name = actName;
+ }
+
+ rp.find = name;
+ if (rp.name == null) rp.name = name;
+
+ // We started to process the pair, mark it as being
+ // started
+ pno += 1;
+ String body = null;
+
+ // Read in the next uncommented line
+ do {
+ if (!scn.hasNextLine()) {
+ String msg =
+ "Ran out of input looking for replacement body for raw name " + name;
+
+ errs.add(new ReplError(lno, pno, msg, null));
+ break;
+ }
+
+ body = scn.nextLine().trim();
+ lno += 1;
+ } while (body.startsWith("#"));
+
+ isMulti = defMulti;
+
+ // Body has attached controls, process them.
+ if (body.startsWith("//")) {
+ body = body.substring(2);
+
+ int idx = body.indexOf("//");
+ if (idx == -1) {
+ String msg = "Did not find control terminator (//) in body where it should be";
+
+ errs.add(new ReplError(lno, pno, msg, body));
+ continue;
+ }
+
+ String contBody = body.substring(0, idx);
+ String actBody = body.substring(idx + 2);
+
+ // Split out each control
+ String[] bits = actBody.split(";");
+
+ for (String bit : bits) {
+ String bitHead = bit.toUpperCase();
+ String bitBody = bit;
+
+ idx = bit.indexOf('/');
+ if (idx != -1) {
+ bitHead = bit.substring(0, idx).toUpperCase();
+ bitBody = bit.substring(idx + 1);
+ }
+
+ switch (bitHead) {
+ case "MT":
+ isMulti = true;
+ break;
+ case "MF":
+ isMulti = false;
+ break;
+ case "M":
+ isMulti = Boolean.parseBoolean(bitBody);
+ break;
+ default:
+ errs.add(new ReplError(lno, pno, String.format("Invalid control name '%s'", bitHead), body));
+ break;
+ }
+ }
+
+ // Multi-line name with a trailer
+ if (isMulti) {
+ String tmp = actBody;
+
+ while (tmp.endsWith("\\")) {
+ boolean incNL = tmp.endsWith("|\\");
+
+ if (!scn.hasNextLine()) break;
+
+ tmp = scn.nextLine().trim();
+
+ if (tmp.startsWith("#")) continue;
+
+ actBody = String.format("%s%s%s", actBody, incNL ? "\n" : "", tmp);
+ }
+ }
+
+ body = actBody;
+ }
+
+ rp.replace = body;
+
+ List<ReplPair> stageList;
+ if (stages.size() < stage) {
+ stageList = stages.get(stage);
+
+ if (stageList == null) {
+ stageList = new ArrayList<>();
+ stages.add(stage, stageList);
+ }
+ } else {
+ stageList = new ArrayList<>();
+ stages.add(stage, stageList);
+ }
+
+ stageList.add(rp);
+ }
+
+ // Special-case one-stage processing.
+ if (stages.size() == 1) {
+ detals.addAll(stages.iterator().next());
+
+ detals.sort(null);
+
+ return detals;
+ }
+
+ // Handle stages
+ List<ReplPair> tmpList = new ArrayList<>();
+ tmpList.addAll(detals);
+
+ for (List<ReplPair> stageList : stages) {
+ List<ReplPair> curStage = new ArrayList<>();
+
+ for (ReplPair rp : stageList) {
+ // Process through every pair in the previous
+ // stages
+ for (ReplPair curPar : tmpList) {
+ rp.replace = rp.replace.replaceAll(curPar.find, curPar.replace);
+ }
+
+ // If we're external; add straight to the output
+ if (rp.stat == StageStatus.EXTERNAL) detals.add(rp);
+ else curStage.add(rp);
+ }
+
+ tmpList.addAll(curStage);
+ tmpList.sort(null);
+ }
+
+ // Copy over to output, excluding internals
+ for (ReplPair rp : tmpList) {
+ if (rp.stat == StageStatus.INTERNAL) continue;
+
+ detals.add(rp);
+ }
+
+ detals.sort(null);
+
+ return detals;
+ }
+
+ @Override
+ public String apply(String inp) {
+ return inp.replaceAll(find, replace);
+ }
+
+ @Override
+ public String toString() {
+ String nameStr = "";
+
+ if (!find.equals(name)) nameStr = String.format("(%s)", name);
+
+ return String.format("%ss/%s/%s/p(%d)", nameStr, find, replace, priority);
+ }
+
+ @Override
+ public int compareTo(ReplPair rp) {
+ if (this.priority == rp.priority) return this.lno - rp.lno;
+
+ return rp.priority - this.priority;
+ }
+}
diff --git a/src/main/java/bjc/replpair/StageStatus.java b/src/main/java/bjc/replpair/StageStatus.java
new file mode 100644
index 0000000..2dd3c74
--- /dev/null
+++ b/src/main/java/bjc/replpair/StageStatus.java
@@ -0,0 +1,21 @@
+package bjc.replpair;
+
+/**
+ * Possible statuses of pairs with respect to exporting.
+ * @author Ben Culkin
+ */
+public enum StageStatus {
+ /**
+ * Only use for staging pairs; don't export.
+ */
+ INTERNAL,
+ /**
+ * Don't use for staging pairs; do export.
+ */
+ EXTERNAL,
+ /**
+ * Use for staging pairs; do export.
+ */
+ BOTH;
+}
+
diff --git a/src/test/java/bjc/replpair/AppTest.java b/src/test/java/bjc/replpair/AppTest.java
deleted file mode 100644
index a81acfd..0000000
--- a/src/test/java/bjc/replpair/AppTest.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package bjc.replpair;
-
-import static org.junit.Assert.assertTrue;
-
-import org.junit.Test;
-
-/**
- * Unit test for simple App.
- */
-public class AppTest
-{
- /**
- * Rigorous Test :-)
- */
- @Test
- public void shouldAnswerWithTrue()
- {
- assertTrue( true );
- }
-}
diff --git a/src/test/java/bjc/replpair/ReplPairTest.java b/src/test/java/bjc/replpair/ReplPairTest.java
new file mode 100644
index 0000000..4ce918f
--- /dev/null
+++ b/src/test/java/bjc/replpair/ReplPairTest.java
@@ -0,0 +1,104 @@
+package bjc.replpair;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+
+import java.util.List;
+import java.util.Scanner;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+/**
+ * Unit test for ReplPair.
+ *
+ * @author Ben Culkin
+ */
+public class ReplPairTest {
+ // Test that we load empty files fine
+ @Test
+ public void testLoadFile() {
+ List<ReplPair> lrp = null;
+ String fName = "data/test/test1.rp";
+
+ try (FileInputStream fis = new FileInputStream(fName); Scanner scn = new Scanner(fis)) {
+ lrp = ReplPair.readList(scn);
+
+ assertTrue(lrp.size() == 0);
+ } catch (IOException ioex) {
+ assertTrue(false);
+ }
+ }
+
+ @Test
+ public void testSingleReplace() {
+ assertMultiReplace("data/test/test2.rp", "test2", "test1", "test2", "test2");
+ }
+
+ @Test
+ public void testMultiReplace() {
+ assertMultiReplace("data/test/test3.rp", "A B C", "a b c", "A A B", "a a b", "AAB", "aab");
+ }
+
+ @Test
+ public void testReplaceOrder() {
+ assertMultiReplace("data/test/test4.rp", "a", "a", "d", "ab");
+ }
+
+ @Test
+ public void testReplaceExpOrder() {
+ assertMultiReplace("data/test/test5.rp", "a", "a", "aa", "ab");
+ }
+
+ private void assertMultiReplace(String fle, String... inps) {
+ assertMultiReplace(false, fle, inps);
+ }
+
+ private void assertMultiReplace(boolean logRep, String fle, String... inps) {
+ if (inps.length < 2) throw new IllegalArgumentException("ERROR: Must provide at least two strings to assertMultiReplace");
+ if (inps.length % 2 != 0) throw new IllegalArgumentException("ERROR: Odd number of strings passed to assertMultiReplace");
+
+ List<ReplPair> lrp = null;
+
+ try (FileInputStream fis = new FileInputStream(fle); Scanner scn = new Scanner(fis)) {
+ lrp = ReplPair.readList(scn);
+ } catch (Exception ex) {
+ System.err.println("EXCEPTION");
+ ex.printStackTrace();
+
+ assertTrue(false);
+
+ return;
+ }
+
+ for (int i = 0; i < inps.length; i += 2) {
+ String right = inps[i];
+ String inp = inps[i + 1];
+
+ assertReplacesTo(logRep, right, lrp, inp);
+ }
+ }
+
+ private void assertReplacesFrom(String right, String inp, String fle) {
+ assertMultiReplace(fle, right, inp);
+ }
+
+ private void assertReplacesTo(String right, List<ReplPair> rps, String inp) {
+ assertReplacesTo(false, right, rps, inp);
+ }
+
+ private void assertReplacesTo(boolean logRep, String right, List<ReplPair> rps, String inp) {
+ String tmp = inp;
+
+ for (ReplPair rp : rps) {
+ String oldTmp = tmp;
+
+ tmp = rp.apply(tmp);
+
+ if (logRep) System.err.printf("\t[LOG] '%s' -> '%s'\t%s\n", oldTmp, tmp, rp);
+ }
+
+ assertEquals(right, tmp);
+ }
+}