package org.openlca.io.refdata;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.concurrent.atomic.AtomicLong;
import javax.persistence.Table;
import org.openlca.core.database.IDatabase;
import org.openlca.core.database.NativeSql;
import org.openlca.core.model.ModelType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class Seq {
private final ModelType[] TYPES = {
ModelType.LOCATION,
ModelType.CATEGORY,
ModelType.UNIT,
ModelType.UNIT_GROUP,
ModelType.FLOW_PROPERTY,
ModelType.FLOW,
ModelType.CURRENCY,
ModelType.IMPACT_CATEGORY,
ModelType.IMPACT_METHOD,
ModelType.NW_SET
};
private Logger log = LoggerFactory.getLogger(getClass());
private IDatabase db;
private final HashMap<String, Long>[] sequences;
private final HashSet<String>[] inDatabase;
private long seqCount = 0;
@SuppressWarnings("unchecked")
public Seq(IDatabase db) {
this.db = db;
sequences = new HashMap[ModelType.values().length];
inDatabase = new HashSet[ModelType.values().length];
for (ModelType type : TYPES)
initType(type);
initSeqCount();
}
private void initType(ModelType type) {
Table table = type.getModelClass().getAnnotation(Table.class);
String query = "select id, ref_id from " + table.name();
HashMap<String, Long> seq = new HashMap<>();
HashSet<String> inDb = new HashSet<>();
try {
NativeSql.on(db).query(query, result -> {
String refId = result.getString(2);
seq.put(refId, result.getLong(1));
inDb.add(refId);
return true;
});
} catch (Exception e) {
log.error("failed to initialize sequence map for " + type, e);
}
sequences[type.ordinal()] = seq;
inDatabase[type.ordinal()] = inDb;
}
private void initSeqCount() {
AtomicLong seq = new AtomicLong(0L);
String query = "select seq_count from sequence";
try {
NativeSql.on(db).query(query, result -> {
seq.set(result.getLong(1));
return true;
});
} catch (Exception e) {
log.error("failed to get sequence count", e);
}
this.seqCount = seq.get() + 500L;
}
public boolean isInDatabase(ModelType type, String refId) {
if (refId == null)
return false;
return inDatabase[type.ordinal()].contains(refId);
}
/**
* Get the allocated integer id for the given reference ID. If there is no
* such ID a new one is allocated.
*/
public long get(ModelType type, String refId) {
if (refId == null)
return next();
HashMap<String, Long> map = sequences[type.ordinal()];
Long i = map.get(refId);
if (i != null)
return i;
seqCount++;
map.put(refId, seqCount);
return seqCount;
}
public long next() {
return ++seqCount;
}
public void write() throws Exception {
String sql = "UPDATE sequence SET SEQ_COUNT = " + next();
NativeSql.on(db).batchUpdate(Arrays.asList(sql));
}
}