]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/gss-lib-2.2/src/com/pras/SpreadSheetFactory.java
Add Spanish translation
[Dictionary.git] / jars / gss-lib-2.2 / src / com / pras / SpreadSheetFactory.java
1 /*\r
2  * Copyright (C) 2010 Prasanta Paul, http://prasanta-paul.blogspot.com\r
3  *\r
4  * Licensed under the Apache License, Version 2.0 (the "License");\r
5  * you may not use this file except in compliance with the License.\r
6  * You may obtain a copy of the License at\r
7  *\r
8  *      http://www.apache.org/licenses/LICENSE-2.0\r
9  *\r
10  * Unless required by applicable law or agreed to in writing, software\r
11  * distributed under the License is distributed on an "AS IS" BASIS,\r
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  * See the License for the specific language governing permissions and\r
14  * limitations under the License.\r
15  */\r
16 \r
17 package com.pras;\r
18 \r
19 import java.util.ArrayList;\r
20 import java.util.HashMap;\r
21 \r
22 import com.pras.auth.Account;\r
23 import com.pras.auth.Authenticator;\r
24 import com.pras.auth.BasicAuthenticatorImpl;\r
25 import com.pras.conn.HttpConHandler;\r
26 import com.pras.conn.Response;\r
27 import com.pras.sp.Entry;\r
28 import com.pras.sp.Feed;\r
29 import com.pras.sp.ParseFeed;\r
30 \r
31 /**\r
32  * <p>\r
33  * It is a SpreadSheet Generator Class. It accepts Gmail User ID and PassWord\r
34  * to generate Authentication Token.\r
35  * <br/>\r
36  * It uses 2 Google APIs-\r
37  * <br/>\r
38  * SpreadSheet Create/Delete - <a href="http://code.google.com/apis/documents/docs/3.0/developers_guide_protocol.html">Google Document API</a>\r
39  * <br/>\r
40  * WorkSheet Create/Delete, Record Add - <a href="http://code.google.com/apis/spreadsheets/data/3.0/developers_guide.html">Google SpreadSheet API</a>\r
41  *\r
42  * @author Prasanta Paul\r
43  *\r
44  */\r
45 public class SpreadSheetFactory {\r
46 \r
47         private String TAG = "SpreadSheetFactory";\r
48         \r
49 //      private String userName;\r
50 //      private String password;\r
51         public static String authToken;\r
52         // URL\r
53         //private final String GOOGLE_CLIENT_LOGIN_URL = "https://www.google.com/accounts/ClientLogin";\r
54         \r
55         private final String SP_GET_LIST_URL = "https://spreadsheets.google.com/feeds/spreadsheets/private/full";\r
56         private final String DOCUMENT_LIST_API_URL = "https://docs.google.com/feeds/default/private/full";\r
57         // Service Name\r
58         /*\r
59          * Google service name (Reference)-\r
60          * http://code.google.com/apis/gdata/faq.html\r
61          */\r
62         final static String SPREADSHEET_API_SERVICE_NAME = "wise";\r
63         final static String DOCUMENT_LIST_API_SERVICE_NAME = "writely";\r
64         \r
65         /**\r
66          * List of presently stored SpreadSheets\r
67          */\r
68         private ArrayList<SpreadSheet> spreadSheets = new ArrayList<SpreadSheet>();\r
69         \r
70         private Authenticator authenticator = null;\r
71         \r
72         private static SpreadSheetFactory factory;\r
73         \r
74         /**\r
75          * This will return an existing SpreadSheetFactory instance or null\r
76          * </br>\r
77          * <b>Note:</b>\r
78          * Make sure you have previously called getInstance(String userName, String password)\r
79          * \r
80          * @return\r
81          */\r
82         public static SpreadSheetFactory getInstance(){\r
83                 return getInstance(null, null);\r
84         }\r
85         \r
86         /**\r
87          * This will create SpreadSheetFactory Instance with valid User ID (e.g. abc@gmail.com) and password\r
88          * \r
89          * @param userName Gmail account id e.g. abc@gmail.com\r
90          * @param password Gmail account password\r
91          * @return\r
92          */\r
93         public static SpreadSheetFactory getInstance(String email, String password){\r
94                 if(factory == null){\r
95                         if(email != null && password != null){\r
96                                 Account account = new Account();\r
97                                 account.setEmail(email);\r
98                                 account.setPassword(password);\r
99                                 BasicAuthenticatorImpl basicAuth = new BasicAuthenticatorImpl(account);\r
100                                 \r
101                                 factory = new SpreadSheetFactory(basicAuth);\r
102                                 \r
103                         }else{\r
104                                 throw new IllegalAccessError("Missing Account Info. Please use getInstance(String email, String password) or getInstance(Authenticator authenticator)");\r
105                         }\r
106                 }\r
107                 return factory;\r
108         }\r
109         \r
110         /**\r
111          * This will create SpreadSheetFactory Instance using your custom Authenticatior.\r
112          * \r
113          * Use this if you want to use your custom Authenticator e.g. in Android you can use AccountManager\r
114          * to create a custom Authenticator.\r
115          * \r
116          * @param authenticator Your Custom Authenticator. \r
117          * @return\r
118          */\r
119         public static SpreadSheetFactory getInstance(Authenticator authenticator){\r
120                 if(authenticator == null){\r
121                         throw new IllegalAccessError("No Authenticator defined");\r
122                 }\r
123                 if(factory == null)\r
124                         factory = new SpreadSheetFactory(authenticator);\r
125                 return factory;\r
126         }\r
127         \r
128         /**\r
129          * Provide Gmail user id and password. Use SpreadSheetFactory instance\r
130          * to generate create/list/delete SpreadSheet\r
131          * \r
132          * @param userName\r
133          * @param password\r
134          */\r
135 //      private SpreadSheetFactory(String userName, String password){\r
136 //              this.userName = userName;\r
137 //              this.password = password;\r
138 //      }\r
139         \r
140         private SpreadSheetFactory(Authenticator authenticator){\r
141                 this.authenticator = authenticator;\r
142         }\r
143         \r
144         /**\r
145          * Deallocate SpreadSheetFactory instance\r
146          */\r
147         public void flushMe(){\r
148                 factory = null;\r
149                 if(spreadSheets != null)\r
150                         spreadSheets.clear();\r
151                 spreadSheets = null;\r
152                 authToken = null;\r
153                 authenticator = null;\r
154         }\r
155         \r
156         /**\r
157          *Create SpreadSheet with the given name\r
158          * \r
159          * @param spName SpreadSheet name\r
160          */\r
161         public void createSpreadSheet(String spName){\r
162                 // login for Document List API\r
163                 login(DOCUMENT_LIST_API_SERVICE_NAME);\r
164                 \r
165                 // Create a SpreadSheet\r
166                 String postData = "<?xml version='1.0' encoding='UTF-8'?>" +\r
167                                                   "<entry xmlns='http://www.w3.org/2005/Atom'>"+\r
168                                                   "<category scheme='http://schemas.google.com/g/2005#kind'"+\r
169                                                   " term='http://schemas.google.com/docs/2007#spreadsheet'/>"+\r
170                                                   "<title>"+ spName +"</title>"+\r
171                                                   "</entry>";\r
172                 // Add Headers\r
173                 HashMap<String, String> httpHeaders = new HashMap<String, String>();\r
174                 httpHeaders.put(HttpConHandler.AUTHORIZATION_HTTP_HEADER, "GoogleLogin auth="+ authToken);\r
175                 httpHeaders.put(HttpConHandler.GDATA_VERSION_HTTP_HEADER, "3.0");\r
176                 httpHeaders.put(HttpConHandler.CONTENT_LENGTH_HTTP_HEADER, ""+ postData.length());\r
177                 httpHeaders.put(HttpConHandler.CONTENT_TYPE_HTTP_HEADER, "application/atom+xml");\r
178                 \r
179                 // Http Connection\r
180                 HttpConHandler http = new HttpConHandler();\r
181                 http.doConnect(DOCUMENT_LIST_API_URL, HttpConHandler.HTTP_POST, httpHeaders, postData);\r
182                 \r
183                 // login for SpreadSheet API\r
184                 // revert back to SpreadSheet Auth Token\r
185                 login(SPREADSHEET_API_SERVICE_NAME);\r
186         }\r
187         \r
188         /**\r
189          * Delete a SpreadSheet\r
190          * \r
191          * @param resID Resource ID of the SpreadSheet you want to Delete\r
192          */\r
193         public void deleteSpreadSheet(String resID){\r
194                 \r
195                 // login for Document List API\r
196                 login(DOCUMENT_LIST_API_SERVICE_NAME);\r
197                 \r
198                 // Delete HTTP request\r
199                 String url = "https://docs.google.com/feeds/default/private/full/"+ resID +"?delete=true";\r
200                 // Add Headers\r
201                 HashMap<String, String> httpHeaders = new HashMap<String, String>();\r
202                 httpHeaders.put(HttpConHandler.AUTHORIZATION_HTTP_HEADER, "GoogleLogin auth="+ SpreadSheetFactory.authToken);\r
203                 httpHeaders.put(HttpConHandler.GDATA_VERSION_HTTP_HEADER, "3.0");\r
204                 httpHeaders.put("If-Match", "*");\r
205                 \r
206                 HttpConHandler http = new HttpConHandler();\r
207                 Response res = http.doConnect(url, HttpConHandler.HTTP_DELETE, httpHeaders, null);\r
208                 \r
209                 if(!res.isError()){\r
210                         for(int i=0; i<spreadSheets.size(); i++){\r
211                                 if(spreadSheets.get(0).getEntry().getResID() == resID)\r
212                                         spreadSheets.remove(i);\r
213                         }\r
214                 }\r
215                 \r
216                 // login for SpreadSheet API\r
217                 // revert back to SpreadSheet Auth Token\r
218                 login(SPREADSHEET_API_SERVICE_NAME);\r
219         }\r
220         \r
221         /**\r
222          * Get list of SpreadSheet with matching title. It will do Synch with Server\r
223          * \r
224          * @param title SpreadSheet title\r
225          * @param isTitleExact Whether title string should be an exact match\r
226          * \r
227          * @return\r
228          */\r
229         public ArrayList<SpreadSheet> getSpreadSheet(String title, boolean isTitleExact){\r
230                 return getAllSpreadSheets(true, title, isTitleExact);\r
231         }\r
232         \r
233         /**\r
234          * Get All stored SpreadSheets from Server\r
235          * \r
236          * @return\r
237          */\r
238         public ArrayList<SpreadSheet> getAllSpreadSheets(){\r
239                 return getAllSpreadSheets(true);\r
240         }\r
241         \r
242         /**\r
243          * Get All stored SpreadSheets either from Server or Local Cache\r
244          * \r
245          * @param doRefresh Do you want to Synch with Server ?\r
246          * @return List of Entry. Each Entry represents a SpreadSheet\r
247          */\r
248         public ArrayList<SpreadSheet> getAllSpreadSheets(boolean doRefresh){\r
249                 return getAllSpreadSheets(doRefresh, null, false);\r
250         }\r
251 \r
252         /**\r
253          * Get All stored SpreadSheets either from Server or Local Cache\r
254          * \r
255          * @param doRefresh\r
256          * @param title SpreadSheet title. <b>null</b> means all SpreadSheets. No need to do URL encode. \r
257          * @param isTitleExact Whether title string should be an exact match\r
258          * @return\r
259          */\r
260         public ArrayList<SpreadSheet> getAllSpreadSheets(boolean doRefresh, String title, boolean isTitleExact){\r
261                 \r
262                 /*\r
263                  *  TODO:\r
264                  *      Retrieve data only if there is change in Feed\r
265                  *      If-None-Match: W/"D0cERnk-eip7ImA9WBBXGEg."\r
266                  */\r
267                 \r
268                 if(!doRefresh){\r
269                         // Don't synch with Server\r
270                         return spreadSheets;\r
271                 }\r
272                 \r
273                 // login to Spreadsheet Service\r
274                 login(SPREADSHEET_API_SERVICE_NAME);\r
275                 \r
276                 // get list of all spreadsheets\r
277                 String xmlOut = getSpreadSheetList(title, isTitleExact);\r
278                 \r
279                 if(xmlOut == null){\r
280                         Log.p(TAG, "No SpreadSheet Feed received from Server!!");\r
281                         return null;\r
282                 }\r
283                 \r
284                 // XML Parsing\r
285                 ParseFeed pf = new ParseFeed();\r
286                 Feed f = pf.parse(xmlOut.getBytes());\r
287                 ArrayList<Entry> entries = f.getEntries();\r
288                 \r
289                 if(entries == null){\r
290                         // No SpreadSheet exists\r
291                         return null;\r
292                 }\r
293                 \r
294                 // Refresh SpreadSheet List from Server\r
295                 // Clear existing list\r
296                 spreadSheets.clear();\r
297                 \r
298                 for(int i=0; i<entries.size(); i++){\r
299                         spreadSheets.add(new SpreadSheet(entries.get(i)));\r
300                 }\r
301                 \r
302                 return spreadSheets;\r
303         }\r
304         \r
305         /**\r
306          * Share a SpreadSheet with a given list of Collaborators.\r
307          * NOTE: You need not to mention editLink of Collaborator\r
308          * \r
309          * @param sp The SpreadSheet you want to share\r
310          * @param collaborators List of Collaborators with whim you want to share this.\r
311          */\r
312         public void addSharePermission(SpreadSheet sp, Collaborator[] collaborators){\r
313                 \r
314                 if(sp == null || collaborators == null || collaborators.length == 0){\r
315                         throw new IllegalArgumentException("Please provide SpreadSheet ResID and Collaborator details to whom you want to share.");\r
316                 }\r
317                 \r
318                 // Get Document List API Authentication Token\r
319                 login(DOCUMENT_LIST_API_SERVICE_NAME);\r
320                 \r
321                 // Share Doc\r
322                 String postData = "";\r
323                 for(int i=0; i<collaborators.length; i++){\r
324                         \r
325                         Collaborator c = collaborators[i];\r
326                         \r
327                         postData = "<entry xmlns='http://www.w3.org/2005/Atom' xmlns:gAcl='http://schemas.google.com/acl/2007'>"+\r
328                                            "<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/acl/2007#accessRule'/>"+\r
329                                            "<gAcl:role value='"+ c.getRole() +"'/>"+\r
330                                            "<gAcl:scope type='"+ c.getScopeType() +"' value='"+ c.getScopeValue() +"'/>"+\r
331                                            "</entry>";\r
332                         \r
333                         // Send Data\r
334                         HashMap<String, String> httpHeaders = new HashMap<String, String>();\r
335                         httpHeaders.put(HttpConHandler.AUTHORIZATION_HTTP_HEADER, "GoogleLogin auth="+ authToken);\r
336                         httpHeaders.put(HttpConHandler.GDATA_VERSION_HTTP_HEADER, "3.0");\r
337                         httpHeaders.put(HttpConHandler.CONTENT_TYPE_HTTP_HEADER, "application/atom+xml");\r
338 \r
339                         // HTTP Connection\r
340                         HttpConHandler http = new HttpConHandler();\r
341                         String url = "https://docs.google.com/feeds/default/private/full/"+ sp.getResourceID() +"/acl";\r
342                         \r
343                         http.doConnect(url, HttpConHandler.HTTP_POST, httpHeaders, postData);\r
344                 }\r
345                 \r
346                 // Get SpreadSheet API Authentication Token\r
347                 login(SPREADSHEET_API_SERVICE_NAME);\r
348                 \r
349         }\r
350         \r
351         /**\r
352          * Get list of all Collaborators to whom this SpreadSheet is shared\r
353          * @param sp SpreadSheet\r
354          * @return\r
355          */\r
356         public ArrayList<Collaborator> getAllCollaborators(SpreadSheet sp){\r
357                 \r
358                 if(sp == null){\r
359                         throw new IllegalArgumentException("Please provide SpreadSheet ResID and Emails to whom you want to share.");\r
360                 }\r
361                 \r
362                 // Get Document List API Authentication Token\r
363                 login(DOCUMENT_LIST_API_SERVICE_NAME);\r
364                 \r
365                 HashMap<String, String> httpHeaders = new HashMap<String, String>();\r
366                 httpHeaders.put(HttpConHandler.AUTHORIZATION_HTTP_HEADER, "GoogleLogin auth="+ authToken);\r
367                 httpHeaders.put(HttpConHandler.GDATA_VERSION_HTTP_HEADER, "3.0");\r
368                 \r
369                 HttpConHandler http = new HttpConHandler();\r
370                 String url = "https://docs.google.com/feeds/default/private/full/"+ sp.getResourceID() +"/acl";\r
371                 Response res = http.doConnect(url, HttpConHandler.HTTP_GET, httpHeaders, null);\r
372                 \r
373                 // Get SpreadSheet API Authentication Token\r
374                 login(SPREADSHEET_API_SERVICE_NAME);\r
375                 \r
376                 // Process output\r
377                 String xmlOut = res.getOutput();\r
378                 \r
379                 if(xmlOut == null){\r
380                         Log.p(TAG, "No XML feed from Server!!");\r
381                         return null;\r
382                 }\r
383                 \r
384                 // XML Parsing\r
385                 ParseFeed pf = new ParseFeed();\r
386                 Feed f = pf.parse(xmlOut.getBytes());\r
387                 ArrayList<Entry> entries = f.getEntries();\r
388                 \r
389                 sp.clearCollaboratorList();\r
390                 \r
391                 if(entries != null){\r
392                         // Create Collaborator Instances\r
393                         System.out.println("Number of Collaborators: "+ entries.size());\r
394                         \r
395                         for(int i=0; i<entries.size(); i++){\r
396                                 Entry e = entries.get(i);\r
397                                 Collaborator c = new Collaborator();\r
398                                 c.setEditLink(e.getEditLink());\r
399                                 c.setScopeType(e.getAclScopeType());\r
400                                 c.setScopeValue(e.getAclScopeValue());\r
401                                 c.setRole(e.getAclRole());\r
402                                 \r
403                                 sp.addCollaborator(c);\r
404                         }\r
405                 }\r
406                 \r
407                 return sp.getCollaborators();\r
408         }\r
409         \r
410         /**\r
411          * Change Share permission for a particular ACL entry\r
412          * \r
413          * @param c Collaborator instance stored in SpreadSheet. It should have a valid EditLink URL\r
414          * @param role {owner, writer, reader} \r
415          */\r
416         public void changeSharePermission(Collaborator c, String role){\r
417                 // Get Document List API Authentication Token\r
418                 login(DOCUMENT_LIST_API_SERVICE_NAME);\r
419                 \r
420                 if(c.getEditLink() == null){\r
421                         throw new IllegalArgumentException("No EditLink URL defined in the Collaborator Instance");\r
422                 }\r
423                 \r
424                 String url = c.getEditLink();\r
425                 \r
426                 String postData = "<entry xmlns='http://www.w3.org/2005/Atom' xmlns:gAcl='http://schemas.google.com/acl/2007'>"+\r
427                                                   "<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/acl/2007#accessRule'/>"+\r
428                                                   "<gAcl:role value='"+ role +"'/>"+\r
429                                                   "<gAcl:scope type='"+ c.getScopeType() +"' value='"+ c.getScopeValue() +"'/>"+\r
430                                                   "</entry>";\r
431                 \r
432                 // HTTP Header- Send PUT request\r
433                 HashMap<String, String> httpHeaders = new HashMap<String, String>();\r
434                 httpHeaders.put(HttpConHandler.AUTHORIZATION_HTTP_HEADER, "GoogleLogin auth="+ authToken);\r
435                 httpHeaders.put(HttpConHandler.GDATA_VERSION_HTTP_HEADER, "3.0");\r
436                 httpHeaders.put(HttpConHandler.CONTENT_TYPE_HTTP_HEADER, "application/atom+xml");\r
437 \r
438                 // HTTP Connection\r
439                 HttpConHandler http = new HttpConHandler();\r
440                 http.doConnect(url, HttpConHandler.HTTP_PUT, httpHeaders, postData);\r
441                 \r
442                 // Get SpreadSheet API Authentication Token\r
443                 login(SPREADSHEET_API_SERVICE_NAME);\r
444         }\r
445         \r
446         /**\r
447          * Remove Share access of a selected user.\r
448          * @param c Collaborator Instance. It should have the Edit Link.\r
449          */\r
450         public void removeSharePermission(Collaborator c){\r
451                 // Get Document List API Authentication Token\r
452                 login(DOCUMENT_LIST_API_SERVICE_NAME);\r
453                 \r
454                 // HTTP Header- Send PUT request\r
455                 HashMap<String, String> httpHeaders = new HashMap<String, String>();\r
456                 httpHeaders.put(HttpConHandler.AUTHORIZATION_HTTP_HEADER, "GoogleLogin auth="+ authToken);\r
457                 httpHeaders.put(HttpConHandler.GDATA_VERSION_HTTP_HEADER, "3.0");\r
458                 \r
459                 HttpConHandler http = new HttpConHandler();\r
460                 String url = c.getEditLink();\r
461                 \r
462                 http.doConnect(url, HttpConHandler.HTTP_DELETE, httpHeaders, null);\r
463                 \r
464                 // Get SpreadSheet API Authentication Token\r
465                 login(SPREADSHEET_API_SERVICE_NAME);\r
466         }\r
467         \r
468         /**\r
469          * Login to get Authentication Token\r
470          * @param service\r
471          */\r
472         private void login(String service){\r
473                 // HTTP POST Data\r
474 //              String postData = "accountType=GOOGLE&Email="+ userName +"&Passwd="+ password +"&service="+ service +"&source=test-app-log";\r
475 //              \r
476 //              HttpConHandler http = new HttpConHandler();\r
477 //              Response res = http.doConnect(GOOGLE_CLIENT_LOGIN_URL, HttpConHandler.HTTP_POST, null, postData);\r
478 //              \r
479 //              if(res.isError()){\r
480 //                      return;\r
481 //              }\r
482 //              \r
483 //              String out = res.getOutput();\r
484 //              /*\r
485 //               * Format of success response\r
486 //               * SID=<>LSID=<>Auth=<>\r
487 //               */\r
488 //              String[] parms = out.split("=");\r
489 //              \r
490 //              for(int i=0; i<parms.length; i++){\r
491 //                      if(parms[i].toLowerCase().endsWith("auth")){\r
492 //                              authToken = parms[i+1];\r
493 //                              break;\r
494 //                      }\r
495 //              }\r
496 //              Log.p(TAG, "AuthToken="+ authToken);\r
497                 // A generic approach to add Authenticator Plug-in\r
498                 Log.p(TAG, "New Auth...");\r
499                 authToken = authenticator.getAuthToken(service);\r
500         }\r
501         \r
502         /**\r
503          * Get a list of stored SpreadSheets\r
504          * @return\r
505          */\r
506         private String getSpreadSheetList(String title, boolean isTitleExact){\r
507                 \r
508                 HashMap<String, String> httpHeaders = new HashMap<String, String>();\r
509                 httpHeaders.put(HttpConHandler.AUTHORIZATION_HTTP_HEADER, "GoogleLogin auth="+ authToken);\r
510                 httpHeaders.put(HttpConHandler.GDATA_VERSION_HTTP_HEADER, "3.0");\r
511                 \r
512                 HttpConHandler http = new HttpConHandler();\r
513                 String url = SP_GET_LIST_URL;\r
514                 \r
515                 // Add SpreadSheet Query Params (title and title-exact)\r
516                 if(title != null){\r
517                         url = url.concat("?title="+ HttpConHandler.encode(title));\r
518                         url = url.concat("&title-exact="+ isTitleExact);\r
519                 }\r
520                 \r
521                 Response res = http.doConnect(url, HttpConHandler.HTTP_GET, httpHeaders, null);\r
522                 \r
523                 if(res.isError()){\r
524                         return null;\r
525                 }\r
526                 \r
527                 return res.getOutput(); \r
528         }\r
529 }\r