home / connvers / src / main / java / avividi / connvers / server / Storage.java

Storage.java



package avividi.connvers.server;

import avividi.connvers.protocol.Message;
import avividi.connvers.protocol.MessageEncoder;
import avividi.connvers.protocol.ValidationException;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedDeque;

public class Storage implements Closeable {

  private static final int MEM_MESSAGE_SIZE = 10;
  private final MessageEncoder messageEncoder;
  private final OutputStream outputStream;

  private final Deque<Message> stack = new ConcurrentLinkedDeque<>();

  public Storage(MessageEncoder messageEncoder, File file) throws IOException {
    if (!file.exists()) {
      file.createNewFile();
    }
    this.messageEncoder = messageEncoder;

    try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
      String line;
      while ((line = reader.readLine()) != null) {
        try {
          addToMem(messageEncoder.decode(line));
        } catch (ValidationException e) {
          throw new RuntimeException(e);
        }
      }
    }
    outputStream = new BufferedOutputStream(new FileOutputStream(file, true));
  }

  public List<Message> getMessages() {
    return new ArrayList<>(stack);
  }

  private void addToMem(Message message) {
    stack.addLast(message);

    while (stack.size() > MEM_MESSAGE_SIZE) {
      stack.pollFirst();
    }
  }

  void push(Message message) {
    addToMem(message);
    persistMessage(message);
  }

  private synchronized void persistMessage(Message message) {
    try {
      outputStream.write(messageEncoder.encode(message).getBytes());
      outputStream.write("\n".getBytes());
      outputStream.flush();
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }


  @Override
  public void close() throws IOException {
    outputStream.close();
  }
}