/*
* Licensed under the Apache License, Version 2.0 (the "License");
*
* You may not use this file except in compliance with the License.
*
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributions from 2013-2017 where performed either by US government
* employees, or under US Veterans Health Administration contracts.
*
* US Veterans Health Administration contributions by government employees
* are work of the U.S. Government and are not subject to copyright
* protection in the United States. Portions contributed by government
* employees are USGovWork (17USC ยง105). Not subject to copyright.
*
* Contribution by contractors to the US Veterans Health Administration
* during this period are contractually contributed under the
* Apache License, Version 2.0.
*
* See: https://www.usa.gov/government-works
*
* Contributions prior to 2013:
*
* Copyright (C) International Health Terminology Standards Development Organisation.
* Licensed under the Apache License, Version 2.0.
*
*/
package sh.isaac.provider.workflow;
//~--- JDK imports ------------------------------------------------------------
import java.util.UUID;
import javax.annotation.PreDestroy;
import javax.inject.Singleton;
//~--- non-JDK imports --------------------------------------------------------
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jvnet.hk2.annotations.Service;
import sh.isaac.api.Get;
import sh.isaac.api.LookupService;
import sh.isaac.api.OchreCache;
import sh.isaac.api.UserRoleService;
import sh.isaac.provider.workflow.crud.WorkflowAccessor;
import sh.isaac.provider.workflow.crud.WorkflowProcessInitializerConcluder;
import sh.isaac.provider.workflow.crud.WorkflowUpdater;
import sh.isaac.provider.workflow.model.WorkflowContentStore;
import sh.isaac.provider.workflow.model.contents.AvailableAction;
import sh.isaac.provider.workflow.model.contents.DefinitionDetail;
import sh.isaac.provider.workflow.model.contents.ProcessDetail;
import sh.isaac.provider.workflow.model.contents.ProcessHistory;
//~--- classes ----------------------------------------------------------------
/**
* {@link WorkflowProvider}
*
* This provider is how users get access to the Workflow implementation objects.
* The data store for this implementation piggy-backs on top of the metacontent store - which comes
* up before this class, and manages its own shutdown - so no shutdown / startup sequence
* is required for this service.
*
* @author <a href="mailto:daniel.armbrust.list@gmail.com">Dan Armbrust</a>
*/
@Service
@Singleton
public class WorkflowProvider
implements OchreCache {
/** The bpmn path. */
// This hack is only visible for test hacking at the moment - this will be redone in the future when we handle multiple bpmn files
public static String BPMN_PATH = "/sh/isaac/provider/workflow/VetzWorkflowV1.0.bpmn2";
//~--- fields --------------------------------------------------------------
/** The logger. */
private final Logger logger = LogManager.getLogger();
/**
* * Workflow-based Data Store containing the available actions based on role and
* initial state. Initialized during the importing of a BPMN2 file (containing
* the definition) and static from then on.
*/
private WorkflowContentStore<AvailableAction> availableActionContentStore;
/**
* Workflow-based Data Store containing the details associated with a given
* project. Initialized during the importing of a BPMN2 file (containing the
* definition) and static from then on.
*/
private WorkflowContentStore<DefinitionDetail> definitionDetailContentStore;
/**
* Workflow-based Data Store containing the workflow process instance entries.
* Initialized by user during process creation and updated by users thereafter.
*/
private WorkflowContentStore<ProcessDetail> processDetailContentStore;
/**
* Workflow-based Data Store containing the process instance historical entries.
* Updated each time a user advances workflow.
*/
private WorkflowContentStore<ProcessHistory> processHistoryContentStore;
/**
* Workflow-based Data Store containing the workflow User Role entries.
* Initialized during reading of WF Definition only and static from then on.
*/
private UserRoleService userRoleContentStore;
/** The bpmn info. */
private BPMNInfo bpmnInfo;
//~--- constant enums ------------------------------------------------------
/**
* The Enum WorkflowContentStoreType.
*/
private enum WorkflowContentStoreType {
/** The available action. */
AVAILABLE_ACTION,
/** The definition detail. */
DEFINITION_DETAIL,
/** The historical workflow. */
HISTORICAL_WORKFLOW,
/** The process definition. */
PROCESS_DEFINITION
}
//~--- constructors --------------------------------------------------------
/**
* Instantiates a new workflow provider.
*/
// For HK2 only
private WorkflowProvider() {
this.logger.debug("Starting up the Workflow Provider");
reCacheStoreRefs();
}
//~--- methods -------------------------------------------------------------
/**
* Reset.
*
* @see sh.isaac.api.OchreCache#reset()
*/
@Override
public void reset() {
this.logger.info("Clearing cache due to metastore shutdown");
this.availableActionContentStore = null;
this.definitionDetailContentStore = null;
this.processDetailContentStore = null;
this.processHistoryContentStore = null;
this.userRoleContentStore = null;
this.bpmnInfo = null;
}
/**
* Re cache store refs.
*/
private synchronized void reCacheStoreRefs() {
this.logger.info("Getting storage refs from metastore " + this);
this.availableActionContentStore = new WorkflowContentStore<>(Get.metaContentService().<UUID,
byte[]>openStore(WorkflowContentStoreType.AVAILABLE_ACTION.toString()),
(bytes) -> (bytes == null) ? null
: new AvailableAction(bytes));
this.definitionDetailContentStore = new WorkflowContentStore<>(Get.metaContentService().<UUID,
byte[]>openStore(WorkflowContentStoreType.DEFINITION_DETAIL.toString()),
(bytes) -> (bytes == null) ? null
: new DefinitionDetail(bytes));
this.processDetailContentStore = new WorkflowContentStore<>(Get.metaContentService().<UUID,
byte[]>openStore(WorkflowContentStoreType.PROCESS_DEFINITION.toString()),
(bytes) -> (bytes == null) ? null
: new ProcessDetail(bytes));
this.processHistoryContentStore = new WorkflowContentStore<>(Get.metaContentService().<UUID,
byte[]>openStore(WorkflowContentStoreType.HISTORICAL_WORKFLOW.toString()),
(bytes) -> (bytes == null) ? null
: new ProcessHistory(bytes));
this.userRoleContentStore = LookupService.getService(UserRoleService.class);
// this needs rework to load 1 (or more) BPMN2 Files from the classpath
if (BPMN_PATH != null) // Null is to support a test case where it doesn't want the file loaded by default
{
this.bpmnInfo = new Bpmn2FileImporter(BPMN_PATH, this).getBPMNInfo();
}
}
/**
* Shutdown.
*/
@PreDestroy
private void shutdown() {
this.logger.debug("Shutting down the Workflow Provider");
// This is a noop, the metacontent store properly shuts itself down
}
//~--- get methods ---------------------------------------------------------
/**
* Gets the available action store.
*
* @return the available action store
*/
public WorkflowContentStore<AvailableAction> getAvailableActionStore() {
if (this.availableActionContentStore == null) {
reCacheStoreRefs();
}
return this.availableActionContentStore;
}
/**
* Gets the BPMN info.
*
* @return the BPMN info
*/
public BPMNInfo getBPMNInfo() {
if (this.bpmnInfo == null) {
reCacheStoreRefs();
}
return this.bpmnInfo;
}
/**
* Gets the definition detail store.
*
* @return the definition detail store
*/
public WorkflowContentStore<DefinitionDetail> getDefinitionDetailStore() {
if (this.definitionDetailContentStore == null) {
reCacheStoreRefs();
}
return this.definitionDetailContentStore;
}
/**
* Gets the process detail store.
*
* @return the process detail store
*/
public WorkflowContentStore<ProcessDetail> getProcessDetailStore() {
if (this.processDetailContentStore == null) {
reCacheStoreRefs();
}
return this.processDetailContentStore;
}
/**
* Gets the process history store.
*
* @return the process history store
*/
public WorkflowContentStore<ProcessHistory> getProcessHistoryStore() {
if (this.processHistoryContentStore == null) {
reCacheStoreRefs();
}
return this.processHistoryContentStore;
}
/**
* Gets the user role store.
*
* @return the user role store
*/
public UserRoleService getUserRoleStore() {
if (this.userRoleContentStore == null) {
reCacheStoreRefs();
}
return this.userRoleContentStore;
}
/**
* Gets the workflow accessor.
*
* @return the workflow accessor
*/
public WorkflowAccessor getWorkflowAccessor() {
return LookupService.get()
.getService(WorkflowAccessor.class);
}
/**
* Gets the workflow process initializer concluder.
*
* @return the workflow process initializer concluder
*/
public WorkflowProcessInitializerConcluder getWorkflowProcessInitializerConcluder() {
return LookupService.get()
.getService(WorkflowProcessInitializerConcluder.class);
}
/**
* Gets the workflow updater.
*
* @return the workflow updater
*/
public WorkflowUpdater getWorkflowUpdater() {
return LookupService.get()
.getService(WorkflowUpdater.class);
}
}