// Path: airomem-core/src/main/java/pl/setblack/airomem/core/PersistenceController.java
// public interface PersistenceController<ROOT extends Serializable> extends AutoCloseable {
// 
//     void close();
// 
//     void shut();
// 
//     /**
//      * Query system (immutable view of it).
//      * <p>
//      * Few things to remember: 1. if operations done on system (using query) do
//      * make some changes they will not be preserved (for long) 2. it is possible
//      * to return any object from domain (including ROOT root) and perform
//      * operations later on (but the more You do inside Query the safer).
//      *
//      * @param <RESULT> result of query
//      * @param query    lambda (or query implementation) with operations
//      * @return calculated result
//      */
//     <RESULT> RESULT query(Query<ROOT, RESULT> query);
// 
//     /**
//      * Perform command on system.
//      * <p>
//      * Inside command can be any code doing any changes. Such changes are
//      * guaranteed to be preserved (if only command ended without exception).
//      *
//      * @param cmd
//      */
//     <R> R executeAndQuery(ContextCommand<ROOT, R> cmd);
// 
//     /**
//      * Perform command on system.
//      * <p>
//      * Inside command can be any code doing any changes. Such changes are
//      * guaranteed to be preserved (if only command ended without exception).
//      *
//      * @param cmd
//      */
//     <R> R executeAndQuery(Command<ROOT, R> cmd);
// 
//     void execute(VoidCommand<ROOT> cmd);
// 
//     void execute(VoidContextCommand<ROOT> cmd);
// 
//     boolean isOpen();
// 
//     void erase();
// 
//     void snapshot();
// 
//     void snapshotXML(Path xmlFile) throws IOException;
// }
// 
// Path: airomem-core/src/main/java/pl/setblack/airomem/core/RestoreException.java
// public class RestoreException extends RuntimeException {
// 
//     public RestoreException(Throwable cause) {
//         super(cause);
//     }
// 
// }
// 
// Path: airomem-core/src/test/java/pl/setblack/airomem/core/StorableObject.java
// public class StorableObject implements Serializable {
// 
//     public final HashMap<String, String> internalMap;
// 
//     private transient Map<String, String> immutable;
// 
//     public StorableObject(HashMap<String, String> intenralMap) {
//         this.internalMap = intenralMap;
//         this.immutable = Collections.unmodifiableMap(intenralMap);
//     }
// 
// 
//     public synchronized Map<String, String> getImmutable() {
//         if (this.immutable == null) {
//             this.immutable = Collections.unmodifiableMap(internalMap);
//         }
//         return immutable;
//     }
// 
//     public static HashMap createTestHashMap() {
//         final HashMap<String, String> result = new HashMap<>();
//         for (int i = 0; i < 10; i++) {
//             result.put("key:" + i, "val:" + i);
//         }
//         return result;
//     }
// 
//     public static StorableObject createTestObject() {
//         return new StorableObject(createTestHashMap());
//     }
// }
// 
// Path: airomem-core/src/main/java/pl/setblack/airomem/core/VoidCommand.java
// public interface VoidCommand<T> extends Command<T, Void> {
// 
//     @Override
//     default Void execute(T system) {
//         this.executeVoid(system);
//         return null;
//     }
// 
//     void executeVoid(T system);
// 
// }
// 
// Path: airomem-core/src/main/java/pl/setblack/airomem/core/disk/PersistenceDiskHelper.java
// public final class PersistenceDiskHelper {
// 
//     public static final String STORAGE_FOLDER = "prevayler";
// 
//     PersistenceDiskHelper() {
//         throw new UnsupportedOperationException("do not create util classes");
//     }
// 
//     public static String calcFolderName(final Path path) {
//         return path.toString();
//     }
// 
//     /**
//      * Check if save of given name exists.
//      */
//     public static boolean exists(Path path) {
//         return Files.exists(path);
//     }
// 
//     public static void delete(Path path) {
//         if (exists(path)) {
//             Politician.beatAroundTheBush(() -> {
//                 FileUtils.deleteDirectory(path.toFile());
//             });
//         }
//     }
// 
// 
//     public static Path calcUserPath(String folderName) {
//         final String userFolder = System.getProperty("user.home");
//         return Paths.get(userFolder, STORAGE_FOLDER, folderName).toAbsolutePath();
//     }
// 
// }


import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.prevayler.foundation.serialization.JavaSerializer;
import pl.setblack.airomem.core.PersistenceController;
import pl.setblack.airomem.core.RestoreException;
import pl.setblack.airomem.core.StorableObject;
import pl.setblack.airomem.core.VoidCommand;
import pl.setblack.airomem.core.disk.PersistenceDiskHelper;
import pl.setblack.badass.Politician;
import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.atomic.AtomicReference;
import static junit.framework.Assert.*;
            System.setProperty("user.home", prevHome);
        }
    }


    @Test
    public void shouldStartTransientPrevayler() {
        //WHEN
        try (
                final PersistenceController<StorableObject> ctrl =
                        PrevaylerBuilder.<StorableObject>newBuilder()
                                .useSupplier(StorableObject::createTestObject)
                                .beTransient()
                                .withFolder(this.testFolder).build();) {

            ctrl.execute((x) -> x.internalMap.put("myKey", "myVal"));
            ctrl.close();
        }
        try (
                final PersistenceController<StorableObject> ctrl =
                        PrevaylerBuilder.<StorableObject>newBuilder()
                                .useSupplier(StorableObject::createTestObject)
                                .beTransient()
                                .withFolder(this.testFolder).build();) {

            assertNull(ctrl.query(obj -> obj.getImmutable().get("myKey")));
            ctrl.close();
        }
    }

// Path: airomem-core/src/main/java/pl/setblack/airomem/core/PersistenceController.java
// public interface PersistenceController<ROOT extends Serializable> extends AutoCloseable {
// 
//     void close();
// 
//     void shut();
// 
//     /**
//      * Query system (immutable view of it).
//      * <p>
//      * Few things to remember: 1. if operations done on system (using query) do
//      * make some changes they will not be preserved (for long) 2. it is possible
//      * to return any object from domain (including ROOT root) and perform
//      * operations later on (but the more You do inside Query the safer).
//      *
//      * @param <RESULT> result of query
//      * @param query    lambda (or query implementation) with operations
//      * @return calculated result
//      */
//     <RESULT> RESULT query(Query<ROOT, RESULT> query);
// 
//     /**
//      * Perform command on system.
//      * <p>
//      * Inside command can be any code doing any changes. Such changes are
//      * guaranteed to be preserved (if only command ended without exception).
//      *
//      * @param cmd
//      */
//     <R> R executeAndQuery(ContextCommand<ROOT, R> cmd);
// 
//     /**
//      * Perform command on system.
//      * <p>
//      * Inside command can be any code doing any changes. Such changes are
//      * guaranteed to be preserved (if only command ended without exception).
//      *
//      * @param cmd
//      */
//     <R> R executeAndQuery(Command<ROOT, R> cmd);
// 
//     void execute(VoidCommand<ROOT> cmd);
// 
//     void execute(VoidContextCommand<ROOT> cmd);
// 
//     boolean isOpen();
// 
//     void erase();
// 
//     void snapshot();
// 
//     void snapshotXML(Path xmlFile) throws IOException;
// }
// 
// Path: airomem-core/src/main/java/pl/setblack/airomem/core/RestoreException.java
// public class RestoreException extends RuntimeException {
// 
//     public RestoreException(Throwable cause) {
//         super(cause);
//     }
// 
// }
// 
// Path: airomem-core/src/test/java/pl/setblack/airomem/core/StorableObject.java
// public class StorableObject implements Serializable {
// 
//     public final HashMap<String, String> internalMap;
// 
//     private transient Map<String, String> immutable;
// 
//     public StorableObject(HashMap<String, String> intenralMap) {
//         this.internalMap = intenralMap;
//         this.immutable = Collections.unmodifiableMap(intenralMap);
//     }
// 
// 
//     public synchronized Map<String, String> getImmutable() {
//         if (this.immutable == null) {
//             this.immutable = Collections.unmodifiableMap(internalMap);
//         }
//         return immutable;
//     }
// 
//     public static HashMap createTestHashMap() {
//         final HashMap<String, String> result = new HashMap<>();
//         for (int i = 0; i < 10; i++) {
//             result.put("key:" + i, "val:" + i);
//         }
//         return result;
//     }
// 
//     public static StorableObject createTestObject() {
//         return new StorableObject(createTestHashMap());
//     }
// }
// 
// Path: airomem-core/src/main/java/pl/setblack/airomem/core/VoidCommand.java
// public interface VoidCommand<T> extends Command<T, Void> {
// 
//     @Override
//     default Void execute(T system) {
//         this.executeVoid(system);
//         return null;
//     }
// 
//     void executeVoid(T system);
// 
// }
// 
// Path: airomem-core/src/main/java/pl/setblack/airomem/core/disk/PersistenceDiskHelper.java
// public final class PersistenceDiskHelper {
// 
//     public static final String STORAGE_FOLDER = "prevayler";
// 
//     PersistenceDiskHelper() {
//         throw new UnsupportedOperationException("do not create util classes");
//     }
// 
//     public static String calcFolderName(final Path path) {
//         return path.toString();
//     }
// 
//     /**
//      * Check if save of given name exists.
//      */
//     public static boolean exists(Path path) {
//         return Files.exists(path);
//     }
// 
//     public static void delete(Path path) {
//         if (exists(path)) {
//             Politician.beatAroundTheBush(() -> {
//                 FileUtils.deleteDirectory(path.toFile());
//             });
//         }
//     }
// 
// 
//     public static Path calcUserPath(String folderName) {
//         final String userFolder = System.getProperty("user.home");
//         return Paths.get(userFolder, STORAGE_FOLDER, folderName).toAbsolutePath();
//     }
// 
// }


// Path: airomem-core/src/test/java/pl/setblack/airomem/core/builders/PrevaylerBuilderTest.java
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.prevayler.foundation.serialization.JavaSerializer;
import pl.setblack.airomem.core.PersistenceController;
import pl.setblack.airomem.core.RestoreException;
import pl.setblack.airomem.core.StorableObject;
import pl.setblack.airomem.core.VoidCommand;
import pl.setblack.airomem.core.disk.PersistenceDiskHelper;
import pl.setblack.badass.Politician;
import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.atomic.AtomicReference;
import static junit.framework.Assert.*;

            System.setProperty("user.home", prevHome);
        }
    }


    @Test
    public void shouldStartTransientPrevayler() {
        //WHEN
        try (
                final PersistenceController<StorableObject> ctrl =
                        PrevaylerBuilder.<StorableObject>newBuilder()
                                .useSupplier(StorableObject::createTestObject)
                                .beTransient()
                                .withFolder(this.testFolder).build();) {

            ctrl.execute((x) -> x.internalMap.put("myKey", "myVal"));
            ctrl.close();
        }
        try (
                final PersistenceController<StorableObject> ctrl =
                        PrevaylerBuilder.<StorableObject>newBuilder()
                                .useSupplier(StorableObject::createTestObject)
                                .beTransient()
                                .withFolder(this.testFolder).build();) {

            assertNull(ctrl.query(obj -> obj.getImmutable().get("myKey")));
            ctrl.close();
        }
    }

    private static final class StrangeTransaction implements VoidCommand<StorableObject>, Serializable {