package br.com.citframework.integracao.core;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Logger;
/**
* {@link SequenceBlock} mant�m um peda�o de n�mero sequenciais, um bloco �nic
*/
public class SequenceBlock {
private static final Logger LOGGER = Logger.getLogger(SequenceBlock.class.getName());
private final AtomicLong lastReturnedValue;
private final long endOfBlock;
private final long startOfBlock;
/**
* Cria um novo {@link SequenceBlock} informando valores iniciais e finais do bloco
*
* @param startOfBlock
* valor, positivo, que � o primeiro valor a ser retornado por {@link #getNextId()}
* @param endOfBlock
* (exclusive) valor, positivo, ( (endOfBlock -1) que � o �ltimo valor a ser retornado por {@link #getNextId()}
*/
public SequenceBlock(final long startOfBlock, final long endOfBlock) {
if (startOfBlock < 0 || endOfBlock <= startOfBlock) {
throw new IllegalArgumentException("Unable to create sequence block with negative or conflicting arguments (initialValue: " + startOfBlock + ", maxValue: "
+ endOfBlock + ").");
}
LOGGER.fine(this.getClass().getSimpleName() + " created (" + startOfBlock + " <= val < " + endOfBlock + " ).");
this.startOfBlock = startOfBlock;
lastReturnedValue = new AtomicLong(startOfBlock - 1);
this.endOfBlock = endOfBlock;
}
/**
* {@code THREAD-SAFE} - Recupera o pr�ximo valor do bloco<br>
*
* @return {@link Long} pr�ximo valor do bloco. {@code -1}, caso o bloco esteja esgotado
*/
public long getNextId() {
LOGGER.fine(this.getClass().getSimpleName() + ".getNextId() called.");
long res = lastReturnedValue.addAndGet(1);
if (res >= endOfBlock) {
res = -1;
}
return res;
}
/**
* Verifica se o bloco est� esgotado
*
* @return {@code true}, se o bloco est� esgotado. {@code false}, caso contr�rio
*/
public boolean isExhausted() {
return lastReturnedValue.get() >= endOfBlock - 1;
}
@Override
public String toString() {
final long lastValue = lastReturnedValue.get();
long remaining = lastValue < startOfBlock ? endOfBlock - startOfBlock : endOfBlock - lastValue - 1;
if (remaining < 0) {
remaining = 0;
}
String debugLast = lastValue < startOfBlock ? "N/A" : "" + lastValue;
if (remaining == 0) {
debugLast = "" + (endOfBlock - 1);
}
return SequenceBlock.class.getSimpleName() + "(startOfBlock: " + startOfBlock + ", endOfBlock: " + endOfBlock + ", lastReturnedValue: " + debugLast + ", remaining: "
+ remaining + ")";
}
}