// Path: airomem-chatsample/airomem-chatsample-data/src/main/java/pl/setblack/airomem/chatsample/data/Chat.java
// public class Chat implements ChatView, Serializable {
// 
//     private CopyOnWriteArrayList<Message> messages;
// 
//     public Chat() {
//         this.messages = new CopyOnWriteArrayList<>();
//     }
// 
//     public void addMessage(String nick, String content, LocalDateTime time) {
//         assert WriteChecker.hasPrevalanceContext();
//         final Author author = new Author(nick);
//         final Message msg = new Message(author, content, time);
//         this.messages.add(msg);
// 
//     }
// 
//     @Override
//     public List<MessageView> getRecentMessages() {
//         int count = this.messages.size();
//         final List<MessageView> res = this.messages.stream().skip(Math.max(count - 10, 0))
//                 .limit(10)
//                 .collect(Collectors.toList());
//         return res;
//     }
// }
// 
// Path: airomem-chatsample/airomem-chatsample-view/src/main/java/pl/setblack/airomem/chatsample/view/ChatView.java
// public interface ChatView {
// 
//     List<MessageView> getRecentMessages();
// }
// 
// Path: airomem-chatsample/airomem-chatsample-view/src/main/java/pl/setblack/airomem/chatsample/view/MessageView.java
// @XmlRootElement
// public interface MessageView {
// 
//     @XmlElement
//     String getContent();
//     
//     @XmlElement
//     AuthorView getAuthorView();
//     
//     @XmlAttribute
//     LocalDateTime getTime();
//     
//     String getAuthorNick();
// }
// 
// 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/data/DataRoot.java
// public class DataRoot<DATA> implements Serializable {
//     private static final long serialVersionUID = 1l;
//     private final DATA persistentObject;
// 
//     public DataRoot(DATA persistentObject) {
//         this.persistentObject = persistentObject;
//     }
// 
//     public DATA getDataObject() {
//         return persistentObject;
//     }
// 
// }


import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import pl.setblack.airomem.chatsample.data.Chat;
import pl.setblack.airomem.chatsample.view.ChatView;
import pl.setblack.airomem.chatsample.view.MessageView;
import pl.setblack.airomem.core.PersistenceController;
import pl.setblack.airomem.core.builders.PersistenceFactory;
import pl.setblack.airomem.data.DataRoot;
/*
 *  Created by Jarek Ratajski
 */
package pl.setblack.airomem.chatsample.execute;


/**
 *
 * @author jarekr
 */
@ApplicationScoped
public class ChatControllerImpl implements ChatController {

    private PersistenceController<DataRoot<ChatView, Chat>, ChatView> controller;

    @PostConstruct
    void initController() {
        final PersistenceFactory factory = new PersistenceFactory();
        controller = factory.initOptional("chat", () -> new DataRoot<>(new Chat()));
    }

    @Override
    public void addMessage(String nick, String message) {
        controller.execute((chat, ctx) -> {

            chat.getDataObject().addMessage(nick, message, LocalDateTime.ofInstant(ctx.time, ZoneId.systemDefault()));
            if (nick.equals("badguy")) {
                throw new SecurityException();
            }
        });
    }

// Path: airomem-chatsample/airomem-chatsample-data/src/main/java/pl/setblack/airomem/chatsample/data/Chat.java
// public class Chat implements ChatView, Serializable {
// 
//     private CopyOnWriteArrayList<Message> messages;
// 
//     public Chat() {
//         this.messages = new CopyOnWriteArrayList<>();
//     }
// 
//     public void addMessage(String nick, String content, LocalDateTime time) {
//         assert WriteChecker.hasPrevalanceContext();
//         final Author author = new Author(nick);
//         final Message msg = new Message(author, content, time);
//         this.messages.add(msg);
// 
//     }
// 
//     @Override
//     public List<MessageView> getRecentMessages() {
//         int count = this.messages.size();
//         final List<MessageView> res = this.messages.stream().skip(Math.max(count - 10, 0))
//                 .limit(10)
//                 .collect(Collectors.toList());
//         return res;
//     }
// }
// 
// Path: airomem-chatsample/airomem-chatsample-view/src/main/java/pl/setblack/airomem/chatsample/view/ChatView.java
// public interface ChatView {
// 
//     List<MessageView> getRecentMessages();
// }
// 
// Path: airomem-chatsample/airomem-chatsample-view/src/main/java/pl/setblack/airomem/chatsample/view/MessageView.java
// @XmlRootElement
// public interface MessageView {
// 
//     @XmlElement
//     String getContent();
//     
//     @XmlElement
//     AuthorView getAuthorView();
//     
//     @XmlAttribute
//     LocalDateTime getTime();
//     
//     String getAuthorNick();
// }
// 
// 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/data/DataRoot.java
// public class DataRoot<DATA> implements Serializable {
//     private static final long serialVersionUID = 1l;
//     private final DATA persistentObject;
// 
//     public DataRoot(DATA persistentObject) {
//         this.persistentObject = persistentObject;
//     }
// 
//     public DATA getDataObject() {
//         return persistentObject;
//     }
// 
// }


// Path: airomem-chatsample/airomem-chatsample-data/src/main/java/pl/setblack/airomem/chatsample/execute/ChatControllerImpl.java
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import pl.setblack.airomem.chatsample.data.Chat;
import pl.setblack.airomem.chatsample.view.ChatView;
import pl.setblack.airomem.chatsample.view.MessageView;
import pl.setblack.airomem.core.PersistenceController;
import pl.setblack.airomem.core.builders.PersistenceFactory;
import pl.setblack.airomem.data.DataRoot;

/*
 *  Created by Jarek Ratajski
 */
package pl.setblack.airomem.chatsample.execute;


/**
 *
 * @author jarekr
 */
@ApplicationScoped
public class ChatControllerImpl implements ChatController {

    private PersistenceController<DataRoot<ChatView, Chat>, ChatView> controller;

    @PostConstruct
    void initController() {
        final PersistenceFactory factory = new PersistenceFactory();
        controller = factory.initOptional("chat", () -> new DataRoot<>(new Chat()));
    }

    @Override
    public void addMessage(String nick, String message) {
        controller.execute((chat, ctx) -> {

            chat.getDataObject().addMessage(nick, message, LocalDateTime.ofInstant(ctx.time, ZoneId.systemDefault()));
            if (nick.equals("badguy")) {
                throw new SecurityException();
            }
        });
    }

    @Override