package com.leanengine.server.appengine;
import com.google.appengine.api.datastore.*;
import com.leanengine.server.LeanException;
import com.leanengine.server.auth.AuthService;
import com.leanengine.server.auth.LeanAccount;
import com.leanengine.server.entity.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import java.util.regex.Pattern;
public class DatastoreUtils {
private static final Logger log = Logger.getLogger(DatastoreUtils.class.getName());
private static DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
private static Pattern pattern = Pattern.compile("^[A-Za-z][A-Za-z_0-9]*");
public static Entity getPrivateEntity(String kind, long entityId) throws LeanException {
LeanAccount account = findCurrentAccount();
if (entityId <= 0 || kind == null) throw new LeanException(LeanException.Error.EntityNotFound,
" Entity 'kind' and 'id' must NOT be null.");
Entity entity;
try {
entity = datastore.get(KeyFactory.createKey(kind, entityId));
} catch (EntityNotFoundException e) {
throw new LeanException(LeanException.Error.EntityNotFound);
}
if (account.id != (Long) entity.getProperty("_account"))
throw new LeanException(LeanException.Error.NotAuthorized,
" Account not authorized to access entity '" + kind + "'with ID '" + entityId + "'");
return entity;
}
public static void deletePrivateEntity(String entityKind, long entityId) throws LeanException {
LeanAccount account = findCurrentAccount();
if (entityId <= 0 || entityKind == null) throw new LeanException(LeanException.Error.EntityNotFound,
" Entity 'kind' and 'id' must NOT be null.");
Entity entity;
try {
entity = datastore.get(KeyFactory.createKey(entityKind, entityId));
} catch (EntityNotFoundException e) {
throw new LeanException(LeanException.Error.EntityNotFound);
}
if (account.id != (Long) entity.getProperty("_account"))
throw new LeanException(LeanException.Error.NotAuthorized,
" Account not authorized to access entity '" + entityKind + "'with ID '" + entityId + "'");
datastore.delete(entity.getKey());
}
private static LeanAccount findCurrentAccount() throws LeanException {
LeanAccount account = AuthService.getCurrentAccount();
// this should not happen, but we check anyway
if (account == null) throw new LeanException(LeanException.Error.NotAuthorized);
return account;
}
public static List<Entity> getPrivateEntities() throws LeanException {
findCurrentAccount();
List<String> kindNames = findAllEntityKinds();
List<Entity> result = new ArrayList<Entity>();
for (String kindName : kindNames) {
result.addAll(getPrivateEntities(kindName));
}
return result;
}
public static List<Entity> getPrivateEntities(String kind) throws LeanException {
if (!pattern.matcher(kind).matches()) {
throw new LeanException(LeanException.Error.IllegalEntityName);
}
LeanAccount account = AuthService.getCurrentAccount();
// this should not happen, but we check anyway
if (account == null) throw new LeanException(LeanException.Error.NotAuthorized);
Query query = new Query(kind);
query.addFilter("_account", Query.FilterOperator.EQUAL, account.id);
PreparedQuery pq = datastore.prepare(query);
return pq.asList(FetchOptions.Builder.withDefaults());
}
public static long putPrivateEntity(String entityName, Map<String, Object> properties) throws LeanException {
if (!pattern.matcher(entityName).matches()) {
throw new LeanException(LeanException.Error.IllegalEntityName);
}
Entity entityEntity = new Entity(entityName);
entityEntity.setProperty("_account", AuthService.getCurrentAccount().id);
if (properties != null) {
for (Map.Entry<String, Object> entry : properties.entrySet()) {
entityEntity.setProperty(entry.getKey(), entry.getValue());
}
}
Key result = datastore.put(entityEntity);
return result.getId();
}
public static QueryResult queryEntityPrivate(LeanQuery leanQuery) throws LeanException {
LeanAccount account = findCurrentAccount();
Query query = new Query(leanQuery.getKind());
query.addFilter("_account", Query.FilterOperator.EQUAL, account.id);
for (QueryFilter queryFilter : leanQuery.getFilters()) {
query.addFilter(
queryFilter.getProperty(),
queryFilter.getOperator().getFilterOperator(),
queryFilter.getValue());
}
for (QuerySort querySort : leanQuery.getSorts()) {
query.addSort(querySort.getProperty(), querySort.getDirection().getSortDirection());
}
FetchOptions fetchOptions = FetchOptions.Builder.withDefaults();
if(leanQuery.getCursor() != null )
fetchOptions.startCursor(leanQuery.getCursor());
if(leanQuery.getOffset() != null)
fetchOptions.offset(leanQuery.getOffset());
if(leanQuery.getLimit() != null)
fetchOptions.limit(leanQuery.getLimit());
try {
PreparedQuery pq = datastore.prepare(query);
QueryResultList<Entity> result;
result = pq.asQueryResultList(fetchOptions);
return new QueryResult(result, result.getCursor());
} catch (DatastoreNeedIndexException dnie) {
throw new LeanException(LeanException.Error.AppEngineMissingIndex);
}
}
public static List<String> findAllEntityKinds() throws LeanException {
Query q = new Query(Query.KIND_METADATA_KIND);
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
PreparedQuery pq = datastore.prepare(q);
List<Entity> list = pq.asList(FetchOptions.Builder.withDefaults());
List<String> result = new ArrayList<String>();
for (Entity entity : list) {
if (!entity.getKey().getName().startsWith("_"))
result.add(entity.getKey().getName());
}
return result;
}
}