/* * eGov suite of products aim to improve the internal efficiency,transparency, * accountability and the service delivery of the government organizations. * * Copyright (C) <2015> eGovernments Foundation * * The updated version of eGov suite of products as by eGovernments Foundation * is available at http://www.egovernments.org * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/ or * http://www.gnu.org/licenses/gpl.html . * * In addition to the terms of the GPL license to be adhered to in using this * program, the following additional terms are to be complied with: * * 1) All versions of this program, verbatim or modified must carry this * Legal Notice. * * 2) Any misrepresentation of the origin of the material is prohibited. It * is required that all modified versions of this material be marked in * reasonable ways as different from the original version. * * 3) This license does not grant any rights to any user of the program * with regards to rights under trademark law for use of the trade names * or trademarks of eGovernments Foundation. * * In case of any queries, you can reach eGovernments Foundation at contact@egovernments.org. */ package org.egov.infra.workflow.entity; import org.egov.infra.admin.master.entity.User; import org.egov.infra.exception.ApplicationRuntimeException; import org.egov.infra.persistence.entity.AbstractAuditable; import org.egov.infra.workflow.entity.State.StateStatus; import org.egov.infra.workflow.entity.contract.StateInfoBuilder; import org.egov.pims.commons.Position; import org.egov.search.domain.Searchable; import org.hibernate.envers.Audited; import org.hibernate.envers.RelationTargetAuditMode; import javax.persistence.CascadeType; import javax.persistence.FetchType; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.MappedSuperclass; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.LinkedList; import java.util.List; import static org.apache.commons.lang3.StringUtils.EMPTY; @MappedSuperclass @Searchable public abstract class StateAware extends AbstractAuditable { private static final long serialVersionUID = 5776408218810221246L; @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinColumn(name = "STATE_ID") private State state; /** * Need to overridden by the implementing class to give details about the State <I>Used by Inbox to fetch the State Detail at * runtime</I> * * @return String Detail */ public abstract String getStateDetails(); /** * To set the Group Link, Any State Aware Object which needs Grouping should override this method **/ public String myLinkId() { return getId().toString(); } @Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED) public State getState() { return state; } protected void setState(final State state) { this.state = state; } public final State getCurrentState() { return state; } public final List<StateHistory> getStateHistory() { return state == null ? Collections.emptyList() : new LinkedList<>(state.getHistory()); } public final String getStateType() { return this.getClass().getSimpleName(); } public final boolean stateIsNew() { return hasState() && getCurrentState().isNew(); } public final boolean stateIsEnded() { return hasState() && getCurrentState().isEnded(); } public final boolean stateInProgress() { return hasState() && getState().getStatus().equals(StateStatus.STARTED) || getState().getStatus().equals(StateStatus.INPROGRESS); } public final boolean hasState() { return getCurrentState() != null; } public final StateAware transition() { if (hasState()) { state.addStateHistory(new StateHistory(state)); state.setStatus(StateStatus.INPROGRESS); resetState(); } return this; } public final StateAware transition(final boolean clone) { if (hasState() && clone) { state.addStateHistory(new StateHistory(state)); state.setStatus(StateStatus.INPROGRESS); } else transition(); return this; } public final StateAware start() { if (hasState()) throw new ApplicationRuntimeException("Workflow already started state."); else { state = new State(); state.setType(getStateType()); state.setStatus(StateStatus.STARTED); state.setValue(State.DEFAULT_STATE_VALUE_CREATED); state.setComments(State.DEFAULT_STATE_VALUE_CREATED); } return this; } public final StateAware end() { if (stateIsEnded()) throw new ApplicationRuntimeException("Workflow already ended state."); else { state.setValue(State.DEFAULT_STATE_VALUE_CLOSED); state.setStatus(StateStatus.ENDED); state.setComments(State.DEFAULT_STATE_VALUE_CLOSED); } return this; } public final StateAware reopen(final boolean clone) { if (stateIsEnded()) { final StateHistory stateHistory = new StateHistory(state); stateHistory.setValue(State.STATE_REOPENED); state.setStatus(StateStatus.INPROGRESS); state.addStateHistory(stateHistory); if (!clone) resetState(); } else throw new ApplicationRuntimeException("Workflow not ended."); return this; } public final StateAware reinitiateTransition() { if (state != null && !stateIsEnded()) throw new ApplicationRuntimeException("Could not reinitiate Workflow, existing workflow not ended."); else state = null; return this; } public final StateAware withOwner(final User owner) { state.setOwnerUser(owner); return this; } public final StateAware withOwner(final Position owner) { state.setOwnerPosition(owner); return this; } public final StateAware withInitiator(final Position owner) { state.setInitiatorPosition(owner); return this; } public final StateAware withStateValue(final String currentStateValue) { state.setValue(currentStateValue); return this; } public final StateAware withNextAction(final String nextAction) { state.setNextAction(nextAction); return this; } public final StateAware withComments(final String comments) { state.setComments(comments); return this; } public final StateAware withNatureOfTask(final String natureOfTask) { state.setNatureOfTask(natureOfTask); return this; } public final StateAware withExtraInfo(final String extraInfo) { state.setExtraInfo(extraInfo); return this; } public final StateAware withDateInfo(final Date dateInfo) { state.setDateInfo(dateInfo); return this; } public final StateAware withExtraDateInfo(final Date extraDateInfo) { state.setExtraDateInfo(extraDateInfo); return this; } public final StateAware withSenderName(final String senderName) { state.setSenderName(senderName); return this; } private void resetState() { state.setComments(EMPTY); state.setDateInfo(null); state.setExtraDateInfo(null); state.setExtraInfo(EMPTY); state.setNextAction(EMPTY); state.setValue(EMPTY); state.setSenderName(EMPTY); state.setNatureOfTask(EMPTY); state.setOwnerUser(null); state.setOwnerPosition(null); state.setInitiatorPosition(null); } public static Comparator<? super StateAware> byCreatedDate() { return (stateAware_1, stateAware_2) -> { int returnVal = 1; if (stateAware_1 == null) returnVal = stateAware_2 == null ? 0 : -1; else if (stateAware_2 == null) returnVal = 1; else { final Date first_date = stateAware_1.getState().getCreatedDate(); final Date second_date = stateAware_2.getState().getCreatedDate(); if (first_date.after(second_date)) returnVal = -1; else if (first_date.equals(second_date)) returnVal = 0; } return returnVal; }; } protected StateInfoBuilder buildStateInfo() { return new StateInfoBuilder().task(this.getState().getNatureOfTask()). itemDetails(this.getStateDetails()).status(getCurrentState().getStatus().name()). refDate(this.getCreatedDate()).sender(this.getState().getSenderName()). senderPhoneno(this.getState().getExtraInfo()); } public String getStateInfoJson() { return this.buildStateInfo().toJson(); } }