// Path: src/main/java/com/oasisdigital/nges/event/EventStoreConflict.java
// public class EventStoreConflict extends EventStoreException {
//     private static final long serialVersionUID = 1L;
// 
//     public EventStoreConflict() {
//         super();
//     }
// 
//     public EventStoreConflict(String message, Throwable cause, boolean enableSuppression,
//             boolean writableStackTrace) {
//         super(message, cause, enableSuppression, writableStackTrace);
//     }
// 
//     public EventStoreConflict(String message, Throwable cause) {
//         super(message, cause);
//     }
// 
//     public EventStoreConflict(String message) {
//         super(message);
//     }
// 
//     public EventStoreConflict(Throwable cause) {
//         super(cause);
//     }
// 
// }
// 
// Path: src/main/java/com/oasisdigital/nges/event/EventStream.java
// public class EventStream {
//     private UUID streamId;
//     private String streamType;
//     private Long lastEventId;
//     private OffsetDateTime lastTransactionTime;
//     private Long lastSeqNo;
// 
//     public UUID getStreamId() {
//         return streamId;
//     }
// 
//     public void setStreamId(UUID streamId) {
//         this.streamId = streamId;
//     }
// 
//     public String getStreamType() {
//         return streamType;
//     }
// 
//     public void setStreamType(String streamType) {
//         this.streamType = streamType;
//     }
// 
//     public Long getLastEventId() {
//         return lastEventId;
//     }
// 
//     public void setLastEventId(Long lastEventId) {
//         this.lastEventId = lastEventId;
//     }
// 
//     public OffsetDateTime getLastTransactionTime() {
//         return lastTransactionTime;
//     }
// 
//     public void setLastTransactionTime(OffsetDateTime lastTransactionTime) {
//         this.lastTransactionTime = lastTransactionTime;
//     }
// 
//     public Long getLastSeqNo() {
//         return lastSeqNo;
//     }
// 
//     public void setLastSeqNo(Long lastSeqNo) {
//         this.lastSeqNo = lastSeqNo;
//     }
// 
// }
// 
// Path: src/main/java/com/oasisdigital/nges/event/EventStoreException.java
// public class EventStoreException extends RuntimeException {
// 
//     private static final long serialVersionUID = -1237680703226042282L;
// 
//     public EventStoreException() {
//         super();
//     }
// 
//     public EventStoreException(String message, Throwable cause, boolean enableSuppression,
//             boolean writableStackTrace) {
//         super(message, cause, enableSuppression, writableStackTrace);
//     }
// 
//     public EventStoreException(String message, Throwable cause) {
//         super(message, cause);
//     }
// 
//     public EventStoreException(String message) {
//         super(message);
//     }
// 
//     public EventStoreException(Throwable cause) {
//         super(cause);
//     }
// }


import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.UUID;
import com.oasisdigital.nges.event.EventStoreConflict;
import com.oasisdigital.nges.event.EventStream;
import com.oasisdigital.nges.event.EventStoreException;
package com.oasisdigital.nges.event.jdbc;



class EventStreamListDao {
    private final JdbcQueries queries;

    public EventStreamListDao(ConnectionSource connectionSource) {
        this.queries = new JdbcQueries(connectionSource);
    }

    /**
     *
     * @param streamId
     * @param lastEventId
     *            ID of the last (new) event for the stream
     * @param lastSequence
     *            sequence number of the last (new) event for the stream
     * @param expectedSequence
     *            sequence number that the update should be applied to; use "0" to indicate a new sequence
     * @throws EventStoreException
     */
    public void update(UUID streamId, long lastEventId, long lastSequence, long expectedSequence)
            throws EventStoreException {
        // @formatter:off
        int updated = queries.update(
                "update event_stream_list set "
              + "  last_event_id = ?, "
              + "  last_transaction_time = current_timestamp, "
              + "  last_seq_no = ? "
              + "where stream_id = ? and coalesce(last_seq_no, 0) = ?",
                lastEventId,
                lastSequence,
                streamId,
                expectedSequence);
        // @formatter:on
        if (updated == 0) {
            throw new EventStoreConflict("Uninitialized stream or concurrent modification: " + streamId);
        }
    }

// Path: src/main/java/com/oasisdigital/nges/event/EventStoreConflict.java
// public class EventStoreConflict extends EventStoreException {
//     private static final long serialVersionUID = 1L;
// 
//     public EventStoreConflict() {
//         super();
//     }
// 
//     public EventStoreConflict(String message, Throwable cause, boolean enableSuppression,
//             boolean writableStackTrace) {
//         super(message, cause, enableSuppression, writableStackTrace);
//     }
// 
//     public EventStoreConflict(String message, Throwable cause) {
//         super(message, cause);
//     }
// 
//     public EventStoreConflict(String message) {
//         super(message);
//     }
// 
//     public EventStoreConflict(Throwable cause) {
//         super(cause);
//     }
// 
// }
// 
// Path: src/main/java/com/oasisdigital/nges/event/EventStream.java
// public class EventStream {
//     private UUID streamId;
//     private String streamType;
//     private Long lastEventId;
//     private OffsetDateTime lastTransactionTime;
//     private Long lastSeqNo;
// 
//     public UUID getStreamId() {
//         return streamId;
//     }
// 
//     public void setStreamId(UUID streamId) {
//         this.streamId = streamId;
//     }
// 
//     public String getStreamType() {
//         return streamType;
//     }
// 
//     public void setStreamType(String streamType) {
//         this.streamType = streamType;
//     }
// 
//     public Long getLastEventId() {
//         return lastEventId;
//     }
// 
//     public void setLastEventId(Long lastEventId) {
//         this.lastEventId = lastEventId;
//     }
// 
//     public OffsetDateTime getLastTransactionTime() {
//         return lastTransactionTime;
//     }
// 
//     public void setLastTransactionTime(OffsetDateTime lastTransactionTime) {
//         this.lastTransactionTime = lastTransactionTime;
//     }
// 
//     public Long getLastSeqNo() {
//         return lastSeqNo;
//     }
// 
//     public void setLastSeqNo(Long lastSeqNo) {
//         this.lastSeqNo = lastSeqNo;
//     }
// 
// }
// 
// Path: src/main/java/com/oasisdigital/nges/event/EventStoreException.java
// public class EventStoreException extends RuntimeException {
// 
//     private static final long serialVersionUID = -1237680703226042282L;
// 
//     public EventStoreException() {
//         super();
//     }
// 
//     public EventStoreException(String message, Throwable cause, boolean enableSuppression,
//             boolean writableStackTrace) {
//         super(message, cause, enableSuppression, writableStackTrace);
//     }
// 
//     public EventStoreException(String message, Throwable cause) {
//         super(message, cause);
//     }
// 
//     public EventStoreException(String message) {
//         super(message);
//     }
// 
//     public EventStoreException(Throwable cause) {
//         super(cause);
//     }
// }


// Path: src/main/java/com/oasisdigital/nges/event/jdbc/EventStreamListDao.java
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.UUID;
import com.oasisdigital.nges.event.EventStoreConflict;
import com.oasisdigital.nges.event.EventStream;
import com.oasisdigital.nges.event.EventStoreException;

package com.oasisdigital.nges.event.jdbc;



class EventStreamListDao {
    private final JdbcQueries queries;

    public EventStreamListDao(ConnectionSource connectionSource) {
        this.queries = new JdbcQueries(connectionSource);
    }

    /**
     *
     * @param streamId
     * @param lastEventId
     *            ID of the last (new) event for the stream
     * @param lastSequence
     *            sequence number of the last (new) event for the stream
     * @param expectedSequence
     *            sequence number that the update should be applied to; use "0" to indicate a new sequence
     * @throws EventStoreException
     */
    public void update(UUID streamId, long lastEventId, long lastSequence, long expectedSequence)
            throws EventStoreException {
        // @formatter:off
        int updated = queries.update(
                "update event_stream_list set "
              + "  last_event_id = ?, "
              + "  last_transaction_time = current_timestamp, "
              + "  last_seq_no = ? "
              + "where stream_id = ? and coalesce(last_seq_no, 0) = ?",
                lastEventId,
                lastSequence,
                streamId,
                expectedSequence);
        // @formatter:on
        if (updated == 0) {
            throw new EventStoreConflict("Uninitialized stream or concurrent modification: " + streamId);
        }
    }

    public EventStream findByStreamId(UUID id) throws EventStoreException {