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 */
5159public 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