package xapi.dev.source;
import xapi.fu.Lazy;
import xapi.time.X_Time;
import xapi.time.api.Moment;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Need a unique name?
*
* Don't want to be bothered to manage state across multiple compiles?
*
* If so, then NameGen is for you!
*
* If you create an instance with a given seed,
* you will get deterministic names when called in a deterministic manner.
*
* If you are lazy and just want globally unique identifiers across a given
* run of a jvm, then use the static factory method to get a shared NamePool.
*
* Created by James X. Nelson (james @wetheinter.net) on 8/20/16.
*/
public class NameGen {
private static final Lazy<NameGen> GLOBAL = Lazy.deferSupplier(NameGen::new, 0xcafebabe);
public static NameGen getGlobal() {
return GLOBAL.out1();
}
private final AtomicInteger cnt;
public NameGen() {
this((int)(Math.random() * Integer.MAX_VALUE / 2));
}
public NameGen(int seed) {
cnt = new AtomicInteger(Math.abs(seed));
}
public String newName(NameType type) {
switch (type) {
case CSS_CLASS:
return newClass();
case ID:
return newId();
case ENCODED_TIMESTAMP:
return newTimestamp();
default:
throw new UnsupportedOperationException("Type " + type + " not supported.");
}
}
protected int nextInt() {
return cnt.getAndUpdate(i->i==Integer.MAX_VALUE ? 1 : i+1);
}
protected String nextString() {
return Integer.toString(nextInt(), 36);
}
protected String classPrefix() {
return "cls-";
}
protected String idPrefix() {
return "id";
}
public String newClass() {
return classPrefix() + nextString();
}
public String newId() {
return idPrefix() + nextString();
}
public String newName(String prefix) {
return prefix + nextString();
}
public String newTimestamp() {
// nowPlusOne uses a double that is a fractional millisecond count;
// when called in rapid succession, it will create the "minimally largest" double
// that can fit within the precision used by the current timestamp.
// If the timestamp should become larger than the current time in millis,
// this will actually park
final Moment now = X_Time.nowPlusOne();
long time = Double.doubleToLongBits(now.millis());
return Long.toString(time, 36);
}
public enum NameType {
CSS_CLASS,
ID,
ENCODED_TIMESTAMP
}
}