blob: 96168f52af852de35d3ed06251ee216526b93780 [file] [log] [blame]
package org.eclipse.osbp.jpa.services.history;
import java.util.Calendar;
import java.util.Date;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.EmptyRecord;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.InsertObjectQuery;
import org.eclipse.persistence.queries.QueryRedirector;
import org.eclipse.persistence.queries.ReadObjectQuery;
import org.eclipse.persistence.queries.UpdateObjectQuery;
import org.eclipse.persistence.queries.WriteObjectQuery;
import org.eclipse.persistence.sessions.Record;
import org.eclipse.persistence.sessions.Session;
/**
* Manages the versioning of historized and timedependent entities.
*/
@SuppressWarnings("serial")
public class HistorizedQueryRedirector implements QueryRedirector {
@Override
public Object invokeQuery(DatabaseQuery query, Record arguments, Session session) {
WriteObjectQuery writeObjectQuery = (WriteObjectQuery) query;
Object persistedObj = writeObjectQuery.getObject();
// the object that was persisted / merged
//
HistorizedObjectWrapper persistedObjWrapper = new HistorizedObjectWrapper(writeObjectQuery.getDescriptor(),
persistedObj);
if (persistedObjWrapper.getVersion() > 1) {
throw new IllegalArgumentException(
"Version must be 0. Changing historized records is not allowed: " + persistedObj.toString());
}
Object current = getCurrent(persistedObjWrapper, (AbstractSession) session);
if (current == null) {
persistedObjWrapper.setId_ValidFrom(createNow(persistedObjWrapper));
persistedObjWrapper.setValidUntil(getMaxDate());
persistedObjWrapper.setCurrentHist(true);
writeObjectQuery.setDoNotRedirect(true);
Object newAdr = writeObjectQuery.execute((AbstractSession) session, (AbstractRecord) arguments);
return newAdr;
} else {
// sleep 1ms for minimum time intervall between historized records
try {
Thread.sleep(1);
} catch (InterruptedException e) {
}
// update the address to be historized
long now = createNow(persistedObjWrapper);
Object histCurrentObj = getCurrentManaged(
new HistorizedObjectWrapper(writeObjectQuery.getDescriptor(), current), (AbstractSession) session);
// the current object in database with flag histCurrent = true
//
HistorizedObjectWrapper histCurrentObjWrapper = new HistorizedObjectWrapper(
writeObjectQuery.getDescriptor(), histCurrentObj);
if (query.getDescriptor().getObjectBuilder().compareObjects(persistedObj, histCurrentObj,
(AbstractSession) session)) {
return persistedObj;
}
histCurrentObjWrapper.setCurrentHist(false);
histCurrentObjWrapper.setValidUntil(now);
UpdateObjectQuery updateCurrent = new UpdateObjectQuery(histCurrentObj);
updateCurrent.setDoNotRedirect(true);
updateCurrent.setIsUserDefined(true);
updateCurrent.execute((AbstractSession) session, (AbstractRecord) arguments);
persistedObjWrapper.setId_ValidFrom(now);
persistedObjWrapper.setValidUntil(getMaxDate());
persistedObjWrapper.setCurrentHist(true);
persistedObjWrapper.setVersion((int) 0);
InsertObjectQuery insertObjectQ = new InsertObjectQuery(persistedObj);
insertObjectQ.setIsUserDefined(true);
insertObjectQ.setDoNotRedirect(true);
Object newAdr = insertObjectQ.execute((AbstractSession) session, (AbstractRecord) arguments);
return newAdr;
}
}
private long createNow(HistorizedObjectWrapper wrapper) {
if (wrapper.isCustomVersion()) {
return wrapper.getId_ValidFrom();
}
return new Date().getTime();
}
private Object getCurrent(HistorizedObjectWrapper wrapper, AbstractSession session) {
UnitOfWorkImpl uow = session.acquireNonSynchronizedUnitOfWork();
ReadObjectQuery rq = new ReadObjectQuery(wrapper.getEntityClass());
ExpressionBuilder eb = rq.getExpressionBuilder();
Expression exp = eb.get(wrapper.getIdAttName()).get(wrapper.getId_IdAttName()).equal(wrapper.getID().id)
.and(eb.get(wrapper.getCurrentHistAttName()).equal(true));
rq.setSelectionCriteria(exp);
rq.dontCheckCache();
rq.dontMaintainCache();
Object current = (Object) rq.executeInUnitOfWork(uow, EmptyRecord.getEmptyRecord());
uow.clearForClose(true);
return current;
}
private Object getCurrentManaged(HistorizedObjectWrapper wrapper, AbstractSession session) {
ReadObjectQuery rq = new ReadObjectQuery(wrapper.getEntityClass());
ExpressionBuilder eb = rq.getExpressionBuilder();
Expression exp = eb.get(wrapper.getIdAttName()).equal(wrapper.getID());
rq.setSelectionCriteria(exp);
Object current = rq.execute(session, EmptyRecord.getEmptyRecord());
return current;
}
private long getMaxDate() {
Calendar cal = Calendar.getInstance();
cal.set(2099, Calendar.DECEMBER, 31, 0, 0, 0);
cal.set(Calendar.MILLISECOND, 0);
Date maxDate = cal.getTime();
return maxDate.getTime();
}
}