Skip to content

Commit 481c2ba

Browse files
Replace
Updated the Replace class to work relative to the placement of the REPLACE statements in the COBOL code.
1 parent b8501d9 commit 481c2ba

File tree

6 files changed

+254
-56
lines changed

6 files changed

+254
-56
lines changed

src/main/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/Replace.java

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
import org.openmainframeproject.cobolcheck.services.log.LogLevel;
55

66
import java.io.*;
7-
import java.util.HashMap;
8-
import java.util.Iterator;
97
import java.util.LinkedList;
108
import java.util.regex.Matcher;
119
import java.util.regex.Pattern;
@@ -60,9 +58,10 @@ public class Replace {
6058
* Looks in the source line for the replace-key and replaces is with the replace-to-value.
6159
*
6260
* @param source a line of cobol-check unit test code
61+
* @param lineNumber the line number of the source line
6362
* @return the source line there the appropriate replacement has been made
6463
*/
65-
public static String replace(String source) {
64+
public static String replace(String source, int lineNumber) {
6665
if (!inspect_performed) {
6766
if (!inspect_performed_warned) {
6867
inspect_performed_warned = true;
@@ -86,14 +85,18 @@ public static String replace(String source) {
8685

8786
for (ReplaceSet replaceSet : replaceMap) {
8887
Log.trace("Replace.replace(): Key: <" + replaceSet.getFrom() + ">, Value: <" + replaceSet.getTo() + ">");
89-
replacesString = replaceSet.replaceInline(replacesString);
88+
replacesString = replaceSet.replaceInline(replacesString, lineNumber);
9089
if ((Log.level() == LogLevel.TRACE) && (!replacesString.equals(source))) {
9190
Log.trace("Replace.replace(): Key: <" + replaceSet.getFrom() + ">, result: " + replacesString);
9291
}
9392
}
9493
return replacesString;
9594
}
9695

96+
public static String replace(String source) {
97+
return replace(source, 0);
98+
}
99+
97100

98101
public static void inspectProgram(File cobolProgram) {
99102
Log.trace("Replace.inspectProgram(): Inspecting the COBOL program file: " + cobolProgram);
@@ -152,4 +155,34 @@ private static void reset() {
152155
inspect_performed = false;
153156
inspect_performed_warned = false;
154157
}
158+
159+
public static String replaceInProgram(File program) {
160+
// write the replaced program back to disk
161+
162+
String newFileName = program+"_MOD";
163+
Log.warn("Replace.replaceInProgram(): Writing the COBOL program file: " + newFileName);
164+
try {
165+
BufferedWriter writer = new BufferedWriter(new FileWriter(newFileName));
166+
// read the program one line at the time
167+
BufferedReader reader = new BufferedReader(new FileReader(program));
168+
//for every line in the program, replace and write to output file
169+
String line;
170+
int lineCount = 0;
171+
while ((line = reader.readLine()) != null) {
172+
writer.write(Replace.replace(line, lineCount++));
173+
writer.newLine();
174+
}
175+
writer.close();
176+
reader.close();
177+
} catch (IOException e) {
178+
Log.error("Replace.replaceInProgram(): Error writing the COBOL program file: " + program);
179+
}
180+
return newFileName;
181+
}
182+
183+
public static void showReplaceSets() {
184+
for (ReplaceSet replaceSet : replaceMap) {
185+
Log.info("Replace.showReplaceSets():" + replaceSet.toString());
186+
}
187+
}
155188
}

src/main/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/ReplaceSet.java

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,21 @@
44
import java.util.regex.Matcher;
55
import java.util.regex.Pattern;
66

7+
/**
8+
* Class to handle the COBOL REPLACE statement keys on the test suite/test case source code.
9+
* <p>
10+
* When fromSourceLine and untilSourceLine are set, the replace is only performed on the lines between these two lines.
11+
* When the values are zero, the replace key set is applied to all lines.
12+
*/
713
public class ReplaceSet {
814
private String from;
915
private String to;
1016
private boolean trailing;
1117
private boolean leading;
18+
private int fromSourceLine;
19+
private int untilSourceLine;
1220

13-
public ReplaceSet(String from, String to, boolean trailing, boolean leading) {
21+
public ReplaceSet(String from, String to, boolean trailing, boolean leading,int fromSourceLine, int untilSourceLine) {
1422
if (trailing && leading) {
1523
throw new IllegalArgumentException("Cannot have both trailing and leading set to true");
1624
}
@@ -19,17 +27,21 @@ public ReplaceSet(String from, String to, boolean trailing, boolean leading) {
1927
this.to = to;
2028
this.trailing = trailing;
2129
this.leading = leading;
30+
this.fromSourceLine = fromSourceLine;
31+
this.untilSourceLine = untilSourceLine;
2232
}
2333

2434
public ReplaceSet() {
2535
this.from = "";
2636
this.to = "";
2737
this.trailing = false;
2838
this.leading = false;
39+
this.fromSourceLine = 0;
40+
this.untilSourceLine = 0;
2941
}
3042

3143
/**
32-
* Perform 'Replace' in the string (line param). Correponding to the 'REPLACE' statement in COBOL program
44+
* Perform 'Replace' in the string (line param). Corresponding to the 'REPLACE' statement in COBOL program
3345
* And the values parsed from the statements are used to replace the values in the line.
3446
*
3547
* @param line The line to replace in
@@ -60,6 +72,28 @@ public String replaceInline(String line) {
6072
}
6173
}
6274

75+
/**
76+
* Perform 'Replace' in the string (line param). Corresponding to the 'REPLACE' statement in COBOL program
77+
* And the values parsed from the statements are used to replace the values in the line.
78+
* @param line
79+
* @param sourceLine
80+
* @return
81+
*/
82+
public String replaceInline(String line, int sourceLine) {
83+
// if the line is zero, the replace key set is applied
84+
if (sourceLine == 0) return replaceInline(line);
85+
86+
// when fromSourceLine and untilSourceLine are zero, the replace key set is applied to all lines.
87+
if (fromSourceLine == 0 && untilSourceLine == 0) return replaceInline(line);
88+
89+
// when the line number is between fromSourceLine and untilSourceLine, the replace is performed
90+
if ((sourceLine >= fromSourceLine && sourceLine <= untilSourceLine) ||
91+
((sourceLine >= fromSourceLine && untilSourceLine == 0))) return replaceInline(line);
92+
93+
// Otherwise, return the line as is
94+
return line;
95+
}
96+
6397
public void setTrailing(boolean trailing) {
6498
if (trailing && this.leading) {
6599
throw new IllegalArgumentException("Cannot have both trailing and leading set to true");
@@ -97,4 +131,20 @@ public boolean isTrailing() {
97131
public boolean isLeading() {
98132
return leading;
99133
}
134+
135+
public void setFromSourceLine(int sourceLineNumber) {
136+
this.fromSourceLine = sourceLineNumber;
137+
}
138+
public void setUntilSourceLine(int sourceLineNumber) {
139+
this.untilSourceLine = sourceLineNumber;
140+
}
141+
public int getFromSourceLine() {
142+
return fromSourceLine;
143+
}
144+
public int getUntilSourceLine() {
145+
return untilSourceLine;
146+
}
147+
public String toString() {
148+
return "From: " + from + ", To: " + to + ", Trailing: " + trailing + ", Leading: " + leading + ", FromSourceLine: " + fromSourceLine + ", UntilSourceLine: " + untilSourceLine;
149+
}
100150
}

src/main/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/ReplaceStatementLocator.java

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.openmainframeproject.cobolcheck.services.cobolLogic.replace;
22

3+
import org.jetbrains.annotations.NotNull;
34
import org.openmainframeproject.cobolcheck.services.log.Log;
45

56
import java.io.*;
@@ -16,9 +17,11 @@ public class ReplaceStatementLocator {
1617
// because it can be split over multiple lines
1718
private final ReplaceTokenizer tokenizer = new ReplaceTokenizer();
1819
protected StringBuilder currentStatement;
20+
protected int statementLineNumber = 0;
1921
protected boolean we_are_parsing_a_replace_statement = false;
2022
protected int sourceLinesProcessed = 0;
2123
protected int commentLinesFound = 0;
24+
private int currentSourcecodeLine = -1;
2225

2326
public ReplaceStatementLocator() {
2427
Log.trace("ReplaceStatementLocator(): No file provided, only for testing purposes");
@@ -29,8 +32,9 @@ public ReplaceStatementLocator(File cobolFile) {
2932
//Iterate over the file and inspect each line
3033
try (BufferedReader reader = new BufferedReader(new FileReader(cobolFile))) {
3134
String line;
35+
int lineCounter = 0;
3236
while ((line = reader.readLine()) != null) {
33-
accumulateStatement(line);
37+
accumulateStatement(line,++lineCounter);
3438
}
3539
} catch (FileNotFoundException e) {
3640
Log.error("ReplaceStatementLocator(): File not found: " + e.getMessage());
@@ -45,7 +49,7 @@ public LinkedList<ReplaceSet> getReplaceSets() {
4549
return replaceSets;
4650
}
4751

48-
protected void accumulateStatement(String line) {
52+
protected void accumulateStatement(String line, int sourceLineNumber) {
4953
// tokenize the line
5054
tokenizer.tokenize(line);
5155

@@ -66,25 +70,40 @@ protected void accumulateStatement(String line) {
6670
if (t.getType() == ReplaceTokenType.REPLACE) {
6771
// if we have a REPLACE token, start accumulating the statement
6872
currentStatement = new StringBuilder().append(t.getValue());
73+
this.statementLineNumber = sourceLineNumber;
6974
we_are_parsing_a_replace_statement = true;
7075
} else if (t.getType() == ReplaceTokenType.TERMINATOR && we_are_parsing_a_replace_statement) {
7176
// if we have a terminator token, process the statement
72-
createStatements(currentStatement.toString());
77+
createStatements(currentStatement.toString(),this.statementLineNumber);
7378
we_are_parsing_a_replace_statement = false;
7479
}
7580
}
7681
}
7782

83+
/**
84+
* Update the untilSourceLine in all ReplaceSet objects where the from is equal to the given value
85+
* @param untilSourceLine the new value for untilSourceLine
86+
*/
87+
protected void updateUntilInReplaceSets(int fromSourceLine, int untilSourceLine) {
88+
for (ReplaceSet replaceSet : replaceSets) {
89+
if (replaceSet.getFromSourceLine() == fromSourceLine) replaceSet.setUntilSourceLine(untilSourceLine);
90+
}
91+
}
92+
7893

7994
/**
8095
* process a complete <i>REPLACE</i> statement and create the ReplaceSet objects
8196
* @param statement string of tokens from replace to terminator (.)
8297
*/
83-
protected void createStatements(String statement) {
98+
protected void createStatements(String statement, int sourceLineNumber) {
8499
ReplaceTokenizer statementTokenizer = new ReplaceTokenizer();
85100
statementTokenizer.tokenize(statement);
86101

87-
ReplaceSet replaceSet = new ReplaceSet();
102+
ReplaceSet replaceSet = getNewReplaceSet(sourceLineNumber);
103+
// update the ReplaceSets that may have been created from the 'currentSourcecodeLine' location
104+
// from and to values are corrected to avoid replacing the REPLACE statement itself
105+
this.updateUntilInReplaceSets(this.currentSourcecodeLine + 1,sourceLineNumber - 1);
106+
this.currentSourcecodeLine = sourceLineNumber;
88107

89108
ReplaceToken t;
90109
boolean nextTokenIsTo = false;
@@ -111,12 +130,20 @@ protected void createStatements(String statement) {
111130
replaceSet.setTo(t.getValue().replace("==", ""));
112131
nextTokenIsTo = false;
113132
replaceSets.add(replaceSet);
114-
replaceSet = new ReplaceSet();
133+
replaceSet = getNewReplaceSet(sourceLineNumber);
115134
} else {
116135
replaceSet.setFrom(t.getValue().replace("==", ""));
117136
}
118137
break;
119138
}
120139
}
121140
}
141+
142+
private static @NotNull ReplaceSet getNewReplaceSet(int sourceLineNumber) {
143+
ReplaceSet replaceSet = new ReplaceSet();
144+
// one is added to the sourceLineNumber because the REPLACE statement is on current line and the replace is done from the next line
145+
// This way we won´t replace the REPLACE statement itself
146+
replaceSet.setFromSourceLine(sourceLineNumber + 1);
147+
return replaceSet;
148+
}
122149
}

src/test/java/org/openmainframeproject/cobolcheck/services/cobolLogic/replace/ReplaceSetTest.java

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,19 @@ public class ReplaceSetTest {
1010
public void testReplaceSet() {
1111

1212
// Create a Replace set
13-
ReplaceSet replaceSet = new ReplaceSet("REPLACE", "REPLACED", false, false);
13+
ReplaceSet replaceSet = new ReplaceSet("REPLACE", "REPLACED", false, false,0,0);
1414
assertEquals("REPLACE", replaceSet.getFrom());
1515
assertEquals("REPLACED", replaceSet.getTo());
1616
assertFalse(replaceSet.isTrailing());
1717
assertFalse(replaceSet.isLeading());
1818

19-
replaceSet = new ReplaceSet("BRUCE", "CAITLYN", true, false);
19+
replaceSet = new ReplaceSet("BRUCE", "CAITLYN", true, false,0,0);
2020
assertEquals("BRUCE", replaceSet.getFrom());
2121
assertEquals("CAITLYN", replaceSet.getTo());
2222
assertTrue(replaceSet.isTrailing());
2323
assertFalse(replaceSet.isLeading());
2424

25-
replaceSet = new ReplaceSet("JOHNNY", "JAY", false, true);
25+
replaceSet = new ReplaceSet("JOHNNY", "JAY", false, true,0,0);
2626
assertEquals("JOHNNY", replaceSet.getFrom());
2727
assertEquals("JAY", replaceSet.getTo());
2828
assertFalse(replaceSet.isTrailing());
@@ -31,25 +31,25 @@ public void testReplaceSet() {
3131
// Having both trailing and leading set to true is not allowed
3232
// This should throw an exception
3333
// Not possible via constructor
34-
assertThrows(IllegalArgumentException.class, () -> new ReplaceSet("JOHNNY", "JAY", true, true));
34+
assertThrows(IllegalArgumentException.class, () -> new ReplaceSet("JOHNNY", "JAY", true, true,0,0));
3535
// not possible via setter
36-
ReplaceSet replaceSetLeading = new ReplaceSet("REPLACE", "REPLACED", false, true);
36+
ReplaceSet replaceSetLeading = new ReplaceSet("REPLACE", "REPLACED", false, true,0,0);
3737
assertThrows(IllegalArgumentException.class, () -> replaceSetLeading.setTrailing(true));
38-
ReplaceSet replaceSetTrailing = new ReplaceSet("REPLACE", "REPLACED", true, false);
38+
ReplaceSet replaceSetTrailing = new ReplaceSet("REPLACE", "REPLACED", true, false,0,0);
3939
assertThrows(IllegalArgumentException.class, () -> replaceSetTrailing.setLeading(true));
4040
}
4141

4242
@Test
4343
public void testReplaceInline() {
44-
ReplaceSet replaceSet = new ReplaceSet("JOHNNY", "JAY", false, false);
44+
ReplaceSet replaceSet = new ReplaceSet("JOHNNY", "JAY", false, false,0,0);
4545
String from = "Johnny is behind the iconic late-night desk.";
4646
String expected = "JAY is behind the iconic late-night desk.";
4747
assertEquals(expected, replaceSet.replaceInline(from));
4848
}
4949

5050
@Test
5151
public void testReplaceInlineTrailing() {
52-
ReplaceSet replaceSet = new ReplaceSet("night", "day", true, false);
52+
ReplaceSet replaceSet = new ReplaceSet("night", "day", true, false,0,0);
5353
String from = "Johnny is behind the iconic late-night desk.";
5454
String expected = "Johnny is behind the iconic late-day desk.";
5555
assertEquals(expected, replaceSet.replaceInline(from));
@@ -61,13 +61,11 @@ public void testReplaceInlineTrailing() {
6161
from = "Johnny is working day and night behind the iconic desk.";
6262
expected = "Johnny is working day and night behind the iconic desk.";
6363
assertEquals(expected, replaceSet.replaceInline(from));
64-
65-
6664
}
6765

6866
@Test
6967
public void testReplaceInlineLeading() {
70-
ReplaceSet replaceSet = new ReplaceSet("late", "early", false, true);
68+
ReplaceSet replaceSet = new ReplaceSet("late", "early", false, true,0,0);
7169
String from = "Johnny is behind the iconic late-night desk.";
7270
String expected = "Johnny is behind the iconic early-night desk.";
7371
assertEquals(expected, replaceSet.replaceInline(from));
@@ -80,4 +78,26 @@ public void testReplaceInlineLeading() {
8078
expected = "Johnny is working early and late behind the iconic desk.";
8179
assertEquals(expected, replaceSet.replaceInline(from));
8280
}
81+
82+
@Test
83+
public void testReplaceInlinewithlinenumbering() {
84+
ReplaceSet replaceSet = new ReplaceSet("late", "early", false, true,10,100);
85+
String from = "Johnny is behind the iconic late-night desk.";
86+
String expected = "Johnny is behind the iconic early-night desk.";
87+
// unchanged as line number is not in the range
88+
assertEquals(from, replaceSet.replaceInline(from,5));
89+
// changed as line number is in the range
90+
assertEquals(expected, replaceSet.replaceInline(from,15));
91+
}
92+
93+
@Test
94+
public void testReplaceinLineWithLinenumberingLastReplaceSetHasZeroAsUntilSourceLine() {
95+
ReplaceSet replaceSet = new ReplaceSet("late", "early", false, true,10,0);
96+
String from = "Johnny is behind the iconic late-night desk.";
97+
String expected = "Johnny is behind the iconic early-night desk.";
98+
// unchanged as line number is not in the range
99+
assertEquals(from, replaceSet.replaceInline(from,5));
100+
// changed as line number is in the range
101+
assertEquals(expected, replaceSet.replaceInline(from,15));
102+
}
83103
}

0 commit comments

Comments
 (0)