Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/objectstyle/cayenne/access/util/ContextCommitObserver.java


1   /* ====================================================================
2    * 
3    * The ObjectStyle Group Software License, Version 1.0 
4    *
5    * Copyright (c) 2002-2003 The ObjectStyle Group 
6    * and individual authors of the software.  All rights reserved.
7    *
8    * Redistribution and use in source and binary forms, with or without
9    * modification, are permitted provided that the following conditions
10   * are met:
11   *
12   * 1. Redistributions of source code must retain the above copyright
13   *    notice, this list of conditions and the following disclaimer. 
14   *
15   * 2. Redistributions in binary form must reproduce the above copyright
16   *    notice, this list of conditions and the following disclaimer in
17   *    the documentation and/or other materials provided with the
18   *    distribution.
19   *
20   * 3. The end-user documentation included with the redistribution, if
21   *    any, must include the following acknowlegement:  
22   *       "This product includes software developed by the 
23   *        ObjectStyle Group (http://objectstyle.org/)."
24   *    Alternately, this acknowlegement may appear in the software itself,
25   *    if and wherever such third-party acknowlegements normally appear.
26   *
27   * 4. The names "ObjectStyle Group" and "Cayenne" 
28   *    must not be used to endorse or promote products derived
29   *    from this software without prior written permission. For written 
30   *    permission, please contact andrus@objectstyle.org.
31   *
32   * 5. Products derived from this software may not be called "ObjectStyle"
33   *    nor may "ObjectStyle" appear in their names without prior written
34   *    permission of the ObjectStyle Group.
35   *
36   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39   * DISCLAIMED.  IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
40   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47   * SUCH DAMAGE.
48   * ====================================================================
49   *
50   * This software consists of voluntary contributions made by many
51   * individuals on behalf of the ObjectStyle Group.  For more
52   * information on the ObjectStyle Group, please see
53   * <http://objectstyle.org/>.
54   *
55   */
56  package org.objectstyle.cayenne.access.util;
57  
58  import java.util.ArrayList;
59  import java.util.Arrays;
60  import java.util.Collection;
61  import java.util.Iterator;
62  import java.util.List;
63  import java.util.Map;
64  
65  import org.apache.log4j.Level;
66  import org.objectstyle.cayenne.CayenneRuntimeException;
67  import org.objectstyle.cayenne.DataObject;
68  import org.objectstyle.cayenne.ObjectId;
69  import org.objectstyle.cayenne.PersistenceState;
70  import org.objectstyle.cayenne.TempObjectId;
71  import org.objectstyle.cayenne.access.DataContext;
72  import org.objectstyle.cayenne.access.ObjectStore;
73  import org.objectstyle.cayenne.access.event.DataContextEvent;
74  import org.objectstyle.cayenne.access.event.DataContextTransactionEventListener;
75  import org.objectstyle.cayenne.access.event.DataObjectTransactionEventListener;
76  import org.objectstyle.cayenne.event.EventManager;
77  import org.objectstyle.cayenne.query.Query;
78  import org.objectstyle.cayenne.util.Util;
79  
80  /**
81   * ContextCommitObserver is used as an observer for DataContext 
82   * commit operations.
83   * 
84   * @author Andrei Adamchik
85   */
86  public class ContextCommitObserver
87      extends DefaultOperationObserver
88      implements DataContextTransactionEventListener {
89  
90      protected List updObjects;
91      protected List delObjects;
92      protected List insObjects;
93      protected List objectsToNotify;
94  
95      protected DataContext context;
96  
97      public ContextCommitObserver(
98          Level logLevel,
99          DataContext context,
100         List insObjects,
101         List updObjects,
102         List delObjects) {
103         super.setLoggingLevel(logLevel);
104         this.context = context;
105         this.insObjects = insObjects;
106         this.updObjects = updObjects;
107         this.delObjects = delObjects;
108         this.objectsToNotify = new ArrayList();
109 
110         // Build a list of objects that need to be notified about posted
111         // DataContext events. When notifying about a successful completion
112         // of a transaction we cannot build this list anymore, since all
113         // the work will be done by then.
114         Iterator collIter =
115             (Arrays.asList(new List[] { delObjects, updObjects, insObjects }))
116                 .iterator();
117         while (collIter.hasNext()) {
118             Iterator objIter = ((Collection) collIter.next()).iterator();
119             while (objIter.hasNext()) {
120                 Object element = objIter.next();
121                 if (element instanceof DataObjectTransactionEventListener) {
122                     this.objectsToNotify.add(element);
123                 }
124             }
125         }
126     }
127 
128     public boolean useAutoCommit() {
129         return false;
130     }
131 
132     /** Update the state of all objects we were synchronizing
133      *  in this transaction.
134      */
135     public void transactionCommitted() {
136         super.transactionCommitted();
137 
138         Iterator insIt = insObjects.iterator();
139         ObjectStore objectStore = context.getObjectStore();
140 
141         synchronized (objectStore) {
142             while (insIt.hasNext()) {
143 
144                 // replace temp id's w/perm.
145                 DataObject nextObject = (DataObject) insIt.next();
146                 TempObjectId tempId = (TempObjectId) nextObject.getObjectId();
147                 ObjectId permId = tempId.getPermId();
148 
149                 objectStore.changeObjectKey(tempId, permId);
150                 nextObject.setObjectId(permId);
151                 Map snapshot = context.takeObjectSnapshot(nextObject);
152                 objectStore.addSnapshot(permId, snapshot);
153 
154                 nextObject.setPersistenceState(PersistenceState.COMMITTED);
155             }
156         }
157 
158         Iterator delIt = delObjects.iterator();
159         while (delIt.hasNext()) {
160             DataObject nextObject = (DataObject) delIt.next();
161             ObjectId anId = nextObject.getObjectId();
162 
163             objectStore.removeObject(anId);
164             nextObject.setPersistenceState(PersistenceState.TRANSIENT);
165             nextObject.setDataContext(null);
166         }
167 
168         Iterator updIt = updObjects.iterator();
169         while (updIt.hasNext()) {
170             DataObject nextObject = (DataObject) updIt.next();
171             // refresh this object's snapshot, check if id data has changed
172             Map snapshot = context.takeObjectSnapshot(nextObject);
173 
174             objectStore.addSnapshot(nextObject.getObjectId(), snapshot);
175             nextObject.setPersistenceState(PersistenceState.COMMITTED);
176         }
177     }
178 
179     public void nextQueryException(Query query, Exception ex) {
180         super.nextQueryException(query, ex);
181         throw new CayenneRuntimeException(
182             "Raising from query exception.",
183             Util.unwindException(ex));
184     }
185 
186     public void nextGlobalException(Exception ex) {
187         super.nextGlobalException(ex);
188         throw new CayenneRuntimeException(
189             "Raising from underlyingQueryEngine exception.",
190             Util.unwindException(ex));
191     }
192 
193     public void registerForDataContextEvents() {
194         try {
195             EventManager mgr = EventManager.getDefaultManager();
196             mgr.addListener(
197                 this,
198                 "dataContextWillCommit",
199                 DataContextEvent.class,
200                 DataContext.WILL_COMMIT,
201                 this.context);
202             mgr.addListener(
203                 this,
204                 "dataContextDidCommit",
205                 DataContextEvent.class,
206                 DataContext.DID_COMMIT,
207                 this.context);
208             mgr.addListener(
209                 this,
210                 "dataContextDidRollback",
211                 DataContextEvent.class,
212                 DataContext.DID_ROLLBACK,
213                 this.context);
214         } catch (NoSuchMethodException nsm) {
215             // this really should not happen since we implement all required methods
216             throw new CayenneRuntimeException(nsm);
217         }
218     }
219 
220     public void unregisterFromDataContextEvents() {
221         EventManager mgr = EventManager.getDefaultManager();
222         mgr.removeListener(this, DataContext.WILL_COMMIT);
223         mgr.removeListener(this, DataContext.DID_COMMIT);
224         mgr.removeListener(this, DataContext.DID_ROLLBACK);
225     }
226 
227     public void dataContextWillCommit(DataContextEvent event) {
228         Iterator iter = objectsToNotify.iterator();
229         while (iter.hasNext()) {
230             ((DataObjectTransactionEventListener) iter.next()).willCommit(
231                 event);
232         }
233     }
234 
235     public void dataContextDidCommit(DataContextEvent event) {
236         Iterator iter = objectsToNotify.iterator();
237         while (iter.hasNext()) {
238             ((DataObjectTransactionEventListener) iter.next()).didCommit(event);
239         }
240     }
241 
242     public void dataContextDidRollback(DataContextEvent event) {
243         // do nothing for now
244     }
245 }