1 // Copyright 2007 Google Inc. All rights reserved.
3 package com
.google
.appengine
.api
.datastore
;
5 import java
.io
.Serializable
;
6 import java
.util
.HashMap
;
10 * {@code Entity} is the fundamental unit of data storage. It has an
11 * immutable identifier (contained in the {@link Key}) object, a
12 * reference to an optional parent {@code Entity}, a kind (represented
13 * as an arbitrary string), and a set of zero or more typed
17 public final class Entity
extends PropertyContainer
implements Cloneable
{
19 static final long serialVersionUID
= -836647825120453511L;
22 * A reserved property name used to refer to the key of the entity.
23 * This string can be used for filtering and sorting by the entity
26 public static final String KEY_RESERVED_PROPERTY
= "__key__";
29 * A reserved property name used to refer to the scatter property of the
31 * Used for finding split points (e.g. for mapping over a kind).
33 public static final String SCATTER_RESERVED_PROPERTY
= "__scatter__";
36 * A reserved property name used to report an entity group's version.
38 public static final String VERSION_RESERVED_PROPERTY
= "__version__";
40 private final Key key
;
41 final Map
<String
, Object
> propertyMap
;
43 static final class UnindexedValue
implements Serializable
{
44 private final Object value
;
47 * @param value may be null
49 UnindexedValue(Object value
) {
53 public Object
getValue() {
58 public boolean equals(Object that
) {
59 if (that
instanceof UnindexedValue
) {
60 UnindexedValue uv
= (UnindexedValue
) that
;
61 return (value
== null) ? uv
.value
== null : value
.equals(uv
.value
);
67 public int hashCode() {
68 return (value
== null) ?
0 : value
.hashCode();
72 public String
toString() {
73 return value
+ " (unindexed)";
78 * Create a new {@code Entity} with the specified kind and no
79 * parent {@code Entity}. The instantiated {@code Entity} will have an
80 * incomplete {@link Key} when this constructor returns. The
81 * {@link Key} will remain incomplete until you put the {@code Entity},
82 * after which time the {@link Key} will have its {@code id} set.
84 public Entity(String kind
) {
85 this(kind
, (Key
) null);
89 * Create a new {@code Entity} with the specified kind and parent
90 * {@code Entity}. The instantiated {@code Entity} will have an
91 * incomplete {@link Key} when this constructor returns. The
92 * {@link Key} will remain incomplete until you put the {@code Entity},
93 * after which time the {@link Key} will have its {@code id} set.
95 public Entity(String kind
, Key parent
) {
97 this(new Key(kind
, parent
));
101 * Create a new {@code Entity} with the specified kind and key name and no
102 * parent {@code Entity}. The instantiated {@code Entity} will have a
103 * complete {@link Key} when this constructor returns. The
104 * {@link Key Key's} {@code name} field will be set to the value of
107 * <p>This constructor is syntactic sugar for
108 * {@code new Entity(KeyFactory.createKey(kind, keyName))}.
110 public Entity(String kind
, String keyName
) {
111 this(KeyFactory
.createKey(kind
, keyName
));
115 * Create a new {@code Entity} with the specified kind and ID and no
116 * parent {@code Entity}. The instantiated {@code Entity} will have a
117 * complete {@link Key} when this constructor returns. The
118 * {@link Key Key's} {@code id} field will be set to the value of
121 * <p>Creating an entity for the purpose of insertion (as opposed to
122 * update) with this constructor is discouraged unless the id was
123 * obtained from a key returned by a {@link KeyRange} obtained from
124 * {@link AsyncDatastoreService#allocateIds(String, long)} or
125 * {@link DatastoreService#allocateIds(String, long)} for the same
128 * <p>This constructor is syntactic sugar for
129 * {@code new Entity(KeyFactory.createKey(kind, id))}.
131 public Entity(String kind
, long id
) {
132 this(KeyFactory
.createKey(kind
, id
));
136 * Create a new {@code Entity} with the specified kind, key name, and
137 * parent {@code Entity}. The instantiated {@code Entity} will have a
138 * complete {@link Key} when this constructor returns. The
139 * {@link Key Key's} {@code name} field will be set to the value of
142 * <p>This constructor is syntactic sugar for
143 * {@code new Entity(KeyFactory.createKey(parent, kind, keyName))}.
145 public Entity(String kind
, String keyName
, Key parent
) {
146 this(KeyFactory
.createKey(parent
, kind
, keyName
));
150 * Create a new {@code Entity} with the specified kind and ID and
151 * parent {@code Entity}. The instantiated {@code Entity} will have a
152 * complete {@link Key} when this constructor returns. The
153 * {@link Key Key's} {@code id} field will be set to the value of
156 * <p>Creating an entity for the purpose of insertion (as opposed to
157 * update) with this constructor is discouraged unless the id was
158 * obtained from a key returned by a {@link KeyRange} obtained from
159 * {@link AsyncDatastoreService#allocateIds(Key, String, long)} or
160 * {@link DatastoreService#allocateIds(Key, String, long)} for the same
163 * <p>This constructor is syntactic sugar for
164 * {@code new Entity(KeyFactory.createKey(parent, kind, id))}.
166 public Entity(String kind
, long id
, Key parent
) {
167 this(KeyFactory
.createKey(parent
, kind
, id
));
171 * Create a new {@code Entity} uniquely identified by the provided
172 * {@link Key}. Creating an entity for the purpose of insertion (as opposed
173 * to update) with a key that has its {@code id} field set is strongly
174 * discouraged unless the key was returned by a {@link KeyRange}.
178 public Entity(Key key
) {
180 this.propertyMap
= new HashMap
<String
, Object
>();
184 * Two {@code Entity} objects are considered equal if they refer to
185 * the same entity (i.e. their {@code Key} objects match).
188 public boolean equals(Object object
) {
189 if (object
instanceof Entity
) {
190 Entity otherEntity
= (Entity
) object
;
191 return key
.equals(otherEntity
.key
);
197 * Returns the {@code Key} that represents this {@code Entity}. If
198 * the entity has not yet been saved (e.g. via {@code
199 * DatastoreService.put}), this {@code Key} will not be fully
200 * specified and cannot be used for certain operations (like {@code
201 * DatastoreService.get}). Once the {@code Entity} has been saved,
202 * its {@code Key} will be updated to be fully specified.
204 public Key
getKey() {
209 * Returns a logical type that is associated with this {@code
210 * Entity}. This is simply a convenience method that forwards to
211 * the {@code Key} for this {@code Entity}.
213 public String
getKind() {
214 return key
.getKind();
218 * Get a {@code Key} that corresponds to this the parent {@code
219 * Entity} of this {@code Entity}. This is simply a convenience
220 * method that forwards to the {@code Key} for this {@code Entity}.
222 public Key
getParent() {
223 return key
.getParent();
227 public int hashCode() {
228 return key
.hashCode();
232 public String
toString() {
233 StringBuilder builder
= new StringBuilder("<Entity [");
234 builder
.append(key
).append("]:\n");
235 appendPropertiesTo(builder
);
236 builder
.append(">\n");
237 return builder
.toString();
241 * Returns the identifier of the application that owns this {@code
242 * Entity}. This is simply a convenience method that forwards to
243 * the {@code Key} for this {@code Entity}.
245 public String
getAppId() {
246 return key
.getAppId();
250 * Returns the AppIdNamespace of the application/namespace that owns
251 * this {@code Entity}. This is simply a convenience method that forwards to
252 * the {@code Key} for this {@code Entity}.
254 AppIdNamespace
getAppIdNamespace() {
255 return key
.getAppIdNamespace();
259 * Returns the namespace of the application/namespace that owns
260 * this {@code Entity}. This is simply a convenience method that forwards to
261 * the {@code Key} for this {@code Entity}.
263 public String
getNamespace() {
264 return key
.getNamespace();
268 * Returns a shallow copy of this {@code Entity} instance. {@code Collection}
269 * properties are cloned as an {@code ArrayList}, the type returned from the
270 * datastore. Instances of mutable datastore types are cloned as well.
271 * Instances of all other types are reused.
273 * @return a shallow copy of this {@code Entity}
276 public Entity
clone() {
277 Entity entity
= new Entity(key
);
278 entity
.setPropertiesFrom(this);
282 public void setPropertiesFrom(Entity src
) {
283 super.setPropertiesFrom(src
);
287 Map
<String
, Object
> getPropertyMap() {