/*****************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
****************************************************************/
package org.apache.cayenne;
import java.util.Collection;
import java.util.Iterator;
import org.apache.cayenne.cache.QueryCacheEntryFactory;
import org.apache.cayenne.cache.QueryCache;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.RefreshQuery;
import org.apache.cayenne.remote.RemoteIncrementalFaultList;
import org.apache.cayenne.util.ListResponse;
import org.apache.cayenne.util.ObjectContextQueryAction;
/**
* @since 1.2
* @author Andrus Adamchik
*/
class CayenneContextQueryAction extends ObjectContextQueryAction {
CayenneContextQueryAction(CayenneContext actingContext, ObjectContext targetContext,
Query query) {
super(actingContext, targetContext, query);
}
public QueryResponse execute() {
if (interceptOIDQuery() != DONE) {
if (interceptRelationshipQuery() != DONE) {
if (interceptRefreshQuery() != DONE) {
if (interceptLocalCache() != DONE) {
if (interceptPaginatedQuery() != DONE) {
runQuery();
}
}
}
}
}
interceptObjectConversion();
return response;
}
private boolean interceptPaginatedQuery() {
if (metadata.getPageSize() > 0) {
response = new ListResponse(new RemoteIncrementalFaultList(
actingContext,
query));
return DONE;
}
return !DONE;
}
protected QueryCache getQueryCache() {
return ((CayenneContext) actingContext).getQueryCache();
}
protected QueryCacheEntryFactory getCacheObjectFactory() {
return new QueryCacheEntryFactory() {
public Object createObject() {
if (interceptPaginatedQuery() != DONE) {
runQuery();
}
return response.firstList();
}
};
}
private boolean interceptRefreshQuery() {
if (query instanceof RefreshQuery) {
RefreshQuery refreshQuery = (RefreshQuery) query;
CayenneContext context = (CayenneContext) actingContext;
// handle 4 separate scenarious, but do not combine them as it will be
// unclear how to handle cascading behavior
// 1. refresh all
if (refreshQuery.isRefreshAll()) {
invalidateLocally(context.internalGraphManager(), context
.internalGraphManager()
.registeredNodes()
.iterator());
context.getQueryCache().clear();
// cascade
return !DONE;
}
// 2. invalidate object collection
Collection objects = refreshQuery.getObjects();
if (objects != null && !objects.isEmpty()) {
invalidateLocally(context.internalGraphManager(), objects.iterator());
// cascade
return !DONE;
}
// 3. refresh query - have to do it eagerly to refresh the objects involved
if (refreshQuery.getQuery() != null) {
Query cachedQuery = refreshQuery.getQuery();
String cacheKey = cachedQuery
.getMetaData(context.getEntityResolver())
.getCacheKey();
context.getQueryCache().remove(cacheKey);
this.response = context.performGenericQuery(cachedQuery);
// do not cascade to avoid running query twice
return DONE;
}
// 4. refresh groups...
if (refreshQuery.getGroupKeys() != null
&& refreshQuery.getGroupKeys().length > 0) {
String[] groups = refreshQuery.getGroupKeys();
for (int i = 0; i < groups.length; i++) {
context.getQueryCache().removeGroup(groups[i]);
}
// cascade group invalidation
return !DONE;
}
}
return !DONE;
}
private void invalidateLocally(CayenneContextGraphManager graphManager, Iterator it) {
while (it.hasNext()) {
Persistent object = (Persistent) it.next();
// we don't care about NEW objects,
// but we still do care about HOLLOW, since snapshot might still be
// present
if (object.getPersistenceState() == PersistenceState.NEW) {
continue;
}
object.setPersistenceState(PersistenceState.HOLLOW);
// remove cached changes
graphManager.changeLog.unregisterNode(object.getObjectId());
graphManager.stateLog.unregisterNode(object.getObjectId());
}
}
}