package org.akvo.gae.remoteapi;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Query;
public class PathToIdMigration implements Process {
private static final String SURVEY_GROUP = "SurveyGroup";
private static final String SURVEY = "Survey";
private static final String USER_AUTHORIZATION = "UserAuthorization";
@Override
public void execute(DatastoreService ds, String[] args) throws Exception {
final List<Entity> surveyGroups = ds.prepare(new Query(SURVEY_GROUP))
.asList(FetchOptions.Builder.withDefaults());
final List<Entity> surveys = ds.prepare(new Query(SURVEY)).asList(
FetchOptions.Builder.withDefaults());
final List<Entity> userAuthorizations = ds.prepare(
new Query(USER_AUTHORIZATION)).asList(
FetchOptions.Builder.withDefaults());
Map<Long, Long> idToParentId = new HashMap<>();
Map<String, Long> pathToId = new HashMap<>();
for (Entity entity : surveyGroups) {
// Ensure root folder parentId == 0
Long entityId = entity.getKey().getId();
if (entity.getProperty("parentId") == null) {
entity.setProperty("parentId", 0L);
}
idToParentId.put(entityId, (Long) entity.getProperty("parentId"));
String path = (String) entity.getProperty("path");
if (path != null) {
pathToId.put(path, entityId);
} else {
System.out.printf("Path for survey group #%s is not set\n",
entityId);
}
}
for (Entity entity : surveys) {
Long entityId = entity.getKey().getId();
Long surveyGroupId = (Long) entity.getProperty("surveyGroupId");
if (surveyGroupId != null) {
idToParentId.put(entityId, surveyGroupId);
} else {
System.out.printf("Survey #%s does not have a surveyGroupId\n",
entityId);
}
}
List<Entity> surveysAndSurveyGroups = new ArrayList<>();
surveysAndSurveyGroups.addAll(surveyGroups);
surveysAndSurveyGroups.addAll(surveys);
for (Entity entity : surveysAndSurveyGroups) {
List<Long> aIds = new ArrayList<>();
Long entityId = entity.getKey().getId();
ancestorIds(idToParentId, aIds, entityId);
if (aIds.isEmpty() || aIds.get(0) != 0) {
System.out
.printf("Could not generate ancestorIds for Survey or Survey group #%s\n",
entityId);
} else {
entity.setProperty("ancestorIds", aIds);
}
}
// Update user authorizations
pathToId.put("/", 0L);
for (Entity entity : userAuthorizations) {
String objectPath = (String) entity.getProperty("objectPath");
if (objectPath != null) {
Long derivedSecuredObjectId = pathToId.get(objectPath);
if (derivedSecuredObjectId != null) {
entity.setProperty("securedObjectId",
derivedSecuredObjectId);
} else {
System.out.printf(
"Could not derive securedObjectId from path %s\n",
objectPath);
}
}
}
ds.put(surveysAndSurveyGroups);
ds.put(userAuthorizations);
}
private static void ancestorIds(final Map<Long, Long> idToParentId,
List<Long> aIds, final Long id) {
Long parentId = idToParentId.get(id);
if (parentId == null) {
return;
}
aIds.add(parentId);
if (parentId == 0) {
Collections.reverse(aIds);
return;
} else {
ancestorIds(idToParentId, aIds, parentId);
}
}
}