temper.core.Generator Maven / Gradle / Ivy
package temper.core;
import java.util.function.Supplier;
import java.util.Objects;
/**
* A supplier of {@link Generator.Result results}.
*
* Generator is monotonic; after the first time {@link Generator#getNext} returns a
* {@link Generator.DoneResult} it will do every time *next* is called for that generator.
*
* Closing releases resources associated with computing subsequent results.
*/
public abstract class Generator implements AutoCloseable, Supplier> {
private boolean done;
protected abstract Result getNext();
/**
* Computes the next result.
*
* @return {@link DoneResult} if {@link #getDone}() is true.
*/
@Override
public final Result get() {
if (done) {
return DoneResult.get();
} else {
boolean gotValueResult = false;
try {
Result result = getNext();
gotValueResult = result instanceof ValueResult;
return result;
} finally {
if (!gotValueResult) {
done = true;
}
}
}
}
/**
* May be overridden to release resources needed by {@link #getNext()}
* but should call `super.close()` to mark done so that {@link #getNext()}
* will not be called again.
*/
@Override
public void close() {
done = true;
}
/**
* True if there are no more results, either because {@link AutoCloseable#close}
* was called or because {@link #getNext} returned a {@link DoneResult} some time in
* the past.
*/
public final boolean getDone() {
return done;
}
public static abstract class Result {
Result() {}
}
/**
* A result from {@link Generator#getNext} that holds a value and indicates
* that getting another result might yield more.
*/
public static final class ValueResult extends Result {
public final T value;
public ValueResult(T value) { this.value = value; }
@Override public String toString() { return "ValueResult(" + value + ")"; }
/** ValueResults have structural equality. */
@Override public boolean equals(Object other) {
return other instanceof ValueResult &&
Objects.equals(this.value, ((ValueResult) other).value);
}
@Override public int hashCode() {
return 0x682a14f3 ^ Objects.hashCode(value);
}
}
/** A singleton that indicates a {@link Generator} will produce no more results. */
public static final class DoneResult extends Result<@Nullable Object> {
private DoneResult() {}
public static final DoneResult singleton = new DoneResult();
public static Result get() {
// DoneResult does not depend on its super types's type parameter,
// and there can exist no subclasses of it which could.
@SuppressWarnings("unchecked")
Result doneResult = (Result) singleton;
return doneResult;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy