Structuralization Involving String Splitting
【Question】
For all subclasses that start with ~ I want to separate them into 2 values and join them to tail of an Array variable called "attributes". For example:
~ public void visitMethod(org.apache.bcel.classfile.Method arg0): 4
SUB_NAME =public void visitMethod(org.apache.bcel.classfile.Method arg0)
CC=4
Which I want to join to tail of an Array variable called "attributes":
String SUB_NAME = metadata[20];
int CC =Integer.parseInt(metadata[19]);
This is the text file I am parsing
gr.spinellis.ckjm.ClassVisitor 13 2 0 14 74 34 2 14 9 0.6042 431 0.8750 1 0.7273 0.2404 0 0 31.5385
~ public void visitMethod(org.apache.bcel.classfile.Method arg0): 4
~ public void registerCoupling(String arg0): 4
~ public void end(): 5
~ public void <init>(org.apache.bcel.classfile.JavaClass arg0, gr.spinellis.ckjm.ClassMetricsContainer arg1): 1
~ public gr.spinellis.ckjm.ClassMetrics getMetrics(): 1
~ private void incRFC(String arg0, String arg1, org.apache.bcel.generic.Type[] arg2): 1
~ public void start(): 1
~ void registerMethodInvocation(String arg0, String arg1, org.apache.bcel.generic.Type[] arg2): 1
~ public void visitField(org.apache.bcel.classfile.Field arg0): 1
~ public void visitJavaClass(org.apache.bcel.classfile.JavaClass arg0): 5
~ void registerFieldAccess(String arg0, String arg1): 2
~ static String className(org.apache.bcel.generic.Type arg0): 3
~ public void registerCoupling(org.apache.bcel.generic.Type arg0): 1
gr.spinellis.ckjm.ClassMetricsContainer 3 1 0 4 18 0 2 3 2 0.0000 66 1.0000 0 0.0000 0.5556 0 0 20.6667
~ void <init>(): 1
~ public gr.spinellis.ckjm.ClassMetrics getMetrics(String arg0): 2
~ public void printMetrics(gr.spinellis.ckjm.CkjmOutputHandler arg0): 3
gr.spinellis.ckjm.MetricsFilter 7 1 0 6 30 11 2 6 5 0.6667 218 1.0000 0 0.0000 0.2000 0 0 29.8571
~ public static boolean isJdkIncluded(): 1
~ static void processClass(gr.spinellis.ckjm.ClassMetricsContainer arg0, String arg1): 3
~ public static void runMetrics(String[] arg0, gr.spinellis.ckjm.CkjmOutputHandler arg1): 2
~ public static boolean includeAll(): 2
~ static void <clinit>(): 1
~ public static void main(String[] arg0): 7
~ public void <init>(): 1
gr.spinellis.ckjm.PrintPlainResults 2 1 0 3 8 0 1 2 2 0.0000 24 1.0000 0 0.0000 0.6250 0 0 10.5000
~ public void handleClass(String arg0, gr.spinellis.ckjm.ClassMetrics arg1): 1
~ public void <init>(java.io.PrintStream arg0): 1
gr.spinellis.ckjm.MethodVisitor 11 2 0 21 40 0 1 21 8 0.5500 209 1.0000 1 0.9474 0.1736 0 0 17.6364
~ public void visitINSTANCEOF(org.apache.bcel.generic.INSTANCEOF arg0): 1
~ public void visitLocalVariableInstruction(org.apache.bcel.generic.LocalVariableInstruction arg0): 2
~ public void visitCHECKCAST(org.apache.bcel.generic.CHECKCAST arg0): 1
~ private boolean visitInstruction(org.apache.bcel.generic.Instruction arg0): 4
~ public void visitInvokeInstruction(org.apache.bcel.generic.InvokeInstruction arg0): 2
~ public void visitReturnInstruction(org.apache.bcel.generic.ReturnInstruction arg0): 1
~ public void visitArrayInstruction(org.apache.bcel.generic.ArrayInstruction arg0): 1
~ public void visitFieldInstruction(org.apache.bcel.generic.FieldInstruction arg0): 1
~ void <init>(org.apache.bcel.generic.MethodGen arg0, gr.spinellis.ckjm.ClassVisitor arg1): 1
~ public void start(): 5
~ private void updateExceptionHandlers(): 3
gr.spinellis.ckjm.CkjmOutputHandler 1 1 0 4 1 0 3 1 1 2.0000 1 0.0000 0 0.0000 1.0000 0 0 0.0000
This is my passing logic of code:
public List<Metrics> readMetricFromCSV(String fileName) {
List<Metrics> metricsss = new ArrayList<>();
Path pathToFile = Paths.get(fileName);
// create an instance of BufferedReader
// using try with resource, Java 7 feature to close resources
try (BufferedReader br = Files.newBufferedReader(pathToFile,
StandardCharsets.US_ASCII)) {
// read the first line from the text file
String line = br.readLine();
while (line != null && !line.isEmpty()) { // loop until all lines
// are read
String[] attributes = line.split(" "); // the file, using a comma as the delimiter first 18 values
String str = line;
String[] arr1 = str.split("~");// the file, using a comma as the delimiter next 2 values
String[] arr2 = arr1[1].split(":");
String SUB_NAME = arr2[0], CC = arr2[1];
// System.out.println("SUB_NAME" + SUB_NAME + ", CC Value:" + CC);
Metrics valueOfMetric = createMetric(attributes+SUB_NAME+CC);
metricsss.add(valueOfMetric); // adding metric into ArrayList
br.readLine();
line = br.readLine();
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
【Answer】
Here’s what you want: Filter the file to get lines containing “~”, split each into two parts by “:”, remove “~” from the first part and name it SUB_NAME, and name the second part CC. It’s too complicated to code this in Java. But it’s simple to get it done in SPL (Structured Process Language):
A |
|
1 |
=file("d:\\source.txt").import@si() |
2 |
=A1.select(left(~,2)=="~") |
3 |
=A2.(~.split@t(":")) |
4 |
=A3.new(mid(~(1),3):SUB_NAME,~(2):CC) |
A1: Import source.txt to as a single-field sequence of strings.
A2: Get members containing “~”.
A3: Split each of A2’s string members into a two-member sequence by the separator “:”.
A4: Generate a two-dimensional table made up of SUB_NAME field and CC field. Each value in SUB_NAME field is the first member of A3’s each sequence member with “~” deleted; CC field contains values that are the second members of A3’s sequence members.
An SPL script can easily integrated with Java. See How to Call an SPL Script in Java.
SPL Official Website 👉 https://www.scudata.com
SPL Feedback and Help 👉 https://www.reddit.com/r/esProc_SPL
SPL Learning Material 👉 https://c.scudata.com
SPL Source Code and Package 👉 https://github.com/SPLWare/esProc
Discord 👉 https://discord.gg/cFTcUNs7
Youtube 👉 https://www.youtube.com/@esProc_SPL