@@ -0,0 +1,3218 @@
+package com.google.research.bleth.utils;%0A%0Aimport com.google.appengine.api.datastore.DatastoreService;%0Aimport com.google.appengine.api.datastore.DatastoreServiceFactory;%0Aimport com.google.appengine.api.datastore.Entity;%0Aimport com.google.appengine.api.datastore.FetchOptions;%0Aimport com.google.appengine.api.datastore.KeyFactory;%0Aimport com.google.appengine.api.datastore.Query;%0A%0Aimport java.util.ArrayList;%0Aimport java.util.Iterator;%0Aimport java.util.List;%0Aimport java.util.Optional;%0A%0Apublic class Queries %7B%0A    public static List%3CEntity%3E Join(String primaryEntityKind, String secondaryEntityKind,%0A                                    String foreignKey, Optional%3CQuery.Filter%3E primaryEntityFilter) %7B%0A        DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();%0A        List%3CEntity%3E result = new ArrayList%3C%3E();%0A%0A        // Retrieve all primaryEntity ordered by their key, filtered by primaryEntityFilter (if provided).%0A        Query primaryMatchingFilterCondition = new Query(primaryEntityKind);%0A        primaryEntityFilter.ifPresent(primaryMatchingFilterCondition::setFilter);%0A        Iterator%3CString%3E primaryKeyIterator = datastore.prepare(primaryMatchingFilterCondition)%0A                .asList(FetchOptions.Builder.withDefaults())%0A                .stream()%0A                .map(entity -%3E KeyFactory.keyToString(entity.getKey()))%0A                .sorted()%0A                .iterator();%0A%0A        // Retrieve all secondaryEntity ordered by their foreignKey.%0A        Query secondary = new Query(secondaryEntityKind)%0A                .addSort(foreignKey, Query.SortDirection.ASCENDING);%0A        Iterator%3CEntity%3E secondaryEntityIterator = datastore.prepare(secondary).asIterator();%0A%0A        // If one of these queries is empty, return an empty list.%0A        if (!(primaryKeyIterator.hasNext() && secondaryEntityIterator.hasNext())) %7B%0A            return result;%0A        %7D%0A%0A        // Iterate over two queries results and add secondary entities with a matching foreign key.%0A        String primaryKey = primaryKeyIterator.next();%0A        Entity secondaryEntity = secondaryEntityIterator.next();%0A        String secondaryKey = (String) secondaryEntity.getProperty(foreignKey);%0A        while (primaryKeyIterator.hasNext() && secondaryEntityIterator.hasNext()) %7B%0A            if (primaryKey.compareTo(secondaryKey) %3E 0) %7B%0A                // primaryKey %3E secondaryKey%0A                secondaryEntity = secondaryEntityIterator.next();%0A                secondaryKey = (String) secondaryEntity.getProperty(foreignKey);%0A            %7D else if (primaryKey.compareTo(secondaryKey) %3C 0) %7B%0A                // primaryKey %3C secondaryKey%0A                primaryKey = primaryKeyIterator.next();%0A            %7D else %7B%0A                // primaryKey = secondaryKey%0A                result.add(secondaryEntity);%0A                primaryKey = primaryKeyIterator.next();%0A                secondaryEntity = secondaryEntityIterator.next();%0A                secondaryKey = (String) secondaryEntity.getProperty(foreignKey);%0A            %7D%0A        %7D%0A%0A        // Add last entity to result (if matching).%0A        if (primaryKey.compareTo(secondaryKey) == 0) %7B%0A            result.add(secondaryEntity);%0A        %7D%0A%0A        return result;%0A    %7D%0A%7D%0A

add Queries method to provide additional db related operations, and implement a generic join method.