package pl.net.bluesoft.rnd.processtool.model; import static pl.net.bluesoft.util.lang.FormatUtil.nvl; import java.util.Date; import java.util.HashSet; import java.util.Set; import javax.persistence.*; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.Parameter; import javax.persistence.Table; import org.hibernate.annotations.*; import pl.net.bluesoft.rnd.processtool.model.config.ProcessDefinitionConfig; import pl.net.bluesoft.rnd.pt.utils.lang.Lang2; /** * Entity representing process instance data. It should be persisted in appropriate database. * Custom processes can reference this class. * * @author tlipski@bluesoft.net.pl */ @Entity @Table(name="pt_process_instance") public class ProcessInstance extends AbstractPersistentEntity { @Id @GeneratedValue(generator = "idGenerator") @GenericGenerator( name = "idGenerator", strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator", parameters = { @org.hibernate.annotations.Parameter(name = "initial_value", value = "" + 1), @org.hibernate.annotations.Parameter(name = "value_column", value = "_DB_ID"), @org.hibernate.annotations.Parameter(name = "sequence_name", value = "DB_SEQ_ID_PROC_INST") } ) @Column(name = "id") protected Long id; private String externalKey; private String internalId; private String definitionName; private String state; private String description; private String keyword; @Enumerated(EnumType.STRING) private ProcessStatus status; @Transient private String taskId; @Transient private String[] assignees; @Transient private String[] taskQueues; @Transient private BpmTask[] activeTasks; private Boolean running; private Date createDate; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name="creator_id") private UserData creator; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name="definition_id") private ProcessDefinitionConfig definition; @OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY) @JoinColumn(name="process_instance_id") private Set<ProcessInstanceAttribute> processAttributes = new HashSet<ProcessInstanceAttribute>(); @OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY) @JoinColumn(name="process_instance_id") private Set<ProcessInstanceLog> processLogs = new HashSet<ProcessInstanceLog>(); @OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY) @JoinColumn(name="parent_id") private Set<ProcessInstance> children = new HashSet<ProcessInstance>(); @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name="parent_id") private ProcessInstance parent; /** Owners of the process. Owner is diffrent then process creator. Process can have many owners */ @ElementCollection(fetch = FetchType.LAZY) @CollectionTable(name = "pt_process_instance_owners", joinColumns = @JoinColumn(name = "process_id")) private Set<String> owners = new HashSet<String>(); @Transient private Set<ProcessInstanceAttribute> toDelete; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public ProcessInstance getRootProcessInstance() { ProcessInstance parentProcess = this; while(parentProcess.getParent() != null){ parentProcess = parentProcess.getParent(); } return parentProcess; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getKeyword() { return keyword; } public void setKeyword(String keyword) { this.keyword = keyword; } public ProcessInstance(String externalKey, UserData creator, String definionName) { this.externalKey = externalKey; this.creator = creator; this.definitionName = definionName; this.createDate = new Date(); } public ProcessInstance() { // TODO Auto-generated constructor stub } public String getExternalKey() { if(externalKey == null && parent != null){ return parent.getExternalKey(); } return externalKey; } public String getOwnExternalKey() { return externalKey; } public void setExternalKey(String externalKey) { this.externalKey = externalKey; } public String getInternalId() { return internalId; } public void setInternalId(String internalId) { this.internalId = internalId; } public Date getCreateDate() { return createDate; } public void setCreateDate(Date createDate) { this.createDate = createDate; } public UserData getCreator() { return creator; } public void setCreator(UserData creator) { this.creator = creator; } public String getDefinitionName() { return definitionName; } public void setDefinitionName(String definitionName) { this.definitionName = definitionName; } public String getState() { return state; } public void setState(String state) { this.state = state; } public Set<String> getOwners() { return owners; } public void setOwners(Set<String> ownersLogins) { this.owners = ownersLogins; } public void addOwner(String ownerLogin) { this.owners.add(ownerLogin); } public void removeOwner(String ownerLogin) { this.owners.remove(ownerLogin); } public Set<ProcessInstanceAttribute> getProcessAttributes() { if (processAttributes == null) processAttributes = new HashSet<ProcessInstanceAttribute>(); return processAttributes; } public void setProcessAttributes(Set<ProcessInstanceAttribute> processAttributes) { this.processAttributes = processAttributes; } public ProcessDefinitionConfig getDefinition() { return definition; } public void setDefinition(ProcessDefinitionConfig definition) { this.definition = definition; } public void removeAttribute(ProcessInstanceAttribute attr) { attr.setProcessInstance(null); processAttributes.remove(attr); if (attr.getId() > 0) { if (toDelete == null) { toDelete = new HashSet<ProcessInstanceAttribute>(); } toDelete.add(attr); } } public Set<ProcessInstanceAttribute> getToDelete() { return toDelete; } public void addAttribute(ProcessInstanceAttribute attr) { attr.setProcessInstance(this); processAttributes.add(attr); } public String getTaskId() { return taskId; } public void setTaskId(String taskId) { this.taskId = taskId; } public Set<ProcessInstanceLog> getProcessLogs() { return processLogs; } public void setProcessLogs(Set<ProcessInstanceLog> processLogs) { this.processLogs = processLogs; } public void addProcessLog(ProcessInstanceLog log) { log.setProcessInstance(this); processLogs.add(log); } public ProcessInstanceAttribute findAttributeByKey(String key) { Set<ProcessInstanceAttribute> attrs = getProcessAttributes(); for (ProcessInstanceAttribute pia : attrs) { if (pia.getKey() != null && pia.getKey().equals(key)) { return pia; } } return null; } public <T extends ProcessInstanceAttribute> T findAttributeByClass(Class<T> clazz) { Set<ProcessInstanceAttribute> attrs = getProcessAttributes(); for (ProcessInstanceAttribute pia : attrs) { if (clazz.isAssignableFrom(pia.getClass())) { return (T) pia; } } return null; } public <T extends ProcessInstanceAttribute> T findOrCreateAttribute(Class<T> attrClass) { T attribute = findAttributeByClass(attrClass); if(attribute == null) { try { attribute = attrClass.newInstance(); addAttribute(attribute); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } return attribute; } public <T extends ProcessInstanceAttribute> Set<T> findAttributesByClass(Class<T> clazz) { Set<T> result = new HashSet<T>(); Set<ProcessInstanceAttribute> attrs = getProcessAttributes(); for (ProcessInstanceAttribute pia : attrs) { if (clazz.isAssignableFrom(pia.getClass())) { result.add((T) pia); } } return result; } public String getSimpleAttributeValue(String key) { ProcessInstanceAttribute attr = findAttributeByKey(key); return attr != null ? ((ProcessInstanceSimpleAttribute)attr).getValue() : null; } public String getSimpleAttributeValue(String key, String default_) { ProcessInstanceAttribute attr = findAttributeByKey(key); return attr != null ? ((ProcessInstanceSimpleAttribute)attr).getValue() : default_; } public String getInheritedSimpleAttributeValue(String key) { return getInheritedSimpleAttributeValue(key, null); } public String getInheritedSimpleAttributeValue(String key, String default_) { for (ProcessInstance pi = this; pi != null; pi = pi.getParent()) { ProcessInstanceAttribute attr = findAttributeByKey(key); if (attr instanceof ProcessInstanceSimpleAttribute) { return ((ProcessInstanceSimpleAttribute)attr).getValue(); } } return default_; } public void setSimpleAttribute(String key, String value) { ProcessInstanceSimpleAttribute attr = (ProcessInstanceSimpleAttribute)findAttributeByKey(key); if (attr != null) { attr.setValue(value); } else { addAttribute(new ProcessInstanceSimpleAttribute(key, value)); } } public void addDictionaryAttributeItem(String dictionary, String key, String value){ ProcessInstanceDictionaryAttribute attr = (ProcessInstanceDictionaryAttribute)findAttributeByKey(dictionary); if (attr == null) { addAttribute(attr = new ProcessInstanceDictionaryAttribute(dictionary)); } attr.put(key, value); } public String[] getAssignees() { return nvl(assignees, new String[] { }); } public void setAssignees(String... assignees) { this.assignees = assignees; } public String[] getTaskQueues() { return nvl(taskQueues, new String[] { }); } public void setTaskQueues(String... taskQueues) { this.taskQueues = taskQueues; } public Boolean getRunning() { return nvl(running,true); } public void setRunning(Boolean running) { this.running = running; } public ProcessStatus getStatus() { return status; } public void setStatus(ProcessStatus status) { this.status = status; } public BpmTask[] getActiveTasks() { return activeTasks; } public void setActiveTasks(BpmTask[] activeTasks) { this.activeTasks = Lang2.noCopy(activeTasks); } public Set<ProcessInstance> getChildren() { return children; } public void setChildren(Set<ProcessInstance> children) { this.children = children; } public ProcessInstance getParent() { return parent; } public void setParent(ProcessInstance parent) { this.parent = parent; } /** Method checks if the process is in running or new state */ public boolean isProcessRunning() { if(getStatus() == null) return false; if(getRunning() != null && !getRunning()) return false; return getStatus().equals(ProcessStatus.NEW) || getStatus().equals(ProcessStatus.RUNNING); } /** Method check, if the given user login is in assigness list */ public boolean isAssignee(String assigneeLogin) { if(assignees == null) return false; for(String login: assignees) if(login.equals(assigneeLogin)) return true; return false; } @Override public String toString() { return "ProcessInstance [externalKey=" + getExternalKey() + ", internalId=" + internalId + "]"; } /** Check if process is subprocess (has parent process) */ public boolean isSubprocess() { return getParent() != null; } }