// Path: pie-core/src/main/java/com/coverity/security/pie/util/IOUtil.java
// public class IOUtil {
//     public static void closeSilently(Closeable closeable) {
//         if (closeable != null) {
//             try {
//                 closeable.close();
//             } catch (IOException e) {
//                 // Do nothing
//             }
//         }
//     }
//     
//     public static String readFile(File file) throws IOException {
//         return toString(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8));
//     }
//     public static String readFile(String file) throws IOException {
//         return toString(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8));
//     }
//     public static String readFile(URL file) throws IOException {
//         return toString(file.openStream());
//     }
//     
//     public static String toString(InputStream is) throws IOException {
//         try {
//             return toString(new InputStreamReader(is, StandardCharsets.UTF_8));
//         } finally {
//             closeSilently(is);
//         }
//     }
//     public static String toString(Reader reader) throws IOException {
//         StringBuilder sb = new StringBuilder();
//         try {
//             char buffer[] = new char[4096];
//             int n;
//             while ((n = reader.read(buffer)) > 0) {
//                 sb.append(buffer, 0, n);
//             }
//             reader.close();
//         } catch (IOException e) {
//             closeSilently(reader);
//             throw e;
//         }
//         return sb.toString();
//     }
//     
//     
//     public static void writeFile(File file, String content) throws IOException {
//         writeFile(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8), content);
//     }
//     private static void writeFile(Writer fw, String content) throws IOException {
//         try {
//             fw.write(content);
//             fw.close();
//         } catch (IOException e) {
//             closeSilently(fw);
//             throw e;
//         }
//     }
//     
// }
// 
// Path: pie-core/src/main/java/com/coverity/security/pie/util/PieLogger.java
// public class PieLogger {
//     private static PieConfig pieConfig = null;
//     private static PrintWriter logWriter = null;
// 
//     public static void setPieConfig(PieConfig pieConfig) {
//         PieLogger.pieConfig = pieConfig;
//         if (logWriter != null) {
//             IOUtil.closeSilently(logWriter);
//             logWriter = null;
//         }
//         if (pieConfig != null && pieConfig.isLoggingEnabled()) {
//             try {
//                 logWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(pieConfig.getLogPath(), true), StandardCharsets.UTF_8));
//             } catch (FileNotFoundException e) {
//                 throw new RuntimeException(e);
//             }
//         }
//     }
// 
//     public static enum LogLevel {
//         DEBUG,
//         INFO,
//         WARN,
//         ERROR
//     }
// 
//     public static void log(LogLevel logLevel, String msg, Throwable throwable) {
//         if (logWriter == null) {
//             return;
//         }
//         logWriter.append("[").append(new Date().toString()).append("] ").append(logLevel.toString()).append(": ").append(msg).append("\n");
//         if (throwable != null) {
//             throwable.printStackTrace(logWriter);
//         }
//         logWriter.flush();
//     }
// 
//     public static void log(LogLevel logLevel, String msg) {
//         log(logLevel, msg, null);
//     }
// 
//     public static void debug(String msg) {
//         log(LogLevel.DEBUG, msg);
//     }
//     public static void debug(String msg, Throwable throwable) {
//         log(LogLevel.DEBUG, msg, throwable);
//     }
//     public static void info(String msg) {
//         log(LogLevel.INFO, msg);
//     }
//     public static void info(String msg, Throwable throwable) {
//         log(LogLevel.INFO, msg, throwable);
//     }
//     public static void warn(String msg) {
//         log(LogLevel.WARN, msg);
//     }
//     public static void warn(String msg, Throwable throwable) {
//         log(LogLevel.WARN, msg, throwable);
//     }
//     public static void error(String msg) {
//         log(LogLevel.ERROR, msg);
//     }
//     public static void error(String msg, Throwable throwable) {
//         log(LogLevel.ERROR, msg, throwable);
//     }
// 
// }


import com.coverity.security.pie.util.IOUtil;
import com.coverity.security.pie.util.PieLogger;
import org.json.JSONObject;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
            FactTreeNode child = children.get(i);
            for (int j = 0; j < indent; j++) {
                writer.write("   ");
            }
            writer.write("\"");
            writer.write(child.value.replaceAll("\\\\", "\\\\\\\\").replaceAll("\"", "\\\\\\\""));
            writer.write("\": {");
            if (child.children.size() == 0) {
                writer.write ("}");
            } else {
                writer.write("\n");
                writePolicy(writer, child, indent+1);
                for (int j = 0; j < indent; j++) {
                    writer.write("   ");
                }
                writer.write ("}");
            }
            
            if (i < children.size()-1) {
                writer.write(",");
            }
            writer.write("\n");
        }
    }

    /**
     * Appends the observed policy violation to this policy's list of violations.
     * @param facts
     */
    protected final void logViolation(String ... facts) {
// Path: pie-core/src/main/java/com/coverity/security/pie/util/IOUtil.java
// public class IOUtil {
//     public static void closeSilently(Closeable closeable) {
//         if (closeable != null) {
//             try {
//                 closeable.close();
//             } catch (IOException e) {
//                 // Do nothing
//             }
//         }
//     }
//     
//     public static String readFile(File file) throws IOException {
//         return toString(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8));
//     }
//     public static String readFile(String file) throws IOException {
//         return toString(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8));
//     }
//     public static String readFile(URL file) throws IOException {
//         return toString(file.openStream());
//     }
//     
//     public static String toString(InputStream is) throws IOException {
//         try {
//             return toString(new InputStreamReader(is, StandardCharsets.UTF_8));
//         } finally {
//             closeSilently(is);
//         }
//     }
//     public static String toString(Reader reader) throws IOException {
//         StringBuilder sb = new StringBuilder();
//         try {
//             char buffer[] = new char[4096];
//             int n;
//             while ((n = reader.read(buffer)) > 0) {
//                 sb.append(buffer, 0, n);
//             }
//             reader.close();
//         } catch (IOException e) {
//             closeSilently(reader);
//             throw e;
//         }
//         return sb.toString();
//     }
//     
//     
//     public static void writeFile(File file, String content) throws IOException {
//         writeFile(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8), content);
//     }
//     private static void writeFile(Writer fw, String content) throws IOException {
//         try {
//             fw.write(content);
//             fw.close();
//         } catch (IOException e) {
//             closeSilently(fw);
//             throw e;
//         }
//     }
//     
// }
// 
// Path: pie-core/src/main/java/com/coverity/security/pie/util/PieLogger.java
// public class PieLogger {
//     private static PieConfig pieConfig = null;
//     private static PrintWriter logWriter = null;
// 
//     public static void setPieConfig(PieConfig pieConfig) {
//         PieLogger.pieConfig = pieConfig;
//         if (logWriter != null) {
//             IOUtil.closeSilently(logWriter);
//             logWriter = null;
//         }
//         if (pieConfig != null && pieConfig.isLoggingEnabled()) {
//             try {
//                 logWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(pieConfig.getLogPath(), true), StandardCharsets.UTF_8));
//             } catch (FileNotFoundException e) {
//                 throw new RuntimeException(e);
//             }
//         }
//     }
// 
//     public static enum LogLevel {
//         DEBUG,
//         INFO,
//         WARN,
//         ERROR
//     }
// 
//     public static void log(LogLevel logLevel, String msg, Throwable throwable) {
//         if (logWriter == null) {
//             return;
//         }
//         logWriter.append("[").append(new Date().toString()).append("] ").append(logLevel.toString()).append(": ").append(msg).append("\n");
//         if (throwable != null) {
//             throwable.printStackTrace(logWriter);
//         }
//         logWriter.flush();
//     }
// 
//     public static void log(LogLevel logLevel, String msg) {
//         log(logLevel, msg, null);
//     }
// 
//     public static void debug(String msg) {
//         log(LogLevel.DEBUG, msg);
//     }
//     public static void debug(String msg, Throwable throwable) {
//         log(LogLevel.DEBUG, msg, throwable);
//     }
//     public static void info(String msg) {
//         log(LogLevel.INFO, msg);
//     }
//     public static void info(String msg, Throwable throwable) {
//         log(LogLevel.INFO, msg, throwable);
//     }
//     public static void warn(String msg) {
//         log(LogLevel.WARN, msg);
//     }
//     public static void warn(String msg, Throwable throwable) {
//         log(LogLevel.WARN, msg, throwable);
//     }
//     public static void error(String msg) {
//         log(LogLevel.ERROR, msg);
//     }
//     public static void error(String msg, Throwable throwable) {
//         log(LogLevel.ERROR, msg, throwable);
//     }
// 
// }


// Path: pie-core/src/main/java/com/coverity/security/pie/core/Policy.java
import com.coverity.security.pie.util.IOUtil;
import com.coverity.security.pie.util.PieLogger;
import org.json.JSONObject;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

            FactTreeNode child = children.get(i);
            for (int j = 0; j < indent; j++) {
                writer.write("   ");
            }
            writer.write("\"");
            writer.write(child.value.replaceAll("\\\\", "\\\\\\\\").replaceAll("\"", "\\\\\\\""));
            writer.write("\": {");
            if (child.children.size() == 0) {
                writer.write ("}");
            } else {
                writer.write("\n");
                writePolicy(writer, child, indent+1);
                for (int j = 0; j < indent; j++) {
                    writer.write("   ");
                }
                writer.write ("}");
            }
            
            if (i < children.size()-1) {
                writer.write(",");
            }
            writer.write("\n");
        }
    }

    /**
     * Appends the observed policy violation to this policy's list of violations.
     * @param facts
     */
    protected final void logViolation(String ... facts) {
        PieLogger.info("Observed policy violation: " + Arrays.toString(facts));