001: /*--
002:
003: Copyright (C) 2002-2005 Adrian Price.
004: All rights reserved.
005:
006: Redistribution and use in source and binary forms, with or without
007: modification, are permitted provided that the following conditions
008: are met:
009:
010: 1. Redistributions of source code must retain the above copyright
011: notice, this list of conditions, and the following disclaimer.
012:
013: 2. Redistributions in binary form must reproduce the above copyright
014: notice, this list of conditions, and the disclaimer that follows
015: these conditions in the documentation and/or other materials
016: provided with the distribution.
017:
018: 3. The names "OBE" and "Open Business Engine" must not be used to
019: endorse or promote products derived from this software without prior
020: written permission. For written permission, please contact
021: adrianprice@sourceforge.net.
022:
023: 4. Products derived from this software may not be called "OBE" or
024: "Open Business Engine", nor may "OBE" or "Open Business Engine"
025: appear in their name, without prior written permission from
026: Adrian Price (adrianprice@users.sourceforge.net).
027:
028: THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
029: WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
030: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
031: DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
032: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
033: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
034: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
035: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
036: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
037: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
038: POSSIBILITY OF SUCH DAMAGE.
039:
040: For more information on OBE, please see
041: <http://obe.sourceforge.net/>.
042:
043: */
044:
045: package org.obe.server.j2ee.repository;
046:
047: import org.apache.commons.logging.Log;
048: import org.obe.client.api.repository.RepositoryException;
049: import org.obe.server.j2ee.ejb.AbstractEntityEJB;
050: import org.obe.spi.service.ServerConfig;
051: import org.obe.xpdl.model.misc.PublicationStatus;
052: import org.obe.xpdl.model.misc.RedefinableHeader;
053: import org.obe.xpdl.model.pkg.XPDLPackage;
054: import org.obe.xpdl.model.workflow.ProcessHeader;
055: import org.obe.xpdl.model.workflow.WorkflowProcess;
056: import org.wfmc.wapi.WMFilter;
057:
058: import javax.ejb.CreateException;
059: import javax.ejb.FinderException;
060: import javax.ejb.ObjectNotFoundException;
061: import java.sql.SQLException;
062: import java.util.Collection;
063: import java.util.Date;
064: import java.util.List;
065:
066: /**
067: * Holds the persistent state of a process definition.
068: *
069: * @author Adrian Price
070: * @ejb:bean type="CMP"
071: * cmp-version="2.x"
072: * name="ProcessDefinition"
073: * display-name="OBE Process Definition"
074: * jndi-name="org/obe/ejb/ProcessDefinition"
075: * local-jndi-name="org/obe/ejb/ProcessDefinitionLocal"
076: * primkey-field="processDefinitionId"
077: * schema="PROCESSDEFINITION"
078: * reentrant="False"
079: * transaction-type="Container"
080: * view-type="local"
081: * @ejb:persistence table-name="OBEPROCESSDEFINITION"
082: * @ejb:pk class="java.lang.String"
083: * unchecked="true"
084: * @ejb:home local-class="org.obe.server.j2ee.repository.ProcessDefinitionLocalHome"
085: * local-extends="org.obe.server.j2ee.repository.ProcessDefinitionROHome,javax.ejb.EJBLocalHome"
086: * @ejb:interface local-class="org.obe.server.j2ee.repository.ProcessDefinitionLocal"
087: * local-extends="org.obe.server.j2ee.repository.ProcessDefinitionRO,javax.ejb.EJBLocalObject"
088: * @ejb:permission unchecked="true"
089: * @ejb:transaction type="Supports"
090: * @weblogic:transaction-isolation ${transaction.isolation}
091: * @ejb:finder signature="java.util.Collection findAll()"
092: * query="SELECT OBJECT(p) FROM PROCESSDEFINITION AS p"
093: * result-type-mapping="Local"
094: * unchecked="true"
095: * @ejb:finder signature="java.util.Collection findByName(java.lang.String name)"
096: * query="SELECT OBJECT(p) FROM PROCESSDEFINITION AS p WHERE p.name=?1"
097: * result-type-mapping="Local"
098: * unchecked="true"
099: * @ejb:finder signature="java.util.Collection findByName(java.lang.String name, java.util.Date when)"
100: * query="SELECT OBJECT(p) FROM PROCESSDEFINITION AS p WHERE p.name=?1 AND p.state=1 AND p.publicationStatus <> 'UNDER_REVISION' AND (p.validFromDate IS NULL OR p.validFromDate > ?2) AND (p.validToDate IS NULL OR p.validToDate < ?2)"
101: * result-type-mapping="Local"
102: * unchecked="true"
103: * @ejb:ejb-ref ejb-name="XPDLPackage"
104: * view-type="local"
105: * @weblogic:ejb-local-reference-description ejb-ref-name="ejb/XPDLPackage"
106: * jndi-name="org/obe/ejb/PackageLocal"
107: * @weblogic:cache concurrency-strategy="Database"
108: * @weblogic:invalidation-target ejb-name="ProcessDefinitionRO"
109: * @ejb:resource-ref res-name="jdbc/TxDataSource"
110: * res-type="javax.sql.DataSource"
111: * res-auth="Container"
112: * @jboss:resource-manager res-man-class="javax.sql.DataSource"
113: * res-man-name="jdbc/TxDataSource"
114: * res-man-jndi-name="java:/${xdoclet.DataSource}"
115: * @weblogic:resource-description res-ref-name="jdbc/TxDataSource"
116: * jndi-name="${xdoclet.DataSource}"
117: * @weblogic:data-source-name java:comp/env/jdbc/TxDataSource
118: * @jboss:create-table false
119: * @weblogic:pool max-beans-in-free-pool="200"
120: * initial-beans-in-free-pool="0"
121: * @weblogic:cache max-beans-in-cache="200"
122: * idle-timeout-seconds="0"
123: * concurrency-strategy="Database"
124: * @weblogic:persistence delay-updates-until-end-of-tx="True"
125: * @jboss:tuned-updates tune="true"
126: * @jboss:container-configuration name="${xdoclet.jboss.container-configuration}"
127: * @jboss:cache-invalidation value="True"
128: * @jboss:cache-invalidation-config invalidation-group-name="ProcessDefinition"
129: */
130: public abstract class ProcessDefinitionEJB extends AbstractEntityEJB {
131: private static final long serialVersionUID = 3832600769148380488L;
132: protected static final Log _logger = getLogger(ProcessDefinitionEJB.class);
133:
134: public ProcessDefinitionEJB() {
135: }
136:
137: /**
138: * @ejb:create-method
139: */
140: public String ejbCreate(WorkflowProcess workflow)
141: throws CreateException {
142:
143: if (_logger.isDebugEnabled() && ServerConfig.isVerbose()) {
144: _logger.debug("ejbCreate(" + workflow + ')');
145: }
146:
147: setProcessDefinitionId(workflow.getId());
148: _update(workflow);
149:
150: return null;
151: }
152:
153: public void ejbPostCreate(WorkflowProcess workflow) {
154: if (_logger.isDebugEnabled() && ServerConfig.isVerbose()) {
155: _logger.debug("ejbPostCreate(" + workflow + ')');
156: }
157: }
158:
159: /**
160: * Counts the number of matching process definitions.
161: *
162: * @param filter Process definition filter; can be <code>null</code>.
163: * @return The number of matching process definitions.
164: * @ejb:home-method
165: */
166: public int ejbHomeCount(WMFilter filter) throws RepositoryException {
167: try {
168: return ProcessDefinitionDAO.getInstance().count(filter);
169: } catch (SQLException e) {
170: throw new RepositoryException(e);
171: }
172: }
173:
174: /**
175: * Retrieves matching process definitions.
176: *
177: * @param filter Process definition filter; should not be <code>null</code>
178: * (use {@link ProcessDefinitionLocalHome#findAll} instead).
179: * @return A collection of matching process definitions.
180: * @ejb:home-method
181: * @see ProcessDefinitionLocalHome#findAll
182: */
183: public Collection ejbHomeXfindByFilter(WMFilter filter)
184: throws FinderException, RepositoryException {
185:
186: try {
187: List procDefs = ProcessDefinitionDAO.getInstance()
188: .findByFilter(filter);
189: ProcessDefinitionLocalHome home = (ProcessDefinitionLocalHome) _ctx
190: .getEJBLocalHome();
191: for (int i = 0; i < procDefs.size(); i++) {
192: try {
193: procDefs
194: .set(i, home
195: .findByPrimaryKey((String) procDefs
196: .get(i)));
197: } catch (ObjectNotFoundException e) {
198: // Someone else deleted this PK, so just skip it.
199: procDefs.remove(i--);
200: }
201: }
202: return procDefs;
203: } catch (SQLException e) {
204: throw new RepositoryException(e);
205: }
206: }
207:
208: /**
209: * @ejb:interface-method
210: * @ejb:persistence column-name="PACKAGEID"
211: */
212: public abstract String getPackageId();
213:
214: /**
215: * @ejb:persistence column-name="PACKAGEID"
216: */
217: public abstract void setPackageId(String packageId);
218:
219: /**
220: * @ejb:interface-method
221: * @ejb:persistence column-name="PROCESSDEFINITIONID"
222: */
223: public abstract String getProcessDefinitionId();
224:
225: /**
226: * @ejb:persistence column-name="PROCESSDEFINITIONID"
227: */
228: public abstract void setProcessDefinitionId(
229: String processDefinitionId);
230:
231: /**
232: * @ejb:interface-method
233: * @ejb:persistence column-name="NAME"
234: */
235: public abstract String getName();
236:
237: /**
238: * @ejb:persistence column-name="NAME"
239: */
240: public abstract void setName(String name);
241:
242: /**
243: * @ejb:interface-method
244: * @ejb:persistence column-name="DESCRIPTION"
245: */
246: public abstract String getDescription();
247:
248: /**
249: * @ejb:persistence column-name="DESCRIPTION"
250: */
251: public abstract void setDescription(String description);
252:
253: /**
254: * @ejb:interface-method
255: * @ejb:persistence column-name="AUTHOR"
256: */
257: public abstract String getAuthor();
258:
259: /**
260: * @ejb:persistence column-name="AUTHOR"
261: */
262: public abstract void setAuthor(String author);
263:
264: /**
265: * @ejb:interface-method
266: * @ejb:persistence column-name="STATUS"
267: */
268: public abstract String getPublicationStatus();
269:
270: /**
271: * @ejb:persistence column-name="STATUS"
272: */
273: public abstract void setPublicationStatus(String status);
274:
275: /**
276: * @ejb:interface-method
277: * @ejb:persistence column-name="CREATEDDATE"
278: */
279: public abstract Date getCreatedDate();
280:
281: /**
282: * @ejb:persistence column-name="CREATEDDATE"
283: */
284: public abstract void setCreatedDate(Date createdDate);
285:
286: /**
287: * @ejb:interface-method
288: * @ejb:persistence column-name="VALIDFROMDATE"
289: */
290: public abstract Date getValidFromDate();
291:
292: /**
293: * @ejb:persistence column-name="VALIDFROMDATE"
294: */
295: public abstract void setValidFromDate(Date fromDate);
296:
297: /**
298: * @ejb:interface-method
299: * @ejb:persistence column-name="VALIDTODATE"
300: */
301: public abstract Date getValidToDate();
302:
303: /**
304: * @ejb:persistence column-name="VALIDTODATE"
305: */
306: public abstract void setValidToDate(Date toDate);
307:
308: /**
309: * @ejb:interface-method
310: * @ejb:persistence column-name="STATE"
311: */
312: public abstract int getState();
313:
314: /**
315: * @ejb:interface-method
316: * @ejb:persistence column-name="STATE"
317: */
318: public abstract void setState(int state);
319:
320: // TODO: Restore method name to 'getPackage' when WebLogic ejbc bug is fixed.
321: // The bug is that ejbc derives formal parameter names from the CMR field
322: // name but doesn't bother to check that it's generated a legal Java
323: // identifier. In this case the CMR field name derived from
324: // ProcessDefinitionEJB.getPackage() is 'package', which of course is a
325: // Java reserved word.
326:
327: /**
328: * @ejb:interface-method
329: * @ejb:relation name="Package-ProcessDefinition"
330: * role-name="ProcessDefinition-Has-A-Package"
331: * cascade-delete="yes"
332: * @weblogic:column-map key-column="PACKAGEID"
333: * foreign-key-column="PACKAGEID"
334: * @jboss:relation related-pk-field="packageId"
335: * fk-column="PACKAGEID"
336: */
337: public abstract PackageLocal getXpdlPackage();
338:
339: public abstract void setXpdlPackage(PackageLocal pkg);
340:
341: /**
342: * @ejb:interface-method
343: */
344: public PackageRO getXPDLPackageRO() {
345: return getXpdlPackage();
346: }
347:
348: /**
349: * Updates the process definition fields from the workflow.
350: *
351: * @param workflow The workflow definition.
352: * @ejb:interface-method
353: */
354: public void update(WorkflowProcess workflow) {
355: _update(workflow);
356: }
357:
358: protected final Log getLogger() {
359: return _logger;
360: }
361:
362: private void _update(WorkflowProcess workflow) {
363: if (!getProcessDefinitionId().equals(workflow.getId()))
364: throw new IllegalArgumentException(
365: "processDefinitionId mismatch");
366: String packageId = getPackageId();
367: if (packageId != null
368: && !packageId.equals(workflow.getPackage().getId())) {
369:
370: // If updating, package ID must match as well.
371: throw new IllegalArgumentException("packageId mismatch");
372: }
373:
374: // TODO: move this lot into WorkflowUtilities.
375: // Extract author, creation, effective and expiry dates from the
376: // workflow header, using defaults from its package where necessary.
377: XPDLPackage pkg = workflow.getPackage();
378: RedefinableHeader redefHdr = workflow.getRedefinableHeader();
379: String author = null;
380: String pubStat = null;
381: if (redefHdr != null) {
382: author = redefHdr.getAuthor();
383: PublicationStatus ps = redefHdr.getPublicationStatus();
384: if (ps != null)
385: pubStat = ps.toString();
386: }
387: redefHdr = pkg.getRedefinableHeader();
388: if (redefHdr != null) {
389: if (author == null)
390: author = redefHdr.getAuthor();
391: if (pubStat == null) {
392: PublicationStatus ps = redefHdr.getPublicationStatus();
393: if (ps != null)
394: pubStat = ps.toString();
395: }
396: }
397:
398: ProcessHeader hdr = workflow.getProcessHeader();
399:
400: // Set persistent fields.
401: setName(workflow.getName());
402: setDescription(hdr.getDescription());
403: setAuthor(author);
404: setPublicationStatus(pubStat);
405: setCreatedDate(hdr.getCreated());
406: setValidFromDate(hdr.getValidFrom());
407: setValidToDate(hdr.getValidTo());
408: setState(workflow.getState());
409: }
410: }
|