/******************************************************************************* * Imixs Workflow * Copyright (C) 2001, 2011 Imixs Software Solutions GmbH, * http://www.imixs.com * * 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 2 * of the License, or (at your option) 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 can receive a copy of the GNU General Public * License at http://www.gnu.org/licenses/gpl.html * * Project: * http://www.imixs.org * http://java.net/projects/imixs-workflow * * Contributors: * Imixs Software Solutions GmbH - initial API and implementation * Ralph Soika - Software Developer *******************************************************************************/ package org.imixs.marty.ejb; import java.util.Collection; import java.util.List; import javax.annotation.security.DeclareRoles; import javax.annotation.security.RolesAllowed; import javax.annotation.security.RunAs; import javax.ejb.EJB; import javax.ejb.LocalBean; import javax.ejb.Stateless; import org.imixs.workflow.ItemCollection; import org.imixs.workflow.WorkflowKernel; import org.imixs.workflow.engine.DocumentService; import org.imixs.workflow.exceptions.AccessDeniedException; import org.imixs.workflow.exceptions.InvalidAccessException; import org.imixs.workflow.exceptions.PluginException; import org.imixs.workflow.exceptions.QueryException; /** * This EJB handles a unique Sequence Number over a group of workitems. * Therefore the ejb loads the parent Workitem for a given Workitem to load and * update a unique sequence number. If the given workitem has no $unqiueIDRef * the ejb will throw an exception! * * The Method getNextSequenceNumberByGroup computes the sequence number based on * a configuration entity with the name "BASIC". The configuration provides a * property 'sequencenumbers' with the current number range for each * workflowGroup. * * This EJB should only run with manager access ! * * sun-ejb-jar.xml * <p> * <code> <ejb> <ejb-name>ScheduledWorkflowServiceImplementation</ejb-name> <jndi-name> ejb/ReklamationsmanagementScheduledWorkflowServiceImplementation </jndi-name> <principal><name>Glassfish</name></principal> </ejb> * </code> * * @author rsoika * */ @DeclareRoles({ "org.imixs.ACCESSLEVEL.NOACCESS", "org.imixs.ACCESSLEVEL.READERACCESS", "org.imixs.ACCESSLEVEL.AUTHORACCESS", "org.imixs.ACCESSLEVEL.EDITORACCESS", "org.imixs.ACCESSLEVEL.MANAGERACCESS" }) @RolesAllowed({ "org.imixs.ACCESSLEVEL.NOACCESS", "org.imixs.ACCESSLEVEL.READERACCESS", "org.imixs.ACCESSLEVEL.AUTHORACCESS", "org.imixs.ACCESSLEVEL.EDITORACCESS", "org.imixs.ACCESSLEVEL.MANAGERACCESS" }) @Stateless @LocalBean @RunAs("org.imixs.ACCESSLEVEL.MANAGERACCESS") public class SequenceService { public final static String SEQUENCE_NAME = "numLastSequenceNummer"; public final static String SEQUENCE_ERROR = "MISSING_UNIQUEIDREF"; // Persistence Manager @EJB DocumentService documentService; /** * This method computes the sequecne number based on a configuration entity * with the name "BASIC". The configuration provides a property * 'sequencenumbers' with the current number range for each workflowGroup. * If a Workitem have a WorkflowGroup with no corresponding entry the method * will not compute a new number. * * @throws InvalidWorkitemException * @throws AccessDeniedException * */ public long getNextSequenceNumberByGroup(ItemCollection aworkitem) throws AccessDeniedException { ItemCollection configItemCollection = null; String sQuery="(type:\"configuration\" AND txtname:\"BASIC\")"; Collection<ItemCollection> col; try { col = documentService.find(sQuery,1, 0); } catch (QueryException e) { throw new InvalidAccessException(InvalidAccessException.INVALID_ID,e.getMessage(),e); } if (col.size() > 0) { configItemCollection = col.iterator().next(); // read configuration and test if a corresponding configuration // exists String sWorkflowGroup = aworkitem .getItemValueString(WorkflowKernel.WORKFLOWGROUP); @SuppressWarnings("unchecked") List<String> vNumbers = configItemCollection .getItemValue("sequencenumbers"); for (int i = 0; i < vNumbers.size(); i++) { String aNumber = vNumbers.get(i); if (aNumber.startsWith(sWorkflowGroup + "=")) { // we got the next number.... String sequcenceNumber = aNumber.substring(aNumber .indexOf('=') + 1); // long currentSequenceNumber = Long .parseLong(sequcenceNumber); long newSequenceNumber = currentSequenceNumber + 1; // Save the new Number back into the config entity aNumber = sWorkflowGroup + "=" + newSequenceNumber; vNumbers.set(i, sWorkflowGroup + "=" + newSequenceNumber); configItemCollection.replaceItemValue("sequencenumbers", vNumbers); documentService.save(configItemCollection); // return the new number return currentSequenceNumber; } } } return 0; } /** * this method computes the next sequence number and updates the parent * workitem where the last sequence number will be stored. * * @throws AccessDeniedException * @throws PluginException */ public long getNextSequenceNumberByParent(ItemCollection aworkitem) throws AccessDeniedException, PluginException { // load current Number ItemCollection sequenceNumberObject = loadParentWorkitem(aworkitem); long currentSequenceNumber = sequenceNumberObject .getItemValueLong(SEQUENCE_NAME); // skip number 0 if (currentSequenceNumber == 0) currentSequenceNumber = 1; long sequenceNumber = currentSequenceNumber; sequenceNumber++; // Save new Number sequenceNumberObject.replaceItemValue(SEQUENCE_NAME, new Long( sequenceNumber)); documentService.save(sequenceNumberObject); return currentSequenceNumber; } /** * load the current Seuqecnce Number from the parent worktiem to the given * aworkitem. The Method throws an exception if the workitem has no parent * workitem! */ public long getLastSequenceNumber(ItemCollection aworkitem) throws Exception { // load current Number ItemCollection sequenceNumberObject = loadParentWorkitem(aworkitem); long sequenceNumber = sequenceNumberObject .getItemValueLong(SEQUENCE_NAME); return sequenceNumber; } /** * sets the current sequence Number */ public void setLastSequenceNumber(ItemCollection aworkitem, long aNewID) throws Exception { // load current Number ItemCollection sequenceNumberObject = loadParentWorkitem(aworkitem); // Save new Number sequenceNumberObject.replaceItemValue(SEQUENCE_NAME, new Long(aNewID)); documentService.save(sequenceNumberObject); } /** * this method loads the parent Workitem of the given workitem * * @return * @throws PluginException */ private ItemCollection loadParentWorkitem(ItemCollection aworkitem) throws PluginException { String sParentID = aworkitem.getItemValueString("$UniqueIDRef"); if ("".equals(sParentID)) throw new PluginException(SequenceService.class.getName(),SEQUENCE_ERROR, "WARNING: SequenceService : No $UniqueIDRef defined"); ItemCollection parent = documentService.load(sParentID); return parent; } }