From c50b9698820c2c1921fa899225074497f2535d3c Mon Sep 17 00:00:00 2001 From: Selebrator Date: Sun, 2 Jun 2019 20:57:35 +0200 Subject: [PATCH] Pretty writer --- src/main/java/_8/Lecture.java | 67 ++++++++-- src/main/java/_8/io/SonState.java | 11 ++ src/main/java/_8/io/SonWriter.java | 198 +++++++++++++++++++++++++++++ 3 files changed, 263 insertions(+), 13 deletions(-) create mode 100644 src/main/java/_8/io/SonState.java create mode 100644 src/main/java/_8/io/SonWriter.java diff --git a/src/main/java/_8/Lecture.java b/src/main/java/_8/Lecture.java index a67f521..ec99432 100644 --- a/src/main/java/_8/Lecture.java +++ b/src/main/java/_8/Lecture.java @@ -1,9 +1,8 @@ package _8; -import java.io.DataInputStream; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; +import _8.io.SonWriter; + +import java.io.*; import java.util.ArrayList; import java.util.List; import java.nio.file.Files; @@ -160,7 +159,7 @@ public class Lecture { List lecturers = data.getLecturers(); StringJoiner sjLect = new StringJoiner(",\n"); for (Lecturer l : lecturers) { - sjLect.add("\t\t{\n\t\t firstname: " + l.getFirstName() + ",\n\t\t" + " lastname: " + l.getLastName() + "\n\t\t}"); + sjLect.add("\t\t{\n\t\t firstName: " + l.getFirstName() + ",\n\t\t" + " lastName: " + l.getLastName() + "\n\t\t}"); } sb.append(sjLect.toString()).append("\n\t],\n"); @@ -173,7 +172,7 @@ public class Lecture { for (String t : topics) { sjTopics.add("\n\t\t " + t); } - sjSched.add("\t\t{\n\t\t time: " + s.getYear() + "-" + s.getMonth() + "-" + s.getDay() + " " + s.getHour() + ", " + "\n\t\t " + "lectureHall: " + s.getLectureHall() + ",\n\t\t topics: [" + sjTopics + "\n\t\t ]\n\t\t}"); + sjSched.add("\t\t{\n\t\t time: " + s.getYear() + "-" + s.getMonth() + "-" + s.getDay() + " " + s.getHour() + ":00, " + "\n\t\t " + "lectureHall: " + s.getLectureHall() + ",\n\t\t topics: [" + sjTopics + "\n\t\t ]\n\t\t}"); } sb.append(sjSched.toString()).append("\n\t]"); sb.append("\n}"); @@ -217,12 +216,12 @@ public class Lecture { if (l.contains("{")) { numberOfLecturers++; lecturers.add(new Lecturer()); - } else if (l.contains("firstname: ")) { - String firstnameLine = splitIdentifier(l, "firstname: "); - lecturers.get(numberOfLecturers-1).setFirstName(firstnameLine); - } else if (l.contains("lastname: ")) { - String lastnameLine = splitIdentifier(l, "lastname: "); - lecturers.get(numberOfLecturers-1).setLastName(lastnameLine); + } else if (l.contains("firstName: ")) { + String firstNameLine = splitIdentifier(l, "firstName: "); + lecturers.get(numberOfLecturers-1).setFirstName(firstNameLine); + } else if (l.contains("lastName: ")) { + String lastNameLine = splitIdentifier(l, "lastName: "); + lecturers.get(numberOfLecturers-1).setLastName(lastNameLine); } else if (l.contains("]")) { lecturersFlag = false; } @@ -237,7 +236,7 @@ public class Lecture { schedule.get(numberOfDates-1).setMonth(Integer.parseInt(time[1])); String[] time2 = time[2].split(" "); schedule.get(numberOfDates-1).setDay(Integer.parseInt(time2[0])); - schedule.get(numberOfDates-1).setHour(Integer.parseInt(time2[1])); + schedule.get(numberOfDates-1).setHour(Integer.parseInt(time2[1].split(":")[0])); } else if (l.contains("lectureHall: ")) { String lectureHallLine = splitIdentifier(l, "lectureHall: "); schedule.get(numberOfDates-1).setLectureHall(lectureHallLine); @@ -265,4 +264,46 @@ public class Lecture { result = result[1].split(","); return result[0]; } + + public static void saveText2(String filename, Lecture data) throws IOException { + Path file = Paths.get(filename); + try(SonWriter out = new SonWriter(Files.newBufferedWriter(file))) { + Lecture.saveSon(out, data); + } + } + + public static void saveSon(SonWriter out, Lecture lecture) throws IOException { + out.beginObject(); + out.name("number").value(lecture.getNumber()); + out.name("title").value(lecture.getTitle()); + out.name("shortTitle").value(lecture.getShortTitle()); + out.name("semester").value(lecture.getSemester()); + + out.name("lecturers").beginArray(); + for(Lecturer lecturer : lecture.getLecturers()) { + out.beginObject(); + out.name("firstName").value(lecturer.getFirstName()); + out.name("lastName").value(lecturer.getLastName()); + out.endObject(); + } + out.endArray(); + + out.name("schedule").beginArray(); + for(Date date : lecture.getSchedule()) { + out.beginObject(); + out.name("time").value(date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " " + date.getHour() + ":00"); + out.name("lectureHall").value(date.getLectureHall()); + + out.name("topics").beginArray(); + for(String topic : date.getTopics()) { + out.value(topic); + } + out.endArray(); + + out.endObject(); + } + out.endArray(); + + out.endObject(); + } } diff --git a/src/main/java/_8/io/SonState.java b/src/main/java/_8/io/SonState.java new file mode 100644 index 0000000..7178895 --- /dev/null +++ b/src/main/java/_8/io/SonState.java @@ -0,0 +1,11 @@ +package _8.io; + +public enum SonState { + EMPTY_DOCUMENT, + NONEMPTY_DOCUMENT, + EMPTY_ARRAY, + NONEMPTY_ARRAY, + EMPTY_OBJECT, + NONEMPTY_OBJECT, + DANGLING_NAME +} \ No newline at end of file diff --git a/src/main/java/_8/io/SonWriter.java b/src/main/java/_8/io/SonWriter.java new file mode 100644 index 0000000..cbd058f --- /dev/null +++ b/src/main/java/_8/io/SonWriter.java @@ -0,0 +1,198 @@ +package _8.io; + +import java.io.Closeable; +import java.io.Flushable; +import java.io.IOException; +import java.io.Writer; +import java.util.Arrays; + +import static _8.io.SonState.*; + +public class SonWriter implements Closeable, Flushable { + + private static final String nextIndicator = ","; + private final Writer out; + private String indent; + private String keyValueSeparator; + + private SonState[] stack = new SonState[32]; + private int stackTop = 0; + private String nextName; + + public SonWriter(Writer out) { + this.out = out; + this.push(EMPTY_DOCUMENT); + this.setIndent(" "); + } + + public final void setIndent(String indent) { + if(indent == null || indent.length() == 0) { + this.indent = null; + this.keyValueSeparator = ":"; + } else { + this.indent = indent; + this.keyValueSeparator = ": "; + } + } + + public SonWriter beginObject() throws IOException { + this.open(EMPTY_OBJECT, "{"); + return this; + } + + public SonWriter endObject() throws IOException { + this.close(EMPTY_OBJECT, NONEMPTY_OBJECT, "}"); + return this; + } + + public SonWriter beginArray() throws IOException { + this.open(EMPTY_ARRAY, "["); + return this; + } + + public SonWriter endArray() throws IOException { + this.close(EMPTY_ARRAY, NONEMPTY_ARRAY, "]"); + return this; + } + + private void open(SonState empty, String openBracket) throws IOException { + this.writeName(); + this.prepareValue(); + this.push(empty); + this.out.write(openBracket); + } + + private void close(SonState empty, SonState nonempty, String closedBracket) throws IOException { + SonState state = this.peek(); + if(state != empty && state != nonempty) { + throw new IllegalStateException("Can't close what's not open"); + } + if(this.nextName != null) { + throw new IllegalStateException("Dangling name: " + this.nextName); + } + + this.pop(); + if(state == nonempty) { + this.newline(); + } + this.out.write(closedBracket); + } + + public SonWriter name(String name) { + if(name == null) { + throw new NullPointerException("name == null"); + } + if(this.nextName != null) { + throw new IllegalStateException("Didn't expect a name again"); + } + + this.nextName = name; + return this; + } + + public SonWriter value(String value) throws IOException { + this.writeName(); + this.prepareValue(); + this.out.write(value); + return this; + } + + public SonWriter value(Boolean value) throws IOException { + return this.value(value ? "true" : "false"); + } + + public SonWriter value(Number value) throws IOException { + return this.value(value.toString()); + } + + private void writeName() throws IOException { + if(this.nextName != null) { + this.prepareName(); + this.out.write(this.nextName); + this.nextName = null; + } + } + + private void prepareName() throws IOException { + SonState state = this.peek(); + if(state == NONEMPTY_OBJECT) { // not first in an object + this.out.write(nextIndicator); + } else if(state != EMPTY_OBJECT) { // not in an object + throw new IllegalStateException("Didn't expect this to be named"); + } + + this.newline(); + this.replaceTop(DANGLING_NAME); + } + + private void newline() throws IOException { + if(this.indent == null) { + return; + } + this.out.write("\n"); + for(int i = 1; i < this.stackTop; i++) { + this.out.write(this.indent); + } + } + + private void prepareValue() throws IOException { + SonState state = this.peek(); + switch(state) { + case EMPTY_DOCUMENT: + this.replaceTop(NONEMPTY_DOCUMENT); + break; + case EMPTY_ARRAY: + this.replaceTop(NONEMPTY_ARRAY); + this.newline(); + break; + case NONEMPTY_ARRAY: + this.out.write(nextIndicator); + this.newline(); + break; + case DANGLING_NAME: + this.out.write(this.keyValueSeparator); + this.replaceTop(NONEMPTY_OBJECT); + break; + default: + throw new IllegalStateException(); + } + } + + @Override + public void flush() throws IOException { + if(this.stackTop == 0) { + throw new IllegalStateException("SonWriter already closed"); + } + this.out.flush(); + } + + @Override + public void close() throws IOException { + this.out.close(); + if(this.stackTop > 1 || this.stackTop == 1 && this.peek() != NONEMPTY_DOCUMENT) { + throw new IOException("Incomplete document"); + } + this.stackTop = 0; + } + + /* stack management */ + + private SonState peek() { + return this.stack[this.stackTop - 1]; + } + + private SonState pop() { + return this.stack[--this.stackTop]; + } + + private void push(SonState newTop) { + if(this.stackTop >= this.stack.length) { + this.stack = Arrays.copyOf(this.stack, this.stackTop * 2); + } + this.stack[this.stackTop++] = newTop; + } + + private void replaceTop(SonState newTop) { + this.stack[this.stackTop - 1] = newTop; + } +}