package org.commcare.adapters; import android.app.Activity; import org.commcare.cases.entity.Entity; import org.commcare.cases.entity.NodeEntityFactory; import org.javarosa.core.model.instance.TreeReference; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; /** * Filter (and order) entities by those whose 'extra key', most likely case id, * is present in the provided ordered key set * * @author Phillip Mates (pmates@dimagi.com). */ public class EntityKeyFilterer extends EntityFiltererBase { private final LinkedHashSet<String> orderedKeySet; /** * @param orderedKeySet Keys that are used to filter and order the Entity * list based on the entity's 'extra key' field */ public EntityKeyFilterer(EntityListAdapter adapter, NodeEntityFactory nodeFactory, List<Entity<TreeReference>> fullEntityList, Activity context, LinkedHashSet<String> orderedKeySet) { super(context, nodeFactory, adapter, fullEntityList); this.orderedKeySet = orderedKeySet; } @Override protected void filter() { if (isCancelled() || orderedKeySet.isEmpty()) { return; } // Add entities whose extra keys are in the key set, preserving key set // ordering. Don't assume one-to-one correspondence between entities // and keys: depending on the appliciation we might want to attach the // same data to multiple entities HashMap<String, List<Entity<TreeReference>>> keyToEntitiesMap = buildKeyToEntitiesMap(fullEntityList); for (String key : orderedKeySet) { if (keyToEntitiesMap.containsKey(key)) { matchList.addAll(keyToEntitiesMap.get(key)); } } } /** * Group entities by their 'extra key' field * * @return A map from 'extra key' values to a list of entities that have * that 'extra key' */ private static HashMap<String, List<Entity<TreeReference>>> buildKeyToEntitiesMap(List<Entity<TreeReference>> entityList) { // NOTE PLM: potentially expensive in presence of large entity set; // could build at entity load time or forgoe ordering or constrain the // key to entity mapping to be one-to-one HashMap<String, List<Entity<TreeReference>>> keyToEntitiesMap = new HashMap<>(); for (Entity<TreeReference> entity : entityList) { if (keyToEntitiesMap.containsKey(entity.extraKey)) { keyToEntitiesMap.get(entity.extraKey).add(entity); } else { ArrayList<Entity<TreeReference>> list = new ArrayList<>(); list.add(entity); keyToEntitiesMap.put(entity.extraKey, list); } } return keyToEntitiesMap; } }