View Javadoc

1   /*******************************************************************************
2    *  Imixs Workflow 
3    *  Copyright (C) 2001, 2011 Imixs Software Solutions GmbH,  
4    *  http://www.imixs.com
5    *  
6    *  This program is free software; you can redistribute it and/or 
7    *  modify it under the terms of the GNU General Public License 
8    *  as published by the Free Software Foundation; either version 2 
9    *  of the License, or (at your option) any later version.
10   *  
11   *  This program is distributed in the hope that it will be useful, 
12   *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
14   *  General Public License for more details.
15   *  
16   *  You can receive a copy of the GNU General Public
17   *  License at http://www.gnu.org/licenses/gpl.html
18   *  
19   *  Project: 
20   *  	http://www.imixs.org
21   *  	http://java.net/projects/imixs-workflow
22   *  
23   *  Contributors:  
24   *  	Imixs Software Solutions GmbH - initial API and implementation
25   *  	Ralph Soika - Software Developer
26   *******************************************************************************/
27  
28  package org.imixs.workflow.plugins.jee;
29  
30  import java.util.Collection;
31  
32  import javax.ejb.EJBTransactionRolledbackException;
33  
34  import org.imixs.workflow.ItemCollection;
35  import org.imixs.workflow.Plugin;
36  import org.imixs.workflow.WorkflowContext;
37  import org.imixs.workflow.exceptions.AccessDeniedException;
38  import org.imixs.workflow.exceptions.PluginException;
39  import org.imixs.workflow.exceptions.ProcessingErrorException;
40  import org.imixs.workflow.jee.ejb.EntityService;
41  import org.imixs.workflow.jee.ejb.WorkflowService;
42  
43  /**
44   * This plugin handles the creation and management of versions from an existing
45   * workitem. inside the Imix JEE Workflow. The creation or modificatin of a
46   * version is defined by the workflowmodel. The plugin can generate new versions
47   * (e.g. creating a version of a master version) and also converting a existing
48   * version into a master version.
49   * <p>
50   * The Plugin depends on the org.imixs.workflow.jee.ejb.WorkflowManager. So the
51   * Plugin can not be used in other implementations.
52   * <p>
53   * The creation and management of a new version is defined by the workflow model
54   * (See Imixs Modeler) There are currently two modes supported (provided by the
55   * activity property 'keyVersion')
56   * <p>
57   * mode=1 indicates that the plugin should create a new version of the current
58   * workitem. The two workitems are identically except the attributes $unqiueid
59   * and $workitemidRef. The attribute workitemidRef points to the $uniqueid form
60   * the source workitem. So the availability of this property indicates that the
61   * workitem is a version of source workitem with this $uniqueid. The source
62   * workitem has typically no $workitemidRef attribute. The Source Workitem is
63   * also named Master Version. After the new version is created the plugin
64   * processes the version with the activity provided by the model
65   * (numVersionActivityID) if provided by the model.
66   * <p>
67   * 2=indicates that the plugin should convert a existing version into a Master
68   * Version. This means that the $workitemIDRef will be nulled. An existing
69   * Master Version will be processed by the activity provided by the model
70   * (numVersionActivityID). Also the $workitemidRef will be set to the current
71   * $workitemID.
72   * <p>
73   * If an error occured during the workflow process this plugin will throw a new
74   * ejbexception in the close() method to cancel the current transaction. So no
75   * changes will be saved by the ejb container
76   * 
77   * @see org.imixs.workflow.jee.ejb.WorkflowManager
78   * @author Ralph Soika
79   * @version 1.0
80   */
81  
82  public class VersionPlugin extends AbstractPlugin {
83  
84  	private EntityService entityService = null;
85  	private WorkflowService workflowService = null;
86  	private String versionMode = "";
87  	private int versionActivityID = -1;
88  	private ItemCollection version = null;
89  
90  	/**
91  	 * the init method throws an exception if the plugin is not run in a
92  	 * instance of org.imixs.workflow.jee.ejb.WorkflowManager. This is necessary
93  	 * as the plugin needs an instance of the EntityService.
94  	 */
95  	public void init(WorkflowContext actx) throws PluginException {
96  		super.init(actx);
97  
98  		// check for an instance of WorkflowService
99  		if (actx instanceof WorkflowService) {
100 			// yes we are running in a WorkflowService EJB
101 			workflowService = (WorkflowService) actx;
102 			// get latest model version....
103 			entityService = workflowService.getEntityService();
104 		}
105 
106 		if (workflowService == null)
107 			throw new PluginException(
108 					"VersionPlugin unable to access WorkflowSerive");
109 
110 	}
111 
112 	public EntityService getEntityService() {
113 		return entityService;
114 	}
115 
116 	public WorkflowService getWorkflowService() {
117 		return workflowService;
118 	}
119 
120 	public ItemCollection getVersion() {
121 		return version;
122 	}
123 
124 	public void setVersion(ItemCollection version) {
125 		this.version = version;
126 	}
127 
128 	/**
129 	 * creates an version depending to the version mode and the version activity
130 	 * ID provided by the workflow model.
131 	 * 
132 	 * @throws InvalidItemValueException
133 	 * 
134 	 */
135 	public int run(ItemCollection adocumentContext,
136 			ItemCollection adocumentActivity) throws PluginException {
137 
138 		// determine mode and ActivityID to manage version
139 		versionMode = adocumentActivity.getItemValueString("keyVersion");
140 		versionActivityID = adocumentActivity
141 				.getItemValueInteger("numVersionActivityID");
142 		try {
143 			// lookup ejbs ?
144 			if ("1".equals(versionMode) || "2".equals(versionMode)) {
145 
146 				// handle different version modes
147 				// 1 = create a new Version from current workitem
148 				if ("1".equals(versionMode)) {
149 
150 					// copy workitem
151 
152 					version = createVersion(adocumentContext);
153 
154 					if (this.ctx.getLogLevel() > 0)
155 						System.out
156 								.println("[VersionPlugin] new version created");
157 					// check if workitem should be processed
158 					if (versionActivityID > 0) {
159 						version.replaceItemValue("$ActivityID",
160 								versionActivityID);
161 						version = workflowService.processWorkItem(version);
162 					} else {
163 						// no processing - simply save workitem
164 						version = entityService.save(version);
165 					}
166 					return Plugin.PLUGIN_OK;
167 
168 				}
169 
170 				// convert to Master Version
171 				if ("2".equals(adocumentActivity
172 						.getItemValueString("keyVersion"))) {
173 
174 					/*
175 					 * this code iterates over all existing workitems with the
176 					 * same $workitemid and fixes lost parent workitemRefIDs.
177 					 */
178 					String sworkitemID = adocumentContext
179 							.getItemValueString("$WorkItemID");
180 
181 					// get current master version
182 					String query = " SELECT workitem FROM Entity AS workitem "
183 							+ " JOIN workitem.textItems AS t1"
184 							+ " WHERE t1.itemName = '$workitemid'"
185 							+ " AND t1.itemValue ='" + sworkitemID + "'";
186 
187 					Collection<ItemCollection> col = entityService
188 							.findAllEntities(query, 0, -1);
189 					// now search master version...
190 					for (ItemCollection aVersion : col) {
191 						String sWorkitemRef = aVersion
192 								.getItemValueString("$workitemIDRef");
193 						if ("".equals(sWorkitemRef)) {
194 							// Master version found!
195 							// convert now this workitem into a Version from the
196 							// current workitem
197 							String id = adocumentContext
198 									.getItemValueString("$uniqueID");
199 							aVersion.replaceItemValue("$WorkItemIDRef", id);
200 							// process version?
201 							// check if worktiem should be processed
202 							if (versionActivityID > 0) {
203 								aVersion.replaceItemValue("$ActivityID",
204 										versionActivityID);
205 								aVersion = workflowService
206 										.processWorkItem(aVersion);
207 							} else {
208 								// no processing - simply save workitem
209 								aVersion = entityService.save(aVersion);
210 							}
211 							version = aVersion;
212 						}
213 					}
214 					// now remove workitemIDRef from current version
215 					adocumentContext.removeItem("$WorkItemIDRef");
216 				}
217 			}
218 
219 		} catch (AccessDeniedException e) {
220 			throw new PluginException(e.getMessage(), e);
221 		} catch (ProcessingErrorException e) {
222 			throw new PluginException(e.getMessage(), e);
223 		}
224 		return Plugin.PLUGIN_OK;
225 	}
226 
227 	public void close(int status) throws PluginException {
228 		// if an error has occurred during processing take back new created
229 		// versions
230 		if (status == Plugin.PLUGIN_ERROR) {
231 			// throw a ejb exception to cancel a running transaction
232 			// this will avoid changes back into the database
233 			throw new EJBTransactionRolledbackException();
234 		}
235 	}
236 
237 	/**
238 	 * This method creates a new instance of a exiting workitem. The method did
239 	 * not save the workitem!. The method can be subclassed to modify the new
240 	 * created version.
241 	 * 
242 	 * The new property $WorkitemIDRef will be added which points to the
243 	 * $uniqueID of the sourceWorkitem.
244 	 * 
245 	 * @param sourceItemCollection
246 	 *            the ItemCollection which should be versioned
247 	 * @return new version of the source ItemCollection
248 	 * 
249 	 * @throws PluginException
250 	 * @throws Exception
251 	 */
252 	public ItemCollection createVersion(ItemCollection sourceItemCollection)
253 			throws PluginException {
254 		ItemCollection itemColNewVersion = new ItemCollection();
255 
256 		itemColNewVersion.replaceAllItems(sourceItemCollection.getAllItems());
257 
258 		String id = sourceItemCollection.getItemValueString("$uniqueid");
259 		if ("".equals(id))
260 			throw new PluginException(
261 					"Error - unable to create a version from a new workitem!");
262 		// remove $Uniqueid to force the generation of a new Entity Instance.
263 		itemColNewVersion.getAllItems().remove("$uniqueid");
264 
265 		// update $WorkItemIDRef to current worktiemID
266 		itemColNewVersion.replaceItemValue("$WorkItemIDRef", id);
267 
268 		return itemColNewVersion;
269 
270 	}
271 
272 }