package sushi.process;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityTransaction;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Query;
import javax.persistence.Table;
import sushi.event.SushiEvent;
import sushi.event.SushiEventType;
import sushi.event.collection.SushiMapTree;
import sushi.persistence.Persistable;
import sushi.persistence.Persistor;
/**
* Represents an instance of a process. It is unique per process by the values of the correlation attributes.
* References the events belonging to the process instance and holds a timer event if correlation over time is enabled.
*/
@Entity
@Table(name = "ProcessInstance")
public class SushiProcessInstance extends Persistable implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
private int ID;
@ManyToMany(cascade=CascadeType.MERGE)
private List<SushiEvent> events;
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="MapTreeID")
private SushiMapTree<String, Serializable> correlationAttributesAndValues;
@OneToOne(cascade=CascadeType.MERGE)
private SushiEvent timerEvent;
@Column(name="progress")
private int progress;
/**
* JPA-default constructor.
*/
public SushiProcessInstance() {
this.ID = 0;
this.events = new ArrayList<SushiEvent>();
this.correlationAttributesAndValues = new SushiMapTree<String, Serializable>();
}
/**
* Constructor
*
* @param correlationAttributesAndValues map of attribute keys and values -
* key must be the expression of the attribute (e.g. location for a root attribute,
* vehicle_information.railway for a second level attribute with vehicle_information as parent)
*/
public SushiProcessInstance(SushiMapTree<String, Serializable> correlationAttributesAndValues) {
this();
this.correlationAttributesAndValues = correlationAttributesAndValues;
}
/**
* Returns the associated {@link SushiEvent}s.
* @return
*/
public List<SushiEvent> getEvents() {
return events;
}
/**
* Sets the associated {@link SushiEvent}s.
* @return
*/
public void setEvents(List<SushiEvent> events) {
this.events = events;
}
/**
* Adds an {@link SushiEvent} to the associated events.
* @return
*/
public boolean addEvent(SushiEvent event) {
if(!events.contains(event)){
return events.add(event);
}
return false;
}
/**
* Removes an {@link SushiEvent} from the associated events.
* @return
*/
public boolean removeEvent(SushiEvent event) {
return events.remove(event);
}
public int getID() {
return ID;
}
public void setID(int iD) {
ID = iD;
}
public SushiMapTree<String, Serializable> getCorrelationAttributesAndValues() {
return correlationAttributesAndValues;
}
public void setCorrelationAttributesAndValues(SushiMapTree<String, Serializable> correlationAttributesAndValues) {
this.correlationAttributesAndValues = correlationAttributesAndValues;
}
/**
* Returns the {@link SushiProcess} for this instance of it from the database.
* @return
*/
public SushiProcess getProcess() {
List<SushiProcess> processes = SushiProcess.findByProcessInstanceID(ID);
if(!processes.isEmpty()){
return SushiProcess.findByProcessInstanceID(ID).get(0);
}
return null;
}
/**
* Returns all {@link SushiProcessInstance}s from the database.
* @return
*/
@SuppressWarnings("unchecked")
public static List<SushiProcessInstance> findAll() {
Query q = Persistor.getEntityManager().createNativeQuery("SELECT * FROM ProcessInstance", SushiProcessInstance.class);
return q.getResultList();
}
/**
* Returns all {@link SushiProcessInstance}s from the database, which have the given correlation attribute.
* @return
*/
@SuppressWarnings("unchecked")
public static List<SushiProcessInstance> findByCorrelationAttribute(String correlationAttribute) {
Query query = Persistor.getEntityManager().createNativeQuery("" +
"SELECT * " +
"FROM ProcessInstance " +
"WHERE MapTreeID IN (" +
"SELECT SushiMapTree_SushiMapID " +
"FROM SushiMapTree_SushiMapTreeRootElements " +
"WHERE treeRootElements_ID IN (" +
"SELECT ID " +
"FROM SushiMapElement " +
"WHERE MapKey = '" + correlationAttribute + "'))", SushiProcessInstance.class);
// "Select Id " +
// "FROM CorrelationAttributesAndValues " +
// "WHERE CorrelationAttribute = '" + correlationAttribute + "')", SushiProcessInstance.class);
return query.getResultList();
}
/**
* Returns all {@link SushiProcessInstance}s from the database, which have the given correlation attribute and associate value.
* @return
*/
public static List<SushiProcessInstance> findByCorrelationAttributeAndValue(String correlationAttribute, Serializable correlationValue) {
Query query = Persistor.getEntityManager().createNativeQuery("" +
"Select * FROM ProcessInstance " +
"WHERE MapTreeID IN (" +
"SELECT SushiMapTree_SushiMapID " +
"FROM SushiMapTree_SushiMapTreeRootElements " +
"WHERE treeRootElements_ID IN (" +
"SELECT ID " +
"FROM SushiMapElement " +
"WHERE MapKey = '" + correlationAttribute + "' AND MapValue = '" + correlationValue + "'))", SushiProcessInstance.class);
// "Select Id " +
// "FROM CorrelationAttributesAndValues " +
// "WHERE CorrelationAttribute = '" + correlationAttribute + "')", SushiProcessInstance.class);
List<SushiProcessInstance> returnList= new ArrayList<SushiProcessInstance>();
for (Object instance : query.getResultList()) {
SushiProcessInstance processInstance = (SushiProcessInstance) instance;
if (processInstance.getCorrelationAttributesAndValues().get(correlationAttribute).equals(correlationValue))
returnList.add(processInstance);
}
return returnList;
}
/**
* Returns the {@link SushiProcessInstance} from the database, which has the given ID, if any.
* @return
*/
@SuppressWarnings("unchecked")
public static SushiProcessInstance findByID(int ID){
Query query = Persistor.getEntityManager().createNativeQuery("" +
"SELECT * " +
"FROM ProcessInstance " +
"WHERE ID = '" + ID + "'", SushiProcessInstance.class);
List<SushiProcessInstance> processInstances = query.getResultList();
if(!processInstances.isEmpty()){
return processInstances.get(0);
}else{
return null;
}
}
@SuppressWarnings("unchecked")
public static List<SushiProcessInstance> findByIDGreaterThan(int ID){
Query query = Persistor.getEntityManager().createNativeQuery("" +
"SELECT * " +
"FROM ProcessInstance " +
"WHERE ID > '" + ID + "'", SushiProcessInstance.class);
return query.getResultList();
}
@SuppressWarnings("unchecked")
public static List<SushiProcessInstance> findByIDLessThan(int ID){
Query query = Persistor.getEntityManager().createNativeQuery("" +
"SELECT * " +
"FROM ProcessInstance " +
"WHERE ID < '" + ID + "'", SushiProcessInstance.class);
return query.getResultList();
}
/**
* Returns all {@link SushiProcessInstance}es from the database, which contain the given {@link SushiEvent}.
* @return
*/
@SuppressWarnings("unchecked")
public static List<SushiProcessInstance> findByContainedEvent(SushiEvent event){
Query query = Persistor.getEntityManager().createNativeQuery("" +
"SELECT * " +
"FROM ProcessInstance " +
"WHERE ID IN (" +
"Select processInstances_ID " +
"FROM ProcessInstance_Event " +
"WHERE events_ID = '" + event.getID()+ "')", SushiProcessInstance.class);
return query.getResultList();
}
/**
* Returns all {@link SushiProcessInstance}es from the database, which are associated to the given {@link SushiProcess}.
* @return
*/
@SuppressWarnings("unchecked")
public static List<SushiProcessInstance> findByProcess(SushiProcess process){
Query query = Persistor.getEntityManager().createNativeQuery("" +
"Select * " +
"FROM ProcessInstance " +
"WHERE ID IN (" +
"Select processInstances_ID " +
"FROM Process_ProcessInstance " +
"WHERE SushiProcess_ID = '" + process.getID()+ "')", SushiProcessInstance.class);
return query.getResultList();
}
/**
* Returns all {@link SushiProcessInstance}es from the database, which contain the given {@link SushiEventType}.
* @return
*/
@SuppressWarnings("unchecked")
public static List<SushiProcessInstance> findByContainedEventType(SushiEventType eventType){
Query query = Persistor.getEntityManager().createNativeQuery("" +
"SELECT * " +
"FROM ProcessInstance " +
"WHERE ID IN (" +
"SELECT processInstances_ID " +
"FROM ProcessInstance_Event " +
"WHERE events_ID IN (" +
"SELECT ID " +
"FROM Event " +
"WHERE EVENTTYPE_ID = '" + eventType.getID() + "'))", SushiProcessInstance.class);
return query.getResultList();
}
@Override
public SushiProcessInstance save() {
return (SushiProcessInstance) super.save();
}
public static boolean save(ArrayList<SushiProcessInstance> processInstances) {
try {
Persistor.getEntityManager().getTransaction().begin();
for (SushiProcessInstance processInstance : processInstances) {
Persistor.getEntityManager().persist(processInstance);
}
Persistor.getEntityManager().getTransaction().commit();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* Deletes the specified process instance from the database.
* @return
*/
@Override
public SushiProcessInstance remove() {
List<SushiEvent> events = SushiEvent.findByProcessInstance(this);
for(SushiEvent event : events){
event.removeProcessInstance(this);
event.save();
}
List<SushiProcess> processes = SushiProcess.findByProcessInstance(this);
for(SushiProcess process : processes){
process.removeProcessInstance(this);
process.save();
}
return (SushiProcessInstance) super.remove();
}
/**
* Deletes the specified eventtypes from the database.
* @return
*/
public static boolean remove(List<SushiProcessInstance> processInstances) {
boolean removed = true;
List<SushiProcessInstance> processInstancesCopy = new ArrayList<SushiProcessInstance>(processInstances);
Iterator<SushiProcessInstance> iterator = processInstancesCopy.iterator();
while (iterator.hasNext()) {
removed = iterator.next().remove() != null;
}
return removed;
}
public static void removeAll() {
for(SushiProcessInstance actualInstance : SushiProcessInstance.findAll()){
List<SushiProcess> processes = SushiProcess.findByProcessInstance(actualInstance);
for(SushiProcess process : processes){
process.removeProcessInstance(actualInstance);
process.save();
}
List<SushiEvent> events = SushiEvent.findByProcessInstance(actualInstance);
for(SushiEvent event : events){
event.removeProcessInstance(actualInstance);
event.save();
}
}
try {
EntityTransaction entr = Persistor.getEntityManager().getTransaction();
entr.begin();
Query query = Persistor.getEntityManager().createQuery("DELETE FROM SushiProcessInstance");
int deleteRecords = query.executeUpdate();
entr.commit();
System.out.println(deleteRecords + " records are deleted.");
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
public SushiEvent getTimerEvent() {
return timerEvent;
}
public void setTimerEvent(SushiEvent timerEvent) {
this.timerEvent = timerEvent;
}
public int getProgress() {
return this.progress;
}
public void setProgress(int percentage) {
if(percentage > 100) percentage = 100;
if(percentage < 0) percentage = 0;
this.progress = percentage;
this.merge();
}
public void addToProgress(int percentage) {
this.progress += percentage;
if(progress > 100) progress = 100;
if(progress < 0) progress = 0;
this.merge();
}
@Override
public String toString() {
return "Process Instance " + this.ID;
}
}