KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cayenne > intercept > DataChannelCallbackInterceptor


1 /*****************************************************************
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  ****************************************************************/

19 package org.apache.cayenne.intercept;
20
21 import java.util.List JavaDoc;
22
23 import org.apache.cayenne.DataChannel;
24 import org.apache.cayenne.LifecycleListener;
25 import org.apache.cayenne.ObjectContext;
26 import org.apache.cayenne.QueryResponse;
27 import org.apache.cayenne.graph.GraphDiff;
28 import org.apache.cayenne.graph.GraphManager;
29 import org.apache.cayenne.query.Query;
30 import org.apache.cayenne.reflect.LifecycleCallbackRegistry;
31
32 /**
33  * Implements JPA-compliant "PreUpdate", "PostUpdate", "PostPersist", "PostRemove",
34  * "PostLoad" callbacks for the DataChannel operations. <p/>Depending on how callbacks are
35  * registered, they are invoked either on persistent object instances directly or on an
36  * instance of an arbitrary listener class. Signature of a callback method of a persistent
37  * object is <code>"void method()"</code>, while for a non-persistent listener it is
38  * <code>"void method(Object)"</code>. <p/>Note that this interceptor does not apply
39  * "PreRemove" and "PrePersist" callbacks during "onSync", assuming that a child
40  * ObjectContext did that already. It is often used in conjunction with
41  * {@link ObjectContextCallbackInterceptor} that adds those callbacks.
42  *
43  * @see ObjectContextCallbackInterceptor
44  * @since 3.0
45  * @author Andrus Adamchik
46  */

47 public class DataChannelCallbackInterceptor extends DataChannelDecorator {
48
49     protected LifecycleCallbackRegistry callbackRegistry;
50     protected boolean contextCallbacksEnabled;
51
52     public void setChannel(DataChannel channel) {
53         this.channel = channel;
54
55         callbackRegistry = (channel != null)
56                 ? getEntityResolver().getCallbackRegistry()
57                 : null;
58     }
59
60     protected boolean isEmpty() {
61         if (!(callbackRegistry.isEmpty(LifecycleListener.PRE_UPDATE)
62                 && callbackRegistry.isEmpty(LifecycleListener.POST_PERSIST)
63                 && callbackRegistry.isEmpty(LifecycleListener.POST_REMOVE)
64                 && callbackRegistry.isEmpty(LifecycleListener.POST_UPDATE) && callbackRegistry
65                 .isEmpty(LifecycleListener.POST_LOAD))) {
66             return false;
67         }
68
69         return contextCallbacksEnabled ? callbackRegistry.isEmpty(LifecycleListener.PRE_REMOVE)
70                 && callbackRegistry.isEmpty(LifecycleListener.PRE_PERSIST) : true;
71     }
72
73     public QueryResponse onQuery(ObjectContext originatingContext, Query query) {
74         QueryResponse response = channel.onQuery(originatingContext, query);
75
76         // TODO: andrus, 9/21/2006 - this method incorrectly calls "postLoad" when query
77
// refresh flag is set to false and object is already there.
78

79         if (!callbackRegistry.isEmpty(LifecycleListener.POST_LOAD)) {
80
81             List JavaDoc list = response.firstList();
82             if (list != null
83                     && !list.isEmpty()
84                     && !(query.getMetaData(channel.getEntityResolver()))
85                             .isFetchingDataRows()) {
86                 callbackRegistry.performCallbacks(LifecycleListener.POST_LOAD, list);
87             }
88         }
89
90         return response;
91     }
92
93     public GraphDiff onSync(
94             ObjectContext originatingContext,
95             GraphDiff changes,
96             int syncType) {
97
98         if (isEmpty()) {
99             return channel.onSync(originatingContext, changes, syncType);
100         }
101
102         SyncCallbackProcessor processor = createSyncProcessor(originatingContext
103                 .getGraphManager(), changes);
104
105         processor.applyPreCommit(syncType);
106         GraphDiff parentDiff = channel.onSync(originatingContext, changes, syncType);
107         processor.applyPostCommit(syncType);
108
109         return parentDiff;
110     }
111
112     SyncCallbackProcessor createSyncProcessor(GraphManager graphManager, GraphDiff changes) {
113         return new SyncCallbackProcessor(this, graphManager, changes);
114     }
115
116     /**
117      * Returns whether "PrePersist" and "PreRemove" callbacks should be executed during
118      * sync. By default this is false, as they are executed by the parent ObjectContext.
119      * This can be changed by calling {@link #setContextCallbacksEnabled(boolean)}.
120      */

121     public boolean isContextCallbacksEnabled() {
122         return contextCallbacksEnabled;
123     }
124
125     public void setContextCallbacksEnabled(boolean contextCallbacksEnabled) {
126         this.contextCallbacksEnabled = contextCallbacksEnabled;
127     }
128
129     public LifecycleCallbackRegistry getCallbackRegistry() {
130         return callbackRegistry;
131     }
132 }
133
Popular Tags