Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.KeyRange;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.PropertyProjection;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.Filter;
import com.google.appengine.api.datastore.QueryResultList;
Expand Down Expand Up @@ -589,7 +590,16 @@ public void putIfChanged(Collection<CachedEntity> entities)
}

public void put(Collection<CachedEntity> entities)
{
{
entities.removeIf(entity -> {
if(entity.projected) {
log.log(Level.WARNING, "Attempted to save a projected entity with key " + entity.getKey().toString());
return true;
}
else return false;
});


if (bulkPutMode)
{
entitiesToBulkPut.removeAll(entities);
Expand Down Expand Up @@ -653,6 +663,10 @@ public void put(Collection<CachedEntity> entities)

public void put(CachedEntity entity)
{
if(entity.projected) {
log.log(Level.WARNING, "Attempted to save a projected entity with key " + entity.getKey().toString());
return;
}
if (bulkPutMode)
{
entitiesToBulkPut.remove(entity);
Expand Down Expand Up @@ -1187,8 +1201,31 @@ else if (dbEntity!=null)
return result;
}



/**
* This method returns partial entities.
* @param limit
* @param q
* @param projections
* @return
*/
public List<CachedEntity> fetchProjectedList(int limit, Query q, Set<String> projections){

for(String proj : projections) {
q.addProjection(new PropertyProjection(proj, null));
}

prepareQuery(q);

FetchOptions fo = FetchOptions.Builder.withLimit(limit).chunkSize(limit).prefetchSize(limit);

List<Entity> entities = pq.asList(fo);
List<CachedEntity> result = new ArrayList<>();


entities.forEach(n -> result.add(CachedEntity.wrap(n, true)));

return result;
}


public CachedEntity fetchSingleEntity(Query q)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,36 @@
package com.universeprojects.cacheddatastore;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.RawValue;
import com.google.appengine.api.datastore.Text;

public class CachedEntity implements Cloneable,Serializable {
private static Logger log = Logger.getLogger(CachedEntity.class.toString());


private transient Map<String,Object> attributes;

private static final long serialVersionUID = 3034412029610092898L;

protected Entity entity;
boolean unsavedChanges = false;
boolean deleted = false;
boolean newEntity = false;

public final boolean projected;
private Set<String> projections;

public CachedEntity(Key key)
{
this(new Entity(key));
Expand Down Expand Up @@ -89,11 +96,14 @@ public CachedEntity(String kind, String keyName, Key parent)
unsavedChanges = true;
}



private CachedEntity(Entity entity) {
this(entity, false);
}

private CachedEntity(Entity entity, boolean projected) {
this.entity = entity;
newEntity = false;
this.projected = projected;
}

public boolean isDeleted()
Expand Down Expand Up @@ -132,6 +142,18 @@ public void refetch(CachedDatastoreService ds)
throw new IllegalStateException("Unable to refetch. Entity "+getKey()+" was deleted.");
}
}

public void setProjections(Collection<String> newProjections) {
if(projected == false || projections != null)
return;

projections = new HashSet<>();
newProjections.forEach(n -> projections.add(n));
}

public Set<String> getProjections(){
return projections;
}

public CachedEntity clone()
{
Expand Down Expand Up @@ -260,10 +282,22 @@ public Map<String, Object> getProperties()

public Object getProperty(String propertyName)
{
if (entity.getProperty(propertyName) instanceof Text)
return ((Text)entity.getProperty(propertyName)).getValue();
else
return entity.getProperty(propertyName);

Object result = null;

if(projected && projections != null && projections.contains(propertyName) == false)
return result;

result = entity.getProperty(propertyName);

if(result instanceof RawValue)
result = ((RawValue) result).getValue();

if(result instanceof Text)
result = ((Text) result).getValue();


return result;
}

public boolean hasProperty(String propertyName)
Expand Down Expand Up @@ -309,11 +343,15 @@ public void setProperty(String propertyName, Object value)
unsavedChanges = true;
}

public static CachedEntity wrap(Entity obj)
{
public static CachedEntity wrap(Entity obj, boolean projected) {
if (obj==null) return null;
return new CachedEntity(obj);
}

public static CachedEntity wrap(Entity obj)
{
return wrap(obj, false);
}

public void setPropertyManually(String propertyName, Object value)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.universeprojects.cacheddatastore;

import java.util.List;
import java.util.Set;

import com.google.appengine.api.datastore.Cursor;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.CompositeFilter;
import com.google.appengine.api.datastore.Query.CompositeFilterOperator;
import com.google.appengine.api.datastore.Query.Filter;
import com.google.appengine.api.datastore.Query.FilterOperator;
Expand Down Expand Up @@ -280,7 +280,40 @@ public List<CachedEntity> getFilteredORList(Cursor cursor, String kind, String f
q.setFilter(filter);

return ds.fetchAsList(q, 1000, cursor);
}
}

public List<CachedEntity> getProjectedList(Set<String> projections, String kind, int limit, String name, FilterOperator operator, Object value){

FilterPredicate f1 = new FilterPredicate(name, operator, value);
Query q = new Query(kind);
q.setFilter(f1);

return ds.fetchProjectedList(limit, q, projections);
}

public List<CachedEntity> getProjectedList(Set<String> projections, String kind, int limit, String name, FilterOperator operator, Object value,
String name2, FilterOperator operator2, Object value2){

FilterPredicate f1 = new FilterPredicate(name, operator, value);
FilterPredicate f2 = new FilterPredicate(name2, operator2, value2);
Query q = new Query(kind);
q.setFilter(CompositeFilterOperator.and(f1, f2));

return ds.fetchProjectedList(limit, q, projections);
}

public List<CachedEntity> getProjectedList(Set<String> projections, String kind, int limit, String name, FilterOperator operator, Object value,
String name2, FilterOperator operator2, Object value2,
String name3, FilterOperator operator3, Object value3){

FilterPredicate f1 = new FilterPredicate(name, operator, value);
FilterPredicate f2 = new FilterPredicate(name2, operator2, value2);
FilterPredicate f3 = new FilterPredicate(name3, operator3, value3);
Query q = new Query(kind);
q.setFilter(CompositeFilterOperator.and(f1, f2, f3));

return ds.fetchProjectedList(limit, q, projections);
}

/**
* This performs an ancestor query to fetch all children (within a limit)
Expand Down