Revision created by MOE tool push_codebase.
[gae.git] / java / src / main / com / google / appengine / api / labs / datastore / overlay / OverlayUtils.java
blob5e47fe696f9bfa56734c50d249cc7ae3dce61de6
1 package com.google.appengine.api.labs.datastore.overlay;
3 import static com.google.common.base.Preconditions.checkArgument;
4 import static com.google.common.base.Preconditions.checkNotNull;
5 import static com.google.common.base.Preconditions.checkState;
7 import com.google.appengine.api.datastore.Entity;
8 import com.google.appengine.api.datastore.Key;
9 import com.google.appengine.api.datastore.KeyFactory;
10 import com.google.common.collect.ImmutableList;
11 import com.google.common.collect.Maps;
13 import java.util.Iterator;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Objects;
18 /**
19 * A collection of utility methods and constants for overlay Datastores.
21 final class OverlayUtils {
23 private static final String TOMBSTONE_UUID = "EB4BD565-1C12-494B-9A6D-182BA54D0B3F";
25 /**
26 * Do not instantiate this class.
28 private OverlayUtils() {}
30 /**
31 * Determines whether an entity is a tombstone.
33 static boolean isTombstone(Entity entity) {
34 return TOMBSTONE_UUID.equals(entity.getKind());
37 /**
38 * Given a {@code tombstoneKey}, returns the key where the associated real entity would be stored,
39 * if it exists.
41 static Key getKeyFromTombstoneKey(Key tombstoneKey) {
42 checkNotNull(tombstoneKey);
43 return tombstoneKey.getParent();
46 /**
47 * Creates a tombstone entity corresponding to {@code key}.
49 * @param key the key
50 * @return a tombstone entity for that key
52 static Entity getTombstoneForKey(Key key) {
53 checkNotNull(key);
54 return new Entity(getTombstoneKey(key));
57 /**
58 * Returns the tombstone key corresponding to {@code key}.
60 static Key getTombstoneKey(Key key) {
61 checkNotNull(key);
62 return key.getChild(TOMBSTONE_UUID, TOMBSTONE_UUID);
65 /**
66 * Returns the tombstone keys corresponding to {@code keys}.
68 static List<Key> getTombstoneKeys(Iterable<Key> keys) {
69 checkNotNull(keys);
70 ImmutableList.Builder<Key> newKeys = ImmutableList.<Key>builder();
71 for (Key key : keys) {
72 newKeys.add(getTombstoneKey(key));
74 return newKeys.build();
77 /**
78 * Returns a list containing both the elements of {@code keys}, and the tombstone keys
79 * corresponding to the elements of {@code keys}.
81 static List<Key> getKeysAndTombstoneKeys(Iterable<Key> keys) {
82 checkNotNull(keys);
83 ImmutableList.Builder<Key> newKeys = ImmutableList.<Key>builder();
84 for (Key key : keys) {
85 newKeys.add(key);
86 newKeys.add(getTombstoneKey(key));
88 return newKeys.build();
91 /**
92 * Returns a list containing the tombstone keys corresponding to the keys of {@code entities}.
94 static List<Key> getTombstoneKeysForEntities(Iterable<Entity> entities) {
95 checkNotNull(entities);
96 ImmutableList.Builder<Key> newKeys = ImmutableList.<Key>builder();
97 for (Entity entity : entities) {
98 Key key = entity.getKey();
99 newKeys.add(getTombstoneKey(key));
101 return newKeys.build();
105 * Returns a list containing both the keys of the elements of {@code entities}, and the tombstone
106 * keys corresponding to those keys.
108 static List<Key> getKeysAndTombstoneKeysForEntities(Iterable<Entity> entities) {
109 checkNotNull(entities);
110 ImmutableList.Builder<Key> newKeys = ImmutableList.<Key>builder();
111 for (Entity entity : entities) {
112 Key key = entity.getKey();
113 newKeys.add(key);
114 newKeys.add(getTombstoneKey(key));
116 return newKeys.build();
120 * Creates a list of tombstone entities corresponding to {@code keys}.
122 static List<Entity> getTombstonesForKeys(Iterable<Key> keys) {
123 checkNotNull(keys);
124 ImmutableList.Builder<Entity> tombstones = ImmutableList.<Entity>builder();
125 for (Key key : keys) {
126 tombstones.add(getTombstoneForKey(key));
128 return tombstones.build();
132 * Returns an entity that is the same as {code @entity}, but where the key is replaced by
133 * {@code newKey}. This method should only be called if {@code entity} has an incomplete key, and
134 * if {@code newKey} has the same kind and parent as {@code entity}.
136 static Entity completeKey(Entity entity, Key newKey) {
137 checkNotNull(entity);
138 checkNotNull(newKey);
139 checkArgument(!entity.getKey().isComplete());
140 checkArgument(Objects.equals(entity.getParent(), newKey.getParent()));
141 checkArgument(Objects.equals(entity.getKind(), newKey.getKind()));
142 Entity newEntity = new Entity(newKey);
143 newEntity.setPropertiesFrom(entity);
144 return newEntity;
148 * Returns a map that indicates how many IDs need to be allocated for each parent-kind combination
149 * represented in {@code entities}.
151 static Map<IncompleteKey, Integer> getIdsNeededMap(Iterable<Entity> entities) {
152 Map<IncompleteKey, Integer> idsNeededMap = Maps.newHashMap();
153 for (Entity entity : entities) {
154 if (!entity.getKey().isComplete()) {
155 IncompleteKey incompleteKey = new IncompleteKey(entity);
156 Integer countInteger = idsNeededMap.get(incompleteKey);
157 if (countInteger != null) {
158 idsNeededMap.put(incompleteKey, countInteger + 1);
159 } else {
160 idsNeededMap.put(incompleteKey, 1);
164 return idsNeededMap;
168 * Returns the subset of the input entities that already have complete keys.
170 static List<Entity> getEntitiesWithPreexistingCompleteKeys(Iterable<Entity> entities) {
171 ImmutableList.Builder<Entity> entitiesWithCompleteKeys = ImmutableList.<Entity>builder();
172 for (Entity entity : entities) {
173 if (entity.getKey().isComplete()) {
174 entitiesWithCompleteKeys.add(entity);
177 return entitiesWithCompleteKeys.build();
181 * Assigns IDs from {@code idsAllocatedMap} to incomplete keys in {@code entities}, after
182 * translating them from the default ID range into the overlay ID range.
184 static List<Entity> translateAndCompleteEntityKeys(Iterable<Entity> entities, Map<IncompleteKey,
185 Iterator<Key>> idsAllocatedMap) {
186 ImmutableList.Builder<Entity> entitiesWithCompleteKeys = ImmutableList.<Entity>builder();
187 for (Entity entity : entities) {
188 Entity newEntity = entity;
189 if (!entity.getKey().isComplete()) {
190 IncompleteKey incompleteKey = new IncompleteKey(entity);
191 Iterator<Key> keyIterator = idsAllocatedMap.get(incompleteKey);
192 Key k = keyIterator.next();
193 Key newKey = KeyFactory.createKey(k.getParent(), k.getKind(),
194 IdAllocationPolicy.overlayIdFromDefaultId(k.getId()));
195 newEntity = OverlayUtils.completeKey(entity, newKey);
197 entitiesWithCompleteKeys.add(newEntity);
199 for (Iterator<Key> iterator : idsAllocatedMap.values()) {
200 checkState(!iterator.hasNext());
202 return entitiesWithCompleteKeys.build();