From 1dc28cbf059fb5a9c6b015a1acca9b63b03a462d Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 4 May 2016 17:00:17 +0200 Subject: [PATCH] Refactor Datastore example, add example on embedded entities --- gcloud-java-examples/README.md | 1 + .../examples/datastore/DatastoreExample.java | 199 ++++++++++++++---- 2 files changed, 156 insertions(+), 44 deletions(-) diff --git a/gcloud-java-examples/README.md b/gcloud-java-examples/README.md index 98af1df5f3f2..84cb6d581d8a 100644 --- a/gcloud-java-examples/README.md +++ b/gcloud-java-examples/README.md @@ -81,6 +81,7 @@ To run examples from your command line: mvn exec:java -Dexec.mainClass="com.google.cloud.examples.datastore.DatastoreExample" -Dexec.args="your-project-id my_name add my\ comment" mvn exec:java -Dexec.mainClass="com.google.cloud.examples.datastore.DatastoreExample" -Dexec.args="your-project-id my_name display" mvn exec:java -Dexec.mainClass="com.google.cloud.examples.datastore.DatastoreExample" -Dexec.args="your-project-id my_name delete" + mvn exec:java -Dexec.mainClass="com.google.cloud.examples.datastore.DatastoreExample" -Dexec.args="your-project-id my_name set myname@mydomain.com 1234" ``` * Here's an example run of `DnsExample`. diff --git a/gcloud-java-examples/src/main/java/com/google/cloud/examples/datastore/DatastoreExample.java b/gcloud-java-examples/src/main/java/com/google/cloud/examples/datastore/DatastoreExample.java index cf0fee504bf8..9ad90ec626c0 100644 --- a/gcloud-java-examples/src/main/java/com/google/cloud/examples/datastore/DatastoreExample.java +++ b/gcloud-java-examples/src/main/java/com/google/cloud/examples/datastore/DatastoreExample.java @@ -38,15 +38,23 @@ /** * An example of using Google Cloud Datastore. * - *

This example adds, display or clear comments for a given user. + *

This example adds, displays or clears comments for a given user. This example also sets + * contact information for a user. * *

Steps needed for running the example:

    *
  1. login using gcloud SDK - {@code gcloud auth login}.
  2. *
  3. compile using maven - {@code mvn compile}
  4. - *
  5. run using maven - {@code mvn exec:java - * -Dexec.mainClass="com.google.cloud.examples.datastore.DatastoreExample" - * -Dexec.args="[projectId] [user] [delete|display|add comment]"}
  6. + * *
  7. run using maven - + *
    {@code mvn exec:java -Dexec.mainClass="com.google.cloud.examples.datastore.DatastoreExample"
    + *  -Dexec.args=" 
    + *  delete |
    + *  display |
    + *  add  |
    + *  set  }
    + *
  8. *
+ * + *

If no action is provided {@code display} is executed. */ public class DatastoreExample { @@ -56,15 +64,24 @@ public class DatastoreExample { private static final String DEFAULT_ACTION = "display"; private static final Map ACTIONS = new HashMap<>(); - private interface DatastoreAction { - void run(Transaction tx, Key userKey, String... args); + private abstract static class DatastoreAction { + + abstract void run(Transaction tx, Key userKey, T request) throws Exception; - String getRequiredParams(); + abstract T parse(String... args) throws Exception; + + protected String params() { + return ""; + } } - private static class DeleteAction implements DatastoreAction { + /** + * This class demonstrates how to delete a user. This action also queries the keys of all comments + * associated with the user and uses them to delete comments. + */ + private static class DeleteAction extends DatastoreAction { @Override - public void run(Transaction tx, Key userKey, String... args) { + public void run(Transaction tx, Key userKey, Void request) { Entity user = tx.get(userKey); if (user == null) { System.out.println("Nothing to delete, user does not exist."); @@ -86,19 +103,29 @@ public void run(Transaction tx, Key userKey, String... args) { } @Override - public String getRequiredParams() { - return ""; + Void parse(String... args) throws Exception { + return null; } } - private static class DisplayAction implements DatastoreAction { + /** + * This class demonstrates how to get a user. The action also queries all comments associated + * with a user. + */ + private static class DisplayAction extends DatastoreAction { @Override - public void run(Transaction tx, Key userKey, String... args) { + public void run(Transaction tx, Key userKey, Void request) { Entity user = tx.get(userKey); if (user == null) { - System.out.println("No comments for '" + userKey.name() + "'."); + System.out.println("User '" + userKey.name() + "' does not exist."); return; } + if (user.contains("contact")) { + FullEntity contact = user.getEntity("contact"); + String email = contact.getString("email"); + String phone = contact.getString("phone"); + System.out.printf("User '%s' email is '%s', phone is '%s'%n", userKey.name(), email, phone); + } System.out.printf("User '%s' has %d comment[s].%n", userKey.name(), user.getLong("count")); int limit = 200; Map sortedComments = new TreeMap<>(); @@ -131,25 +158,37 @@ public void run(Transaction tx, Key userKey, String... args) { } @Override - public String getRequiredParams() { - return ""; + Void parse(String... args) throws Exception { + return null; } } - private static class AddAction implements DatastoreAction { + /** + * This class adds a comment for a user. If the user does not exist its entity is created. + */ + private static class AddCommentAction extends DatastoreAction { @Override - public void run(Transaction tx, Key userKey, String... args) { + public void run(Transaction tx, Key userKey, String content) { Entity user = tx.get(userKey); if (user == null) { System.out.println("Adding a new user."); - user = Entity.builder(userKey) - .set("count", 1L) - .build(); + user = Entity.builder(userKey).set("count", 1L).build(); tx.add(user); } else { user = Entity.builder(user).set("count", user.getLong("count") + 1L).build(); tx.update(user); } + IncompleteKey commentKey = IncompleteKey.builder(userKey, COMMENT_KIND).build(); + FullEntity comment = FullEntity.builder(commentKey) + .set("content", content) + .set("timestamp", DateTime.now()) + .build(); + tx.addWithDeferredIdAllocation(comment); + System.out.println("Adding a comment to user '" + userKey.name() + "'."); + } + + @Override + String parse(String... args) throws Exception { String content = "No comment."; if (args.length > 0) { StringBuilder stBuilder = new StringBuilder(); @@ -159,28 +198,98 @@ public void run(Transaction tx, Key userKey, String... args) { stBuilder.setLength(stBuilder.length() - 1); content = stBuilder.toString(); } - IncompleteKey commentKey = IncompleteKey.builder(userKey, COMMENT_KIND).build(); - FullEntity comment = FullEntity.builder(commentKey) - .set("content", content) - .set("timestamp", DateTime.now()) + return content; + } + + @Override + protected String params() { + return ""; + } + } + + /** + * This class sets contact information (email and phone) for a user. If the user does not exist + * its entity is created. Contact information is saved as an entity embedded in the user entity. + */ + private static class SetContactAction extends DatastoreAction { + + static final class Contact { + + private final String email; + private final String phone; + + Contact(String email, String phone) { + this.email = email; + this.phone = phone; + } + + String email() { + return email; + } + + String phone() { + return phone; + } + } + + @Override + public void run(Transaction tx, Key userKey, Contact contact) { + Entity user = tx.get(userKey); + if (user == null) { + System.out.println("Adding a new user."); + user = Entity.builder(userKey).set("count", 0L).build(); + tx.add(user); + } + FullEntity contactEntity = FullEntity.builder() + .set("email", contact.email()) + .set("phone", contact.phone()) .build(); - tx.addWithDeferredIdAllocation(comment); - System.out.println("Adding a comment to user '" + userKey.name() + "'."); + tx.update(Entity.builder(user).set("contact", contactEntity).build()); + System.out.println("Setting contact for user '" + userKey.name() + "'."); } @Override - public String getRequiredParams() { - return "comment"; + Contact parse(String... args) throws Exception { + String message; + if (args.length == 2) { + return new Contact(args[0], args[1]); + } else if (args.length > 2) { + message = "Too many arguments."; + } else { + message = "Missing required email and phone."; + } + throw new IllegalArgumentException(message); + } + + @Override + protected String params() { + return " "; } } static { ACTIONS.put("delete", new DeleteAction()); - ACTIONS.put("add", new AddAction()); + ACTIONS.put("add", new AddCommentAction()); + ACTIONS.put("set", new SetContactAction()); ACTIONS.put("display", new DisplayAction()); } - public static void main(String... args) { + private static void printUsage() { + StringBuilder actionAndParams = new StringBuilder(); + for (Map.Entry entry : ACTIONS.entrySet()) { + actionAndParams.append("\n\t").append(entry.getKey()); + + String param = entry.getValue().params(); + if (param != null && !param.isEmpty()) { + actionAndParams.append(' ').append(param.replace("\n", "\n\t\t")); + } + } + System.out.printf("Usage: %s operation *%s%n", + DatastoreExample.class.getSimpleName(), actionAndParams); + } + + @SuppressWarnings("unchecked") + public static void main(String... args) throws Exception { String projectId = args.length > 0 ? args[0] : null; // If you want to access a local Datastore running via the Google Cloud SDK, do // DatastoreOptions options = DatastoreOptions.builder() @@ -197,24 +306,26 @@ public static void main(String... args) { String actionName = args.length > 2 ? args[2].toLowerCase() : DEFAULT_ACTION; DatastoreAction action = ACTIONS.get(actionName); if (action == null) { - StringBuilder actionAndParams = new StringBuilder(); - for (Map.Entry entry : ACTIONS.entrySet()) { - actionAndParams.append(entry.getKey()); - String param = entry.getValue().getRequiredParams(); - if (param != null && !param.isEmpty()) { - actionAndParams.append(' ').append(param); - } - actionAndParams.append('|'); - } - actionAndParams.setLength(actionAndParams.length() - 1); - System.out.printf("Usage: %s [projectId] [user] [%s]%n", - DatastoreExample.class.getSimpleName(), actionAndParams); + System.out.println("Unrecognized action."); + printUsage(); return; } args = args.length > 3 ? Arrays.copyOfRange(args, 3, args.length) : new String []{}; Transaction tx = datastore.newTransaction(); + Object request; + try { + request = action.parse(args); + } catch (IllegalArgumentException ex) { + System.out.println("Invalid input for action '" + actionName + "'. " + ex.getMessage()); + System.out.println("Expected: " + action.params()); + return; + } catch (Exception ex) { + System.out.println("Failed to parse request."); + ex.printStackTrace(); + return; + } try { - action.run(tx, key, args); + action.run(tx, key, request); tx.commit(); } finally { if (tx.active()) {