Skip to content

Commit 1dc28cb

Browse files
committed
Refactor Datastore example, add example on embedded entities
1 parent 82023df commit 1dc28cb

File tree

2 files changed

+156
-44
lines changed

2 files changed

+156
-44
lines changed

gcloud-java-examples/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ To run examples from your command line:
8181
mvn exec:java -Dexec.mainClass="com.google.cloud.examples.datastore.DatastoreExample" -Dexec.args="your-project-id my_name add my\ comment"
8282
mvn exec:java -Dexec.mainClass="com.google.cloud.examples.datastore.DatastoreExample" -Dexec.args="your-project-id my_name display"
8383
mvn exec:java -Dexec.mainClass="com.google.cloud.examples.datastore.DatastoreExample" -Dexec.args="your-project-id my_name delete"
84+
mvn exec:java -Dexec.mainClass="com.google.cloud.examples.datastore.DatastoreExample" -Dexec.args="your-project-id my_name set myname@mydomain.com 1234"
8485
```
8586
8687
* Here's an example run of `DnsExample`.

gcloud-java-examples/src/main/java/com/google/cloud/examples/datastore/DatastoreExample.java

Lines changed: 155 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,23 @@
3838
/**
3939
* An example of using Google Cloud Datastore.
4040
*
41-
* <p>This example adds, display or clear comments for a given user.
41+
* <p>This example adds, displays or clears comments for a given user. This example also sets
42+
* contact information for a user.
4243
*
4344
* <p>Steps needed for running the example:<ol>
4445
* <li>login using gcloud SDK - {@code gcloud auth login}.</li>
4546
* <li>compile using maven - {@code mvn compile}</li>
46-
* <li>run using maven - {@code mvn exec:java
47-
* -Dexec.mainClass="com.google.cloud.examples.datastore.DatastoreExample"
48-
* -Dexec.args="[projectId] [user] [delete|display|add comment]"}</li>
47+
* * <li>run using maven -
48+
* <pre>{@code mvn exec:java -Dexec.mainClass="com.google.cloud.examples.datastore.DatastoreExample"
49+
* -Dexec.args="<project_id> <user>
50+
* delete |
51+
* display |
52+
* add <comment> |
53+
* set <email> <phone>}</pre>
54+
* </li>
4955
* </ol>
56+
*
57+
* <p>If no action is provided {@code display} is executed.
5058
*/
5159
public class DatastoreExample {
5260

@@ -56,15 +64,24 @@ public class DatastoreExample {
5664
private static final String DEFAULT_ACTION = "display";
5765
private static final Map<String, DatastoreAction> ACTIONS = new HashMap<>();
5866

59-
private interface DatastoreAction {
60-
void run(Transaction tx, Key userKey, String... args);
67+
private abstract static class DatastoreAction<T> {
68+
69+
abstract void run(Transaction tx, Key userKey, T request) throws Exception;
6170

62-
String getRequiredParams();
71+
abstract T parse(String... args) throws Exception;
72+
73+
protected String params() {
74+
return "";
75+
}
6376
}
6477

65-
private static class DeleteAction implements DatastoreAction {
78+
/**
79+
* This class demonstrates how to delete a user. This action also queries the keys of all comments
80+
* associated with the user and uses them to delete comments.
81+
*/
82+
private static class DeleteAction extends DatastoreAction<Void> {
6683
@Override
67-
public void run(Transaction tx, Key userKey, String... args) {
84+
public void run(Transaction tx, Key userKey, Void request) {
6885
Entity user = tx.get(userKey);
6986
if (user == null) {
7087
System.out.println("Nothing to delete, user does not exist.");
@@ -86,19 +103,29 @@ public void run(Transaction tx, Key userKey, String... args) {
86103
}
87104

88105
@Override
89-
public String getRequiredParams() {
90-
return "";
106+
Void parse(String... args) throws Exception {
107+
return null;
91108
}
92109
}
93110

94-
private static class DisplayAction implements DatastoreAction {
111+
/**
112+
* This class demonstrates how to get a user. The action also queries all comments associated
113+
* with a user.
114+
*/
115+
private static class DisplayAction extends DatastoreAction<Void> {
95116
@Override
96-
public void run(Transaction tx, Key userKey, String... args) {
117+
public void run(Transaction tx, Key userKey, Void request) {
97118
Entity user = tx.get(userKey);
98119
if (user == null) {
99-
System.out.println("No comments for '" + userKey.name() + "'.");
120+
System.out.println("User '" + userKey.name() + "' does not exist.");
100121
return;
101122
}
123+
if (user.contains("contact")) {
124+
FullEntity<IncompleteKey> contact = user.getEntity("contact");
125+
String email = contact.getString("email");
126+
String phone = contact.getString("phone");
127+
System.out.printf("User '%s' email is '%s', phone is '%s'%n", userKey.name(), email, phone);
128+
}
102129
System.out.printf("User '%s' has %d comment[s].%n", userKey.name(), user.getLong("count"));
103130
int limit = 200;
104131
Map<DateTime, String> sortedComments = new TreeMap<>();
@@ -131,25 +158,37 @@ public void run(Transaction tx, Key userKey, String... args) {
131158
}
132159

133160
@Override
134-
public String getRequiredParams() {
135-
return "";
161+
Void parse(String... args) throws Exception {
162+
return null;
136163
}
137164
}
138165

139-
private static class AddAction implements DatastoreAction {
166+
/**
167+
* This class adds a comment for a user. If the user does not exist its entity is created.
168+
*/
169+
private static class AddCommentAction extends DatastoreAction<String> {
140170
@Override
141-
public void run(Transaction tx, Key userKey, String... args) {
171+
public void run(Transaction tx, Key userKey, String content) {
142172
Entity user = tx.get(userKey);
143173
if (user == null) {
144174
System.out.println("Adding a new user.");
145-
user = Entity.builder(userKey)
146-
.set("count", 1L)
147-
.build();
175+
user = Entity.builder(userKey).set("count", 1L).build();
148176
tx.add(user);
149177
} else {
150178
user = Entity.builder(user).set("count", user.getLong("count") + 1L).build();
151179
tx.update(user);
152180
}
181+
IncompleteKey commentKey = IncompleteKey.builder(userKey, COMMENT_KIND).build();
182+
FullEntity<IncompleteKey> comment = FullEntity.builder(commentKey)
183+
.set("content", content)
184+
.set("timestamp", DateTime.now())
185+
.build();
186+
tx.addWithDeferredIdAllocation(comment);
187+
System.out.println("Adding a comment to user '" + userKey.name() + "'.");
188+
}
189+
190+
@Override
191+
String parse(String... args) throws Exception {
153192
String content = "No comment.";
154193
if (args.length > 0) {
155194
StringBuilder stBuilder = new StringBuilder();
@@ -159,28 +198,98 @@ public void run(Transaction tx, Key userKey, String... args) {
159198
stBuilder.setLength(stBuilder.length() - 1);
160199
content = stBuilder.toString();
161200
}
162-
IncompleteKey commentKey = IncompleteKey.builder(userKey, COMMENT_KIND).build();
163-
FullEntity<IncompleteKey> comment = FullEntity.builder(commentKey)
164-
.set("content", content)
165-
.set("timestamp", DateTime.now())
201+
return content;
202+
}
203+
204+
@Override
205+
protected String params() {
206+
return "<comment>";
207+
}
208+
}
209+
210+
/**
211+
* This class sets contact information (email and phone) for a user. If the user does not exist
212+
* its entity is created. Contact information is saved as an entity embedded in the user entity.
213+
*/
214+
private static class SetContactAction extends DatastoreAction<SetContactAction.Contact> {
215+
216+
static final class Contact {
217+
218+
private final String email;
219+
private final String phone;
220+
221+
Contact(String email, String phone) {
222+
this.email = email;
223+
this.phone = phone;
224+
}
225+
226+
String email() {
227+
return email;
228+
}
229+
230+
String phone() {
231+
return phone;
232+
}
233+
}
234+
235+
@Override
236+
public void run(Transaction tx, Key userKey, Contact contact) {
237+
Entity user = tx.get(userKey);
238+
if (user == null) {
239+
System.out.println("Adding a new user.");
240+
user = Entity.builder(userKey).set("count", 0L).build();
241+
tx.add(user);
242+
}
243+
FullEntity<IncompleteKey> contactEntity = FullEntity.builder()
244+
.set("email", contact.email())
245+
.set("phone", contact.phone())
166246
.build();
167-
tx.addWithDeferredIdAllocation(comment);
168-
System.out.println("Adding a comment to user '" + userKey.name() + "'.");
247+
tx.update(Entity.builder(user).set("contact", contactEntity).build());
248+
System.out.println("Setting contact for user '" + userKey.name() + "'.");
169249
}
170250

171251
@Override
172-
public String getRequiredParams() {
173-
return "comment";
252+
Contact parse(String... args) throws Exception {
253+
String message;
254+
if (args.length == 2) {
255+
return new Contact(args[0], args[1]);
256+
} else if (args.length > 2) {
257+
message = "Too many arguments.";
258+
} else {
259+
message = "Missing required email and phone.";
260+
}
261+
throw new IllegalArgumentException(message);
262+
}
263+
264+
@Override
265+
protected String params() {
266+
return "<email> <phone>";
174267
}
175268
}
176269

177270
static {
178271
ACTIONS.put("delete", new DeleteAction());
179-
ACTIONS.put("add", new AddAction());
272+
ACTIONS.put("add", new AddCommentAction());
273+
ACTIONS.put("set", new SetContactAction());
180274
ACTIONS.put("display", new DisplayAction());
181275
}
182276

183-
public static void main(String... args) {
277+
private static void printUsage() {
278+
StringBuilder actionAndParams = new StringBuilder();
279+
for (Map.Entry<String, DatastoreAction> entry : ACTIONS.entrySet()) {
280+
actionAndParams.append("\n\t").append(entry.getKey());
281+
282+
String param = entry.getValue().params();
283+
if (param != null && !param.isEmpty()) {
284+
actionAndParams.append(' ').append(param.replace("\n", "\n\t\t"));
285+
}
286+
}
287+
System.out.printf("Usage: %s <project_id> <user> operation <args>*%s%n",
288+
DatastoreExample.class.getSimpleName(), actionAndParams);
289+
}
290+
291+
@SuppressWarnings("unchecked")
292+
public static void main(String... args) throws Exception {
184293
String projectId = args.length > 0 ? args[0] : null;
185294
// If you want to access a local Datastore running via the Google Cloud SDK, do
186295
// DatastoreOptions options = DatastoreOptions.builder()
@@ -197,24 +306,26 @@ public static void main(String... args) {
197306
String actionName = args.length > 2 ? args[2].toLowerCase() : DEFAULT_ACTION;
198307
DatastoreAction action = ACTIONS.get(actionName);
199308
if (action == null) {
200-
StringBuilder actionAndParams = new StringBuilder();
201-
for (Map.Entry<String, DatastoreAction> entry : ACTIONS.entrySet()) {
202-
actionAndParams.append(entry.getKey());
203-
String param = entry.getValue().getRequiredParams();
204-
if (param != null && !param.isEmpty()) {
205-
actionAndParams.append(' ').append(param);
206-
}
207-
actionAndParams.append('|');
208-
}
209-
actionAndParams.setLength(actionAndParams.length() - 1);
210-
System.out.printf("Usage: %s [projectId] [user] [%s]%n",
211-
DatastoreExample.class.getSimpleName(), actionAndParams);
309+
System.out.println("Unrecognized action.");
310+
printUsage();
212311
return;
213312
}
214313
args = args.length > 3 ? Arrays.copyOfRange(args, 3, args.length) : new String []{};
215314
Transaction tx = datastore.newTransaction();
315+
Object request;
316+
try {
317+
request = action.parse(args);
318+
} catch (IllegalArgumentException ex) {
319+
System.out.println("Invalid input for action '" + actionName + "'. " + ex.getMessage());
320+
System.out.println("Expected: " + action.params());
321+
return;
322+
} catch (Exception ex) {
323+
System.out.println("Failed to parse request.");
324+
ex.printStackTrace();
325+
return;
326+
}
216327
try {
217-
action.run(tx, key, args);
328+
action.run(tx, key, request);
218329
tx.commit();
219330
} finally {
220331
if (tx.active()) {

0 commit comments

Comments
 (0)