KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cayenne > access > ClientServerChannelQueryAction


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
20 package org.apache.cayenne.access;
21
22 import java.util.ArrayList JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.List JavaDoc;
25
26 import org.apache.cayenne.CayenneRuntimeException;
27 import org.apache.cayenne.ObjectId;
28 import org.apache.cayenne.Persistent;
29 import org.apache.cayenne.QueryResponse;
30 import org.apache.cayenne.map.EntityResolver;
31 import org.apache.cayenne.query.PrefetchTreeNode;
32 import org.apache.cayenne.query.Query;
33 import org.apache.cayenne.query.QueryMetadata;
34 import org.apache.cayenne.reflect.ClassDescriptor;
35 import org.apache.cayenne.util.GenericResponse;
36 import org.apache.cayenne.util.IncrementalListResponse;
37 import org.apache.cayenne.util.ListResponse;
38 import org.apache.cayenne.util.ObjectDetachOperation;
39
40 /**
41  * A query handler used by ClientServerChannel.
42  *
43  * @since 1.2
44  * @author Andrus Adamchik
45  */

46 class ClientServerChannelQueryAction {
47
48     static final boolean DONE = true;
49
50     private final ClientServerChannel channel;
51     private Query serverQuery;
52     private QueryResponse response;
53     private final QueryMetadata serverMetadata;
54     private final EntityResolver serverResolver;
55
56     ClientServerChannelQueryAction(ClientServerChannel channel, Query query) {
57         this.channel = channel;
58         this.serverResolver = channel.getEntityResolver();
59         this.serverQuery = query;
60         this.serverMetadata = serverQuery.getMetaData(serverResolver);
61     }
62
63     QueryResponse execute() {
64
65         if (interceptSinglePageQuery() != DONE) {
66             runQuery();
67         }
68
69         if (interceptIncrementalListConversion() != DONE) {
70             interceptObjectConversion();
71         }
72
73         return response;
74     }
75
76     private boolean interceptSinglePageQuery() {
77
78         // retrieve range from the previously cached list
79
if (serverMetadata.getFetchStartIndex() >= 0
80                 && serverMetadata.getFetchLimit() > 0
81                 && serverMetadata.getCacheKey() != null) {
82
83             List JavaDoc cachedList = channel.getQueryCache().get(serverMetadata);
84             if (cachedList == null) {
85                 throw new CayenneRuntimeException("No cached list for "
86                         + serverMetadata.getCacheKey());
87             }
88
89             int startIndex = serverMetadata.getFetchStartIndex();
90             int endIndex = startIndex + serverMetadata.getFetchLimit();
91
92             // send back just one page... query sender will figure out where it fits in
93
// the incremental list
94
this.response = new ListResponse(new ArrayList JavaDoc(cachedList.subList(
95                     startIndex,
96                     endIndex)));
97
98             return DONE;
99         }
100
101         return !DONE;
102     }
103
104     private void runQuery() {
105         this.response = channel.getParentChannel().onQuery(null, serverQuery);
106     }
107
108     private boolean interceptIncrementalListConversion() {
109         int pageSize = serverMetadata.getPageSize();
110         if (pageSize > 0 && serverMetadata.getCacheKey() != null) {
111
112             List JavaDoc list = response.firstList();
113             if (list.size() > pageSize && list instanceof IncrementalFaultList) {
114
115                 // cache
116
channel.getQueryCache().put(serverMetadata, list);
117
118                 // extract and convert first page
119

120                 List JavaDoc sublist = list.subList(0, pageSize);
121
122                 List JavaDoc firstPage = (serverMetadata.isFetchingDataRows()) ? new ArrayList JavaDoc(
123                         sublist) : toClientObjects(sublist);
124
125                 this.response = new IncrementalListResponse(firstPage, list.size());
126                 return DONE;
127             }
128         }
129
130         return !DONE;
131     }
132
133     private void interceptObjectConversion() {
134
135         if (!serverMetadata.isFetchingDataRows()) {
136
137             GenericResponse clientResponse = new GenericResponse();
138
139             for (response.reset(); response.next();) {
140                 if (response.isList()) {
141                     List JavaDoc serverObjects = response.currentList();
142                     clientResponse.addResultList(toClientObjects(serverObjects));
143
144                 }
145                 else {
146                     clientResponse.addBatchUpdateCount(response.currentUpdateCount());
147                 }
148             }
149
150             this.response = clientResponse;
151         }
152     }
153
154     private List JavaDoc toClientObjects(List JavaDoc serverObjects) {
155
156         // create a list copy even if it is empty to ensure that we have a
157
// clean serializable list...
158
List JavaDoc clientObjects = new ArrayList JavaDoc(serverObjects.size());
159
160         if (!serverObjects.isEmpty()) {
161             ObjectDetachOperation op = new ObjectDetachOperation(serverResolver
162                     .getClientEntityResolver());
163             Iterator JavaDoc it = serverObjects.iterator();
164             PrefetchTreeNode prefetchTree = serverMetadata.getPrefetchTree();
165
166             while (it.hasNext()) {
167                 Persistent object = (Persistent) it.next();
168                 ObjectId id = object.getObjectId();
169
170                 // sanity check
171
if (id == null) {
172                     throw new CayenneRuntimeException(
173                             "Server returned an object without an id: " + object);
174                 }
175
176                 // have to resolve descriptor here for every object, as
177
// often a query will not have any info indicating the
178
// entity type
179
ClassDescriptor serverDescriptor = serverResolver.getClassDescriptor(id
180                         .getEntityName());
181
182                 clientObjects.add(op.detach(object, serverDescriptor, prefetchTree));
183             }
184         }
185
186         return clientObjects;
187     }
188
189 }
190
Popular Tags