blob: 6d22d898e7ca55e8d8cd50bc34b422f18fa8f98b [file] [log] [blame]
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package compiler.compilercontrol.share;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.Objects;
import java.util.Stack;
/**
* Simple JSON file writer
*/
public class JSONFile implements AutoCloseable {
private final Stack<Element> stack;
private final String fileName;
private final PrintStream out;
private int spaces;
/**
* JSON element
*/
public enum Element {
OBJECT,
ARRAY,
PAIR,
VALUE
}
/**
* Constructor. Creates file with default name
*/
public JSONFile() {
this("directives_file.json");
}
/**
* Constructor
*
* @param fileName file name
*/
public JSONFile(String fileName) {
this.spaces = 0;
this.stack = new Stack<>();
this.fileName = fileName;
try {
out = new PrintStream(fileName);
} catch (FileNotFoundException e) {
throw new Error("TESTBUG: can't open/create file " + fileName, e);
}
}
/**
* Gets file name
*
* @return file name string
*/
public String getFileName() {
return fileName;
}
/**
* Gets current JSON element in the file.
* The element is a current {@linkplain Element}
* that was written into a file.
*
* @return the type of the current element,
* or null if there are nothing written
*/
public Element getElement() {
if (stack.empty()) {
return null;
}
return stack.peek();
}
/**
* Writes given type with a value to file.
* Note that only PAIR and VALUE types accept a single value parameter.
* OBJECT and ARRAY do not have a value
*
* @param element JSON element type
* @param value element's value
* @return this file instance
*/
public JSONFile write(Element element, String... value) {
if (value.length > 1) {
throw new Error("TESTBUG: Unexpected value length: "
+ value.length);
}
if (!stack.empty()) {
if (stack.peek() == Element.VALUE) {
out.print(", ");
stack.pop();
}
}
switch (element) {
case OBJECT:
out.print("{");
spaces++;
stack.push(Element.VALUE);
break;
case ARRAY:
out.print("[");
stack.push(Element.VALUE);
break;
case PAIR:
fillSpaces();
Objects.requireNonNull(value, "TESTBUG: " + element
+ "requires a value to be set");
out.print(value[0] + ": ");
break;
case VALUE:
Objects.requireNonNull(value, "TESTBUG: " + element
+ "requires a value to be set");
out.print(value[0]);
break;
}
stack.push(element);
return this;
}
private void fillSpaces() {
out.println();
for (int i = 0; i < spaces; i++) {
// Fill with spaces to be more readable
out.print(" ");
}
}
/**
* Ends current object or array of {@linkplain Element}
*
* @return this file instance
*/
public JSONFile end() {
if (!stack.empty()) {
Element prev = stack.pop();
while (prev != Element.OBJECT && prev != Element.ARRAY
&& !stack.empty()) {
prev = stack.pop();
}
switch (prev) {
case OBJECT:
spaces--;
fillSpaces();
out.print("}");
break;
case ARRAY:
out.print("]");
break;
default:
throw new Error("TESTBUG: Incorrect end. " +
"Wrong type found: " + prev);
}
} else {
throw new Error("TESTBUG: Incorrect end. Empty stack");
}
return this;
}
/**
* Closes this file
*/
@Override
public void close() {
out.close();
}
}