package org.orienteer.bpm.camunda.handler;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.apache.wicket.util.string.Strings;
import org.camunda.bpm.engine.impl.db.ListQueryParameterObject;
import org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity;
import org.camunda.bpm.engine.impl.persistence.entity.JobEntity;
import org.camunda.bpm.engine.impl.persistence.entity.MessageEntity;
import org.camunda.bpm.engine.impl.persistence.entity.TimerEntity;
import org.camunda.bpm.engine.runtime.JobQuery;
import org.orienteer.bpm.camunda.OPersistenceSession;
import org.orienteer.bpm.camunda.handler.history.UserOperationLogEntryEventEntityHandler;
import org.orienteer.core.OClassDomain;
import org.orienteer.core.util.OSchemaHelper;
import com.github.raymanrt.orientqb.query.Clause;
import com.github.raymanrt.orientqb.query.Operator;
import com.github.raymanrt.orientqb.query.Parameter;
import com.github.raymanrt.orientqb.query.Query;
import com.orientechnologies.orient.core.metadata.schema.OType;
import com.orientechnologies.orient.core.record.impl.ODocument;
/**
* {@link IEntityHandler} for {@link JobEntity}
*/
public class JobEntityHandler extends AbstractEntityHandler<JobEntity> {
public static final String OCLASS_NAME = "BPMJob";
public JobEntityHandler() {
super(OCLASS_NAME);
}
@Override
public void applySchema(OSchemaHelper helper) {
super.applySchema(helper);
helper.domain(OClassDomain.SYSTEM);
helper.oProperty("type", OType.STRING, 10)
.oProperty("duedate", OType.DATETIME, 20)
.oProperty("lockExpirationTime", OType.DATETIME, 30)
.oProperty("lockOwner", OType.STRING, 40)
.oProperty("exclusive", OType.BOOLEAN, 50)
.oProperty("execution", OType.LINK, 60).assignVisualization("listbox")
.oProperty("processInstanceId", OType.STRING, 70)
.oProperty("processDefinition", OType.LINK, 90).assignVisualization("listbox")
.oProperty("processDefinitionKey", OType.STRING, 100)
.oProperty("retries", OType.INTEGER, 110)
.oProperty("exceptionByteArrayId", OType.STRING, 120)
.oProperty("exceptionMessage", OType.STRING, 130)
.oProperty("repeat", OType.STRING, 140)
.oProperty("jobHandlerType", OType.STRING, 150)
.oProperty("JobHandlerConfigurationRaw", OType.STRING, 160)
.oProperty("deployment", OType.LINK, 170)
.oProperty("suspensionState", OType.INTEGER, 180)
.oProperty("jobDefinitionId", OType.STRING, 190)
.oProperty("sequenceCounter", OType.LONG, 200)
.oProperty("priority", OType.LONG, 210)
.oProperty("userOperationLogEntryEvents", OType.LINKLIST, 220).assignVisualization("table");
}
@Override
public void applyRelationships(OSchemaHelper helper) {
super.applyRelationships(helper);
helper.setupRelationship(JobEntityHandler.OCLASS_NAME, "deployment", DeploymentEntityHandler.OCLASS_NAME);
helper.setupRelationship(JobEntityHandler.OCLASS_NAME, "processDefinition", ProcessDefinitionEntityHandler.OCLASS_NAME);
helper.setupRelationship(JobEntityHandler.OCLASS_NAME, "execution", ExecutionEntityHandler.OCLASS_NAME);
helper.setupRelationship(OCLASS_NAME, "userOperationLogEntryEvents", UserOperationLogEntryEventEntityHandler.OCLASS_NAME, "job");
}
@Override
public JobEntity mapToEntity(ODocument doc, JobEntity entity, OPersistenceSession session) {
if(entity==null) {
String type = doc.field("type");
if(TimerEntity.TYPE.equals(type)) entity = new TimerEntity();
else if(MessageEntity.TYPE.equals(type)) entity = new MessageEntity();
}
entity = super.mapToEntity(doc, entity, session);
String exceptionByteArrayId = doc.field("exceptionByteArrayId");
//JobEntity doesn't allow to set exceptionByteArrayId: so lets inject it.
//TODO: Fix this behavior
if(exceptionByteArrayId!=null) {
try {
Field field = JobEntity.class.getDeclaredField("exceptionByteArrayId");
field.setAccessible(true);
field.set(entity, exceptionByteArrayId);
} catch (Exception e) {
logger.warn("Setting exceptionByteArrayId doesn't work", e);
}
}
return entity;
}
@Statement
public List<JobEntity> selectJobByQueryCriteria(OPersistenceSession session, JobQuery query) {
return query(session, query);
}
@Statement
public List<JobEntity> selectJobsByConfiguration(OPersistenceSession session, ListQueryParameterObject query) {
Map<String, Object> params = (Map<String, Object>) query.getParameter();
String config = (String) params.get("handlerConfiguration");
String followUpConfig = (String) params.get("handlerConfigurationWithFollowUpJobCreatedProperty");
String type = (String) params.get("handlerType");
List<String> args = new ArrayList<>();
Query q = new Query().from(getSchemaClass());
q.where(Clause.clause("jobHandlerType", Operator.EQ, Parameter.PARAMETER));
args.add(type);
Clause eqConfig = Clause.clause("JobHandlerConfigurationRaw", Operator.EQ, Parameter.PARAMETER);
if(Strings.isEmpty(followUpConfig)) {
q.where(eqConfig);
args.add(config);
} else {
q.where(Clause.or(eqConfig, eqConfig));
args.add(config);
args.add(followUpConfig);
}
return queryList(session, q.toString(), args.toArray());
}
@Statement
public List<JobEntity> selectExclusiveJobsToExecute(OPersistenceSession session, ListQueryParameterObject query) {
Map<String, Object> params = (Map<String, Object>) query.getParameter();
Date now=(Date) params.get("now");
int maxResults=query.getMaxResults();
return queryList(session, "select from "+getSchemaClass()+
" where retries > 0"
+ " and (duedate is null or duedate <= ?)"
+ " and (lockOwner is null or lockExpirationTime < ?)"
+ " and exclusive = true"
+ " and suspensionState = 1"
+ " LIMIT ?", now, now, maxResults);
}
@Statement
public List<JobEntity> selectNextJobsToExecute(OPersistenceSession session, ListQueryParameterObject query) {
Map<String, Object> params = (Map<String, Object>) query.getParameter();
Date now=(Date) params.get("now");
int maxResults=query.getMaxResults();
String orderBy = query.getOrderBy();
return queryList(session, "select from "+getSchemaClass()+
" where retries > 0"
+ " and (duedate is null or duedate <= ?)"
+ " and (lockOwner is null or lockExpirationTime < ?)"
+ " and suspensionState = 1"
+ (Strings.isEmpty(orderBy)?" order by "+orderBy:"")
+ " LIMIT ?", now, now, maxResults);
}
@Statement
public JobEntity selectJob(OPersistenceSession session, String id) {
return read(id, session);
}
@Statement
public List<JobEntity> selectJobsByExecutionId(OPersistenceSession session, ListQueryParameterObject query) {
return queryList(session, "select from "+getSchemaClass()+" where execution.id = ?", query.getParameter());
}
}