package org.dsrg.service;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.xml.xpath.XPathExpressionException;
import org.dsrg.soenea.service.UniqueIdFactory;
import org.korsakow.ide.DataRegistry;
import org.korsakow.services.exception.BetterSQLException;
import org.w3c.dom.NodeList;
/**
* This is a factory for generating unique Id's. It works on a dedicated ID table.
*
* Note, this sucker doesn't lock tables at the moment! Beware! (sqlite doesn't seem to support it)
*
* @author dave
*/
public class IdTableUniqueIdFactory extends UniqueIdFactory {
private static int BUFFER_SIZE = 50;
private final List<Long> availableIds = new ArrayList<Long>();
private long max_id;
public IdTableUniqueIdFactory(String idTable, String idField)
{
}
/**
* Advances the max id by the specified amount, effectively reserving that many ids in the range [return-value, return-value+delta)
* By simply advancing and not setting, we avoid the possibility of race conditions.
* @return the old max id, the base of the reserved id range
*/
public synchronized long advanceMaxId(long delta)
{
long oldmax = max_id;
availableIds.clear();
max_id += delta;
return oldmax;
}
@Override
public synchronized long getId(String table, String field) throws SQLException
{
try {
return getId();
} catch (XPathExpressionException e) {
throw new BetterSQLException(e);
}
}
public synchronized long getId() throws XPathExpressionException
{
// notice how we keep the max_id between calls. its important that we dont clear it
// since the setMaxId functionality relies on it
if(availableIds.isEmpty()) {
// String result = DataRegistry.getHelper().xpathAsString("/korsakow/descendant::*/id[not(text() <= /korsakow/descendant::*/id) and not(text() <= /korsakow/descendant::*/id)]");
NodeList list = DataRegistry.getHelper().xpathAsNodeList("/korsakow/descendant::*/id");
int length = list.getLength();
for (int i = 0; i < length; ++i) {
try {
long id = Long.parseLong(list.item(i).getTextContent());
if (id > max_id)
max_id = id;
} catch (NumberFormatException e) {
continue;
}
}
List<Long> ids = new ArrayList<Long>();
for (int i = 0; i < BUFFER_SIZE; ++i) {
++max_id;
ids.add(max_id);
}
availableIds.addAll(ids);
}
// Logger.getLogger(IdTableUniqueIdFactory.class).
return availableIds.remove(0);
}
}