Source Code Cross Referenced for AbstractExecutionObject.java in  » Workflow-Engines » wfmopen-2.1.1 » de » danet » an » workflow » domain » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Workflow Engines » wfmopen 2.1.1 » de.danet.an.workflow.domain 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * This file is part of the WfMOpen project.
003:         * Copyright (C) 2001-2003 Danet GmbH (www.danet.de), GS-AN.
004:         * All rights reserved.
005:         *
006:         * This program is free software; you can redistribute it and/or modify
007:         * it under the terms of the GNU General Public License as published by
008:         * the Free Software Foundation; either version 2 of the License, or
009:         * (at your option) any later version.
010:         *
011:         * This program is distributed in the hope that it will be useful,
012:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014:         * GNU General Public License for more details.
015:         *
016:         * You should have received a copy of the GNU General Public License
017:         * along with this program; if not, write to the Free Software
018:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
019:         * 
020:         * $Id: AbstractExecutionObject.java,v 1.11.2.1 2007/11/02 16:00:33 drmlipp Exp $
021:         *
022:         * $Log: AbstractExecutionObject.java,v $
023:         * Revision 1.11.2.1  2007/11/02 16:00:33  drmlipp
024:         * Merged bug fixes from HEAD.
025:         *
026:         * Revision 1.13  2007/09/21 07:57:12  drmlipp
027:         * Removed superfluous import.
028:         *
029:         * Revision 1.12  2007/09/21 06:19:35  mlipp
030:         * Fixed problem with NamingException during process deletion.
031:         *
032:         * Revision 1.11  2007/05/03 21:58:19  mlipp
033:         * Internal refactoring for making better use of local EJBs.
034:         *
035:         */
036:
037:        package de.danet.an.workflow.domain;
038:
039:        import java.rmi.RemoteException;
040:        import java.util.ArrayList;
041:        import java.util.Collection;
042:        import java.util.Date;
043:        import java.util.Iterator;
044:        import java.util.List;
045:        import java.util.Map;
046:
047:        import de.danet.an.workflow.api.ProcessDefinition;
048:        import de.danet.an.workflow.api.Activity.ClosedCompletedState;
049:        import de.danet.an.workflow.apix.ExtActivity;
050:        import de.danet.an.workflow.apix.ExtProcess;
051:        import de.danet.an.workflow.internalapi.ExtExecutionObjectLocal;
052:        import de.danet.an.workflow.localcoreapi.WfExecutionObjectLocal;
053:        import de.danet.an.workflow.omgcore.AlreadySuspendedException;
054:        import de.danet.an.workflow.omgcore.CannotResumeException;
055:        import de.danet.an.workflow.omgcore.CannotStopException;
056:        import de.danet.an.workflow.omgcore.CannotSuspendException;
057:        import de.danet.an.workflow.omgcore.HistoryNotAvailableException;
058:        import de.danet.an.workflow.omgcore.InvalidControlOperationException;
059:        import de.danet.an.workflow.omgcore.InvalidDataException;
060:        import de.danet.an.workflow.omgcore.InvalidPriorityException;
061:        import de.danet.an.workflow.omgcore.InvalidStateException;
062:        import de.danet.an.workflow.omgcore.NotRunningException;
063:        import de.danet.an.workflow.omgcore.NotSuspendedException;
064:        import de.danet.an.workflow.omgcore.ProcessData;
065:        import de.danet.an.workflow.omgcore.ResultNotAvailableException;
066:        import de.danet.an.workflow.omgcore.SourceNotAvailableException;
067:        import de.danet.an.workflow.omgcore.TransitionNotAllowedException;
068:        import de.danet.an.workflow.omgcore.UpdateNotAllowedException;
069:        import de.danet.an.workflow.omgcore.WfAuditEvent;
070:        import de.danet.an.workflow.omgcore.WfExecutionObject;
071:        import de.danet.an.workflow.omgcore.WfStateAuditEvent;
072:        import de.danet.an.workflow.omgcore.WfExecutionObject.ClosedState;
073:        import de.danet.an.workflow.omgcore.WfExecutionObject.NotRunningState;
074:        import de.danet.an.workflow.omgcore.WfExecutionObject.OpenState;
075:        import de.danet.an.workflow.omgcore.WfExecutionObject.State;
076:
077:        /**
078:         * <code>AbstractExecutionObject</code> represents a base
079:         * implementation of the interface {@link
080:         * de.danet.an.workflow.api.ExecutionObject
081:         * <code>ExecutionObject</code>}.<P>
082:         *
083:         * With logger level <code>DEBUG</code>, event handling information
084:         * will be logged.
085:         */
086:        public abstract class AbstractExecutionObject implements 
087:                WfExecutionObjectLocal, ExtExecutionObjectLocal {
088:
089:            private static final org.apache.commons.logging.Log logger = org.apache.commons.logging.LogFactory
090:                    .getLog(AbstractExecutionObject.class);
091:
092:            // Make sure that loading this class loads the new states
093:            static {
094:                State s = RunningState.RUNNING;
095:                s = DebugState.ABORTING;
096:                s = SuspendedState.SUSPENDED;
097:                s = ClosedCompletedState.NORMAL;
098:            }
099:
100:            //
101:            // Persistent attribute accessors and associated methods
102:            //
103:
104:            /**
105:             * The getter method for the persistent attribute <code>key</code>.
106:             *
107:             * @return the value of key.
108:             */
109:            protected abstract String getPaKey();
110:
111:            /**
112:             * The getter method for the persistent attribute <code>name</code>.
113:             *
114:             * @return the value of name.
115:             * @see #setPaName
116:             */
117:            protected abstract String getPaName();
118:
119:            /**
120:             * The setter method for the persistent attribute <code>name</code>.
121:             *
122:             * @param newName the new value of name.
123:             * @see #getPaName
124:             */
125:            protected abstract void setPaName(String newName);
126:
127:            /**
128:             * The getter method for the persistent attribute <code>description</code>.
129:             *
130:             * @return the value of description.
131:             * @see #setPaDescription
132:             */
133:            protected abstract String getPaDescription();
134:
135:            /**
136:             * The setter method for the persistent attribute <code>description</code>.
137:             *
138:             * @param newDescription the new value of description.
139:             * @see #getPaDescription
140:             */
141:            protected abstract void setPaDescription(String newDescription);
142:
143:            /**
144:             * The getter method for the persistent attribute <code>priority</code>.
145:             *
146:             * @return the value of priority.
147:             * @see #setPaPriority
148:             */
149:            protected abstract Priority getPaPriority();
150:
151:            /**
152:             * The setter method for the persistent attribute <code>priority</code>.
153:             *
154:             * @param newPriority the new value of priority.
155:             * @see #getPaPriority
156:             */
157:            protected abstract void setPaPriority(Priority newPriority);
158:
159:            /**
160:             * The getter method for the persistent attribute
161:             * <code>lastStateTime</code>.  This attribute holds the time when
162:             * the state was last changed. This may happen from an explicit
163:             * action like the <code>complete()</code> method or via a state
164:             * change propagation from another WfmExecutionObject.
165:             *
166:             * @return the value of lastStateTime.
167:             * @see #setPaLastStateTime
168:             */
169:            protected abstract Date getPaLastStateTime();
170:
171:            /**
172:             * The setter method for the persistent attribute
173:             * <code>lastStateTime</code>.
174:             *
175:             * @param newLastStateTime the new value of lastStateTime.
176:             * @see #getPaLastStateTime
177:             */
178:            protected abstract void setPaLastStateTime(Date newLastStateTime);
179:
180:            /**
181:             * The getter method for the persistent attribute
182:             * <code>typedState</code>.
183:             *
184:             * @return the value of typedState.
185:             * @see #setPaTypedState
186:             */
187:            protected abstract State getPaTypedState();
188:
189:            /**
190:             * The setter method for the persistent attribute
191:             * <code>typedState</code>.
192:             *
193:             * @param newTypedState the new value of typedState.
194:             * @see #getPaTypedState
195:             */
196:            protected abstract void setPaTypedState(State newTypedState);
197:
198:            /**
199:             * The getter method for the persistent attribute <code>debug</code>.
200:             *
201:             * @return the value of debug.
202:             * @see #setPaDebug
203:             */
204:            protected abstract boolean getPaDebug();
205:
206:            /**
207:             * The setter method for the persistent attribute <code>debug</code>.
208:             *
209:             * @param newDebug the new value of debug.
210:             * @see #getPaDebug
211:             */
212:            protected abstract void setPaDebug(boolean newDebug);
213:
214:            /**
215:             * The getter method for the persistent attribute
216:             * <code>auditEventSelection</code>.
217:             *
218:             * @return the value of auditEventSelection.
219:             * @see #setPaAuditEventSelection
220:             */
221:            protected abstract int getPaAuditEventSelection();
222:
223:            /**
224:             * The setter method for the persistent attribute
225:             * <code>auditEventSelection</code>.
226:             *
227:             * @param newAuditEventSelection the new value of
228:             * auditEventSelection.
229:             * @see #getPaAuditEventSelection
230:             */
231:            protected abstract void setPaAuditEventSelection(
232:                    int newAuditEventSelection);
233:
234:            /**
235:             * The getter method for the persistent attribute
236:             * <code>storeAuditEvents</code>.
237:             *
238:             * @return the value of storeAuditEvents.
239:             * @see #setPaStoreAuditEvents
240:             */
241:            protected abstract boolean getPaStoreAuditEvents();
242:
243:            /**
244:             * The setter method for the persistent attribute
245:             * <code>storeAuditEvents</code>.
246:             *
247:             * @param newStoreAuditEvents the new value of storeAuditEvents.
248:             * @see #getPaStoreAuditEvents
249:             */
250:            protected abstract void setPaStoreAuditEvents(
251:                    boolean newStoreAuditEvents);
252:
253:            /**
254:             * Initializes the class, i.e. resets all attributes to default
255:             * values. Note that 
256:             * {@link #refresh <code>refresh</code>} will be called subsequently.
257:             * 
258:             * @see #dispose
259:             */
260:            protected void init() {
261:                setPaLastStateTime(new Date());
262:                setPaPriority(Priority.NORMAL);
263:                setPaDebug(false);
264:            }
265:
266:            /**
267:             * Called after change of persistent attributes. May be used to
268:             * synchronise state derived from persistent attributes with
269:             * the new values.
270:             *
271:             * @see #init
272:             */
273:            protected void refresh() {
274:            }
275:
276:            /**
277:             * Releases all allocated resources. The object will be in an
278:             * unusable state until resources are reallocated by calling
279:             * {@link #init <code>init</code>} and
280:             * {@link #refresh <code>refresh</code>}.
281:             */
282:            protected void dispose() {
283:            }
284:
285:            //
286:            // Domain methods
287:            //
288:
289:            /**
290:             * Returns a hash code value for this object.<P>
291:             *
292:             * Note that stubs do not in general implement
293:             * <code>hashCode</code> correctly, so even if two execution
294:             * objects are equal (<code>this.equals(obj)</code> is
295:             * <code>true</code>) <code>this.hashCode()</code> need not be
296:             * equal to <code>obj.hashCode()</code>.
297:             *
298:             * @return the hash code value.
299:             */
300:            public int hashCode() {
301:                try {
302:                    return getPaKey().hashCode();
303:                } catch (NullPointerException e) {
304:                    // workaround for jboss bug #634362
305:                    return 1;
306:                }
307:            }
308:
309:            /**
310:             * Returns the name of the execution object.
311:             * @return name of the execution object
312:             */
313:            public String name() {
314:                return getPaName();
315:            }
316:
317:            /**
318:             * Set a new name of the execution object.
319:             * @param newValue new name.
320:             * @see #name
321:             */
322:            public void setName(String newValue) {
323:                setPaName(newValue);
324:            }
325:
326:            /**
327:             * Returns the key of the execution object.
328:             * @return key of the execution object
329:             */
330:            public String key() {
331:                return getPaKey();
332:            }
333:
334:            /**
335:             * Returns the description of the execution object.
336:             * @return description of the execution object
337:             */
338:            public String description() {
339:                return getPaDescription();
340:            }
341:
342:            /**
343:             * Set a new description of the execution object.
344:             * @param newValue new description
345:             * @see #description
346:             */
347:            public void setDescription(String newValue) {
348:                setPaDescription(newValue);
349:            }
350:
351:            /**
352:             * Updates process context of the execution object.
353:             * @param newValues the name-value pairs to be set.
354:             * @throws InvalidDataException If a name or value type does not match
355:             * the signature of this process.
356:             * @throws UpdateNotAllowedException If the update is not allowed.
357:             */
358:            public void setProcessContext(ProcessData newValues)
359:                    throws InvalidDataException, UpdateNotAllowedException {
360:                throw new UpdateNotAllowedException("Not implemented.");
361:            }
362:
363:            /**
364:             * Returns the priority of the execution object.
365:             * @return priority of the execution object
366:             */
367:            public int priority() {
368:                return getPaPriority().toInt();
369:            }
370:
371:            /**
372:             * For the first iteration throws an
373:             * <code>UpdateNotAllowedException</code>.
374:             * @param newValue new priority
375:             * @throws InvalidPriorityException when the specified priority is out of 
376:             * range.
377:             * @throws UpdateNotAllowedException when the priority cannot be updated.
378:             */
379:            public void setPriority(int newValue)
380:                    throws InvalidPriorityException, UpdateNotAllowedException {
381:                setPaPriority(Priority.fromInt(newValue));
382:            }
383:
384:            /**
385:             * Enable or disable debugging of the execution object.
386:             * @param debug if the execution object is to be debugged
387:             * @throws InvalidStateException if changing debug mode is not
388:             * allowed
389:             */
390:            public void setDebugEnabled(boolean debug)
391:                    throws InvalidStateException {
392:                setPaDebug(debug);
393:            }
394:
395:            /**
396:             * Checks if the execution object is in debugging mode.
397:             *
398:             * @return <code>true</code> if the execution object is in
399:             * debugging mode
400:             */
401:            public boolean debugEnabled() {
402:                return getPaDebug();
403:            }
404:
405:            //
406:            // state handling
407:            //
408:
409:            /**
410:             * Returns the last state time of the execution object.
411:             * @return last state time of the execution object
412:             */
413:            public Date lastStateTime() {
414:                return getPaLastStateTime();
415:            }
416:
417:            /**
418:             * Returns a list of all the valid states (as <code>State</code> objects) 
419:             * that can be reached 
420:             * from the current state. If there is no valid state, the collection
421:             * will be empty.
422:             * @return list of all the valid states
423:             */
424:            protected Collection validTypedStates() {
425:                Collection c = (Collection) getStateTransitionMap().get(
426:                        getPaTypedState());
427:                if (c == null) {
428:                    return new ArrayList(0);
429:                }
430:                return c;
431:            }
432:
433:            /**
434:             * Returns a list of all the valid states as strings that can be reached 
435:             * from the current state. If there is no valid state, the collection
436:             * will be empty.
437:             * @return list of all the valid states
438:             */
439:            public Collection validStates() {
440:                Collection c = (Collection) getStateTransitionMap().get(
441:                        getPaTypedState());
442:                if (c == null) {
443:                    return new ArrayList(0);
444:                }
445:                Collection cs = new ArrayList();
446:                for (Iterator i = c.iterator(); i.hasNext();) {
447:                    cs.add(((State) i.next()).toString());
448:                }
449:                return cs;
450:            }
451:
452:            /**
453:             * Returns the {@link java.util.Map <code>Map</code>} that maps
454:             * the execution object states to a {@link java.util.Map
455:             * <code>List</code>} of reachable process states. <P>
456:             *
457:             * The map returns the state transitions allowed as parameters of
458:             * {@link
459:             * de.danet.an.workflow.localcoreapi.WfExecutionObjectLocal#changeState
460:             * <code>changeState</code>} only. I.e. the map does not reflect
461:             * all possible transitions, there may be more, but those are only
462:             * accessible to the workflow engine itself.
463:             * @return the resulting map.
464:             */
465:            protected abstract Map getStateTransitionMap();
466:
467:            /**
468:             * Updates the current state of the execution object. As a result
469:             * the state of execution objects associated with this execution
470:             * object might be updated, too. This implementation effectively
471:             * calls {@link ExecutionObjectLocal#changeState
472:             * <code>changeState(State)</code>} after converting the argument
473:             * to <code>State</code>. Derived classes therefore only need to
474:             * override <code>changeState(State)</code>.
475:             *
476:             * @param newState State to change to.
477:             * @throws InvalidStateException If <code>newState</code> is an invalid
478:             * state for the execution object.
479:             * @throws TransitionNotAllowedException If the transition from the current
480:             * state to <code>newState</code> is not allowed.
481:             */
482:            public void changeState(String newState)
483:                    throws InvalidStateException, TransitionNotAllowedException {
484:                changeState(State.fromString(newState));
485:            }
486:
487:            /**
488:             * Returns the internal state, i.e. the state represented as
489:             * <code>State</code> object.
490:             * @return internal state.
491:             * @see #updateState
492:             */
493:            public State typedState() {
494:                return getPaTypedState();
495:            }
496:
497:            /**
498:             * Updates the current state of the execution object. As a result
499:             * the state of execution objects associated with this execution object
500:             * may be updated, too. This method uses 
501:             * the <code>State</code> class to represent states.
502:             * 
503:             * @param newState the new state.
504:             * @throws InvalidStateException If <code>newState</code> is an invalid
505:             * state for the execution object.
506:             * @throws TransitionNotAllowedException If the transition from the current
507:             * state to <code>newState</code> is not allowed.
508:             */
509:            public void changeState(State newState)
510:                    throws InvalidStateException, TransitionNotAllowedException {
511:                try {
512:                    if (newState.isSameOrSubState(NotRunningState.SUSPENDED)) {
513:                        suspend();
514:                        return;
515:                    }
516:                    if (newState == OpenState.RUNNING) {
517:                        resume();
518:                        return;
519:                    }
520:                    if (newState == ClosedState.TERMINATED) {
521:                        terminate();
522:                        return;
523:                    }
524:                    if (newState == ClosedState.ABORTED) {
525:                        abort();
526:                        return;
527:                    }
528:                } catch (NotRunningException e) {
529:                    throw new TransitionNotAllowedException(e.getClass()
530:                            .getName()
531:                            + ": " + e.getMessage());
532:                } catch (InvalidControlOperationException e) {
533:                    throw new TransitionNotAllowedException(e.getClass()
534:                            .getName()
535:                            + ": " + e.getMessage());
536:                }
537:                throw new TransitionNotAllowedException(toString() + " from "
538:                        + state() + " to " + newState.toString());
539:            }
540:
541:            /**
542:             * Sets the state of this object. The method updates the last
543:             * state time and fires a state change event.
544:             *
545:             * @param newState new state.
546:             * @see #typedState
547:             */
548:            protected void updateState(State newState) {
549:                State oldState = getPaTypedState();
550:                setPaLastStateTime(new Date());
551:                setPaTypedState(newState);
552:                int auditSel = getPaAuditEventSelection();
553:                // base event information
554:                WfAuditEvent event = auditEventBase((this  instanceof  AbstractProcess) ? WfAuditEvent.PROCESS_STATE_CHANGED
555:                        : WfAuditEvent.ACTIVITY_STATE_CHANGED);
556:                // Now add general or specific information to the event. Note that we 
557:                // must always fire a state audit event if a process closes (see below),
558:                // but we have to add result information only if the event is to be 
559:                // published.
560:                if ((this  instanceof  AbstractProcess)
561:                        && newState.isSameOrSubState(State.CLOSED)
562:                        && (auditSel == ProcessDefinition.AUDIT_SELECTION_ALL_EVENTS
563:                                || auditSel == ProcessDefinition.AUDIT_SELECTION_STATE_EVENTS_ONLY || auditSel == ProcessDefinition.AUDIT_SELECTION_PROCESS_CLOSED_EVENTS_ONLY)) {
564:                    try {
565:                        event = new DefaultProcessClosedAuditEvent(event,
566:                                oldState.toString(), newState.toString(),
567:                                ((AbstractProcess) this ).result());
568:                    } catch (ResultNotAvailableException e) {
569:                        // Cannot happen, see implementation
570:                        logger.debug("Unexpected exception: " + e.getMessage(),
571:                                e);
572:                    }
573:                } else {
574:                    event = new DefaultStateAuditEvent(event, oldState
575:                            .toString(), newState.toString());
576:                }
577:                // Note that process closed events
578:                // (case AUDIT_SELECTION_PROCESS_CLOSED_EVENTS_ONLY) are fired
579:                // because they are handled by the process
580:                if (auditSel == ProcessDefinition.AUDIT_SELECTION_ALL_EVENTS
581:                        || auditSel == ProcessDefinition.AUDIT_SELECTION_STATE_EVENTS_ONLY
582:                        || AbstractActivity.isHandled(event)
583:                        || AbstractProcess.isHandled(event)) {
584:                    fireAuditEvent(event);
585:                }
586:            }
587:
588:            /**
589:             * Like {@link #updateState <code>updateState</code>} this method
590:             * sets the state of this object and fires a state change
591:             * event. The state change event will, however, not be fed back to
592:             * the engine, i.e. it will not lead to follow up activities and
593:             * the last state time will not be updated.<P>
594:             *
595:             * The method is intended to be used for an interim state change,
596:             * i.e. the caller knows that the state will change again before
597:             * the transaction is completed.
598:             *
599:             * @param newState new state.
600:             * @see #typedState
601:             */
602:            protected void updateInterim(State newState) {
603:                doUpdateNoFeedback(newState, false);
604:            }
605:
606:            /**
607:             * Like {@link #updateState <code>updateState</code>} this method
608:             * sets the state of this object and fires a state change
609:             * event. The state change event will, however, not be fed back to
610:             * the engine, i.e. it will not lead to follow up activities.<P>
611:             *
612:             * The method is intended to be used in cases where the engine triggers
613:             * a state change itself and also performs all actions that are usually
614:             * done in the event handling method.
615:             *
616:             * @param newState new state.
617:             * @see #typedState
618:             */
619:            protected void updateImmediate(State newState) {
620:                doUpdateNoFeedback(newState, true);
621:            }
622:
623:            private void doUpdateNoFeedback(State newState,
624:                    boolean updateStateTime) {
625:                State oldState = getPaTypedState();
626:                setPaTypedState(newState);
627:                if (updateStateTime) {
628:                    setPaLastStateTime(new Date());
629:                }
630:                int auditSel = getPaAuditEventSelection();
631:                if (auditSel == ProcessDefinition.AUDIT_SELECTION_ALL_EVENTS
632:                        || auditSel == ProcessDefinition.AUDIT_SELECTION_STATE_EVENTS_ONLY) {
633:                    fireAuditEvent(new DefaultStateAuditEvent(
634:                            auditEventBase((this  instanceof  AbstractProcess) ? WfAuditEvent.PROCESS_STATE_CHANGED
635:                                    : WfAuditEvent.ACTIVITY_STATE_CHANGED),
636:                            oldState.toString(), newState.toString(), true));
637:                }
638:            }
639:
640:            /**
641:             * Returns the workflow state.
642:             * @return the workflow state.
643:             */
644:            public State workflowState() {
645:                return getPaTypedState().workflowState();
646:            }
647:
648:            /**
649:             * Returns the workflow substate for open execution objects.
650:             * @return the workflow substate.
651:             */
652:            public State whileOpen() {
653:                return getPaTypedState().whileOpenState();
654:            }
655:
656:            /**
657:             * Returns the workflow substate for open, not running
658:             * execution objects.
659:             * @return the workflow substate.
660:             */
661:            public State whyNotRunning() {
662:                return getPaTypedState().whyNotRunningState();
663:            }
664:
665:            /**
666:             * Returns the workflow substate for closed
667:             * execution objects.
668:             * @return the workflow substate.
669:             */
670:            public State howClosed() {
671:                return getPaTypedState().howClosedState();
672:            }
673:
674:            /**
675:             * Returns the string representation of the state.
676:             * @return string representation of the state.
677:             */
678:            public String state() {
679:                return getPaTypedState().toString();
680:            }
681:
682:            /* Comment copied from Interface. */
683:            public void suspend() throws CannotSuspendException,
684:                    NotRunningException, AlreadySuspendedException {
685:                if (typedState().isSameOrSubState(NotRunningState.SUSPENDED)) {
686:                    throw new AlreadySuspendedException(toString());
687:                }
688:                if (!typedState().isSameOrSubState(OpenState.RUNNING)) {
689:                    throw new NotRunningException(toString() + " is " + state());
690:                }
691:                if (!validTypedStates().contains(NotRunningState.SUSPENDED)) {
692:                    throw new CannotSuspendException(toString() + " is "
693:                            + state());
694:                }
695:                updateState(SuspendedState.SUSPENDED);
696:            }
697:
698:            /* Comment copied from Interface. */
699:            public void resume() throws CannotResumeException,
700:                    NotRunningException, NotSuspendedException {
701:                if (!typedState().isSameOrSubState(OpenState.RUNNING)
702:                        && !typedState().isSameOrSubState(
703:                                SuspendedState.SUSPENDED)) {
704:                    throw new NotRunningException(toString() + " is " + state());
705:                }
706:                if (!typedState().isSameOrSubState(NotRunningState.SUSPENDED)) {
707:                    throw new NotSuspendedException(toString());
708:                }
709:                if (!validTypedStates().contains(OpenState.RUNNING)) {
710:                    throw new CannotResumeException(toString() + " is "
711:                            + state());
712:                }
713:                updateState(RunningState.RUNNING);
714:            }
715:
716:            /* Comment copied from Interface. */
717:            public void terminate() throws CannotStopException,
718:                    NotRunningException {
719:                throw new CannotStopException(toString()
720:                        + " cannot be terminated.");
721:            }
722:
723:            /* Comment copied from Interface. */
724:            public void abort() throws CannotStopException, NotRunningException {
725:                throw new CannotStopException(toString()
726:                        + " cannot be aborted.");
727:            }
728:
729:            /* Comment copied from Interface. */
730:            public abstract Collection history()
731:                    throws HistoryNotAvailableException;
732:
733:            //
734:            // Audit handling
735:            //
736:
737:            /**
738:             * Returns a <code>WfAuditEvent</code> containing information about the 
739:             * execution object.
740:             * @param eventType event type
741:             * @return the event containing the required information.
742:             */
743:            protected abstract WfAuditEvent auditEventBase(String eventType);
744:
745:            private static ThreadLocal queuingEvents = new ThreadLocal() {
746:                protected Object initialValue() {
747:                    return Boolean.FALSE;
748:                }
749:            };
750:            private static ThreadLocal eventQueue = new ThreadLocal() {
751:                protected Object initialValue() {
752:                    return new ArrayList();
753:                }
754:            };
755:
756:            /**
757:             * Process newly generated event. This fall-back implementation
758:             * logs the event with level <code>DEBUG</code> and calls handlers
759:             * for state change events. If the event source is an
760:             * <code>AbstractProcess</code> its <code>handleAuditEvent</code>
761:             * is called. If the event source is an
762:             * <code>AbstractActivity</code> both the activity's and the
763:             * process' handler are called.<P>
764:             *
765:             * This implementation is mainly intended for unit tests on the
766:             * domain level. It must be overridden by the derived classes.
767:             *
768:             * @param event Event
769:             */
770:            protected void fireAuditEvent(WfAuditEvent event) {
771:                logger.debug(event.toString());
772:                List eq = (List) eventQueue.get();
773:                eq.add(event);
774:                if (((Boolean) queuingEvents.get()).booleanValue()) {
775:                    return;
776:                }
777:                queuingEvents.set(Boolean.TRUE);
778:                while (eq.size() > 0) {
779:                    event = (WfAuditEvent) eq.remove(0);
780:                    if ((event instanceof  WfStateAuditEvent)
781:                            || (event instanceof  ImplCompleteAuditEvent)) {
782:                        try {
783:                            WfExecutionObject eo = event.source();
784:                            if (eo instanceof  ExtProcess) {
785:                                ((ExtProcess) eo).handleAuditEvent(event);
786:                            } else if (eo instanceof  ExtActivity) {
787:                                ExtActivity aAct = (ExtActivity) eo;
788:                                aAct.handleAuditEvent(event);
789:                                if (!(event instanceof  ImplCompleteAuditEvent)) {
790:                                    ((ExtProcess) aAct.container())
791:                                            .handleAuditEvent(event);
792:                                }
793:                            }
794:                        } catch (SourceNotAvailableException e) {
795:                            // can't do anything about this
796:                            logger.error("Event discarded: " + e.getMessage(),
797:                                    e);
798:                        } catch (RemoteException e) {
799:                            // shouldn't really happen on domain level
800:                            logger.error(e.getMessage(), e);
801:                        }
802:                    }
803:                }
804:                queuingEvents.set(Boolean.FALSE);
805:            }
806:
807:            /**
808:             * Handles the given audit event. The fall back implementation
809:             * simply calls
810:             * <code>AbstractExecutionObject.handleStateAuditEvent</code> if
811:             * the event source is this object and the event is a
812:             * <code>WfStateAuditEvent</code> or a
813:             * <code>ToolCompletedAuditEvent</code> .
814:             * @param event the event.
815:             * @ejb.interface-method view-type="remote"
816:             */
817:            public void handleAuditEvent(WfAuditEvent event) {
818:                if (logger.isDebugEnabled()) {
819:                    logger.debug("Got event: " + event.toString());
820:                }
821:                // Is this the target?
822:                if (event.activityKey() == null) {
823:                    if (!(this  instanceof  AbstractProcess)
824:                            || !event.processKey().equals(getPaKey())) {
825:                        return;
826:                    }
827:                } else {
828:                    if (!(this  instanceof  AbstractActivity)
829:                            || !event.activityKey().equals(getPaKey())) {
830:                        return;
831:                    }
832:                }
833:                if (event instanceof  ToolInvocationFailedAuditEvent) {
834:                    handleToolInvocationFailedAuditEvent((ToolInvocationFailedAuditEvent) event);
835:                    return;
836:                }
837:                if ((event instanceof  WfStateAuditEvent)
838:                        || (event instanceof  ImplCompleteAuditEvent)) {
839:                    handleStateAuditEvent(event);
840:                }
841:            }
842:
843:            /**
844:             * Handles a tool invocation failed audit event. The default
845:             * implementation does nothing.
846:             * @param event the event.
847:             */
848:            protected void handleToolInvocationFailedAuditEvent(
849:                    ToolInvocationFailedAuditEvent event) {
850:            }
851:
852:            /**
853:             * Handles a state audit event, this includes
854:             * <code>ImplCompleteAuditEvent</code>s. This implementation
855:             * simply calls the appropriate handler method
856:             * <code>handle<i>Transition</i>Event</code>.
857:             * @param event the event.
858:             */
859:            protected void handleStateAuditEvent(WfAuditEvent event) {
860:                try {
861:                    if (event instanceof  ImplCompleteAuditEvent) {
862:                        handleImplCompletedEvent((ImplCompleteAuditEvent) event);
863:                        return;
864:                    }
865:                    WfStateAuditEvent evt = (WfStateAuditEvent) event;
866:                    State oldState = State.fromString(evt.oldState());
867:                    State newState = State.fromString(evt.newState());
868:                    if (oldState.isSameOrSubState(NotRunningState.NOT_STARTED)) {
869:                        if (newState == RunningState.RUNNING) {
870:                            handleStartedEvent(evt);
871:                            return;
872:                        }
873:                        if (newState == ClosedState.TERMINATED) {
874:                            handleTerminatedEvent(evt);
875:                            return;
876:                        }
877:                    } else if (oldState
878:                            .isSameOrSubState(NotRunningState.SUSPENDED)) {
879:                        if (newState == RunningState.RUNNING) {
880:                            handleResumedEvent(evt);
881:                            return;
882:                        }
883:                        if (newState == ClosedState.ABORTED) {
884:                            handleAbortedEvent(evt);
885:                            return;
886:                        }
887:                    } else if (oldState.isSameOrSubState(OpenState.RUNNING)) {
888:                        if (newState == SuspendedState.SUSPENDED) {
889:                            handleSuspendedEvent(evt);
890:                            return;
891:                        }
892:                        if (newState == ClosedCompletedState.NORMAL) {
893:                            handleCompletedEvent(evt);
894:                            return;
895:                        }
896:                        if (newState == ClosedState.TERMINATED) {
897:                            handleTerminatedEvent(evt);
898:                            return;
899:                        }
900:                    }
901:                    logger
902:                            .warn("Cannot handle undefined state transition from "
903:                                    + oldState.toString()
904:                                    + " to "
905:                                    + newState.toString() + " for " + this );
906:                } catch (InvalidStateException e) {
907:                    // can't do much about this, shouldn't happen
908:                    logger.error(e.getMessage(), e);
909:                }
910:            }
911:
912:            /**
913:             * Handles a tool completed audit event. The default
914:             * implementation does nothing.
915:             * @param event the event.
916:             */
917:            protected void handleImplCompletedEvent(ImplCompleteAuditEvent event) {
918:            }
919:
920:            /**
921:             * Handles a started audit event. The default
922:             * implementation does nothing.
923:             * @param event the event.
924:             */
925:            protected void handleStartedEvent(WfStateAuditEvent event) {
926:            }
927:
928:            /**
929:             * Handles a terminated audit event. The default
930:             * implementation does nothing.
931:             * @param event the event.
932:             */
933:            protected void handleTerminatedEvent(WfStateAuditEvent event) {
934:            }
935:
936:            /**
937:             * Handles a resumed audit event. The default
938:             * implementation does nothing.
939:             * @param event the event.
940:             */
941:            protected void handleResumedEvent(WfStateAuditEvent event) {
942:            }
943:
944:            /**
945:             * Handles a aborting audit event. The default
946:             * implementation does nothing.
947:             * @param event the event.
948:             */
949:            protected void handleAbortedEvent(WfStateAuditEvent event) {
950:            }
951:
952:            /**
953:             * Handles a suspended audit event. The default
954:             * implementation does nothing.
955:             * @param event the event.
956:             */
957:            protected void handleSuspendedEvent(WfStateAuditEvent event) {
958:            }
959:
960:            /**
961:             * Handles a completed audit event. The default
962:             * implementation does nothing.
963:             * @param event the event.
964:             */
965:            protected void handleCompletedEvent(WfStateAuditEvent event) {
966:            }
967:
968:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.