1 19 20 package org.apache.cayenne.access; 21 22 import java.util.ArrayList ; 23 import java.util.Iterator ; 24 import java.util.List ; 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 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 if (serverMetadata.getFetchStartIndex() >= 0 80 && serverMetadata.getFetchLimit() > 0 81 && serverMetadata.getCacheKey() != null) { 82 83 List 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 this.response = new ListResponse(new ArrayList (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 list = response.firstList(); 113 if (list.size() > pageSize && list instanceof IncrementalFaultList) { 114 115 channel.getQueryCache().put(serverMetadata, list); 117 118 120 List sublist = list.subList(0, pageSize); 121 122 List firstPage = (serverMetadata.isFetchingDataRows()) ? new ArrayList ( 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 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 toClientObjects(List serverObjects) { 155 156 List clientObjects = new ArrayList (serverObjects.size()); 159 160 if (!serverObjects.isEmpty()) { 161 ObjectDetachOperation op = new ObjectDetachOperation(serverResolver 162 .getClientEntityResolver()); 163 Iterator 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 if (id == null) { 172 throw new CayenneRuntimeException( 173 "Server returned an object without an id: " + object); 174 } 175 176 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 |