select row on right click
[pithos] / src / gr / ebs / gss / client / rest / GetCommand.java
index 1ffe5a0..e6ea225 100644 (file)
@@ -35,7 +35,12 @@ import gr.ebs.gss.client.rest.resource.UploadStatusResource;
 import gr.ebs.gss.client.rest.resource.UserResource;
 import gr.ebs.gss.client.rest.resource.UserSearchResource;
 
+import java.util.HashMap;
+import java.util.Map;
+
+import com.google.gwt.core.client.GWT;
 import com.google.gwt.http.client.Request;
+import com.google.gwt.http.client.RequestBuilder;
 import com.google.gwt.http.client.Response;
 
 /**
@@ -45,66 +50,110 @@ public abstract class GetCommand<T extends RestResource> extends RestCommand{
 
        boolean complete = false;
        T result = null;
+       Throwable exception = null;
        Class<T> aclass;
+       private final String path;
+       private String username;
+       private boolean requestSent = false;
+       T cached;
+       
+       private static final long MAX_CACHE_AGE = 1000;
+       
+       private static class RequestData {
+               public String path;
+               public String username;
+               
+               public RequestData(String _path, String _username) {
+                       path = _path;
+                       username = _username;
+               }
+
+               @Override
+               public int hashCode() {
+                       final int prime = 31;
+                       int result = 1;
+                       result = prime * result + ((path == null) ? 0 : path.hashCode());
+                       result = prime * result + ((username == null) ? 0 : username.hashCode());
+                       return result;
+               }
 
-       public GetCommand(Class<T> theclass, String pathToGet){
-               this(theclass,pathToGet,true);
+               @Override
+               public boolean equals(Object obj) {
+                       if (this == obj)
+                               return true;
+                       if (obj == null)
+                               return false;
+                       if (getClass() != obj.getClass())
+                               return false;
+                       RequestData other = (RequestData) obj;
+                       if (path == null) {
+                               if (other.path != null)
+                                       return false;
+                       } else if (!path.equals(other.path))
+                               return false;
+                       if (username == null) {
+                               if (other.username != null)
+                                       return false;
+                       } else if (!username.equals(other.username))
+                               return false;
+                       return true;
+               }
+       }
+       
+       private static class ResponseData {
+               public long timestamp;
+               public Object result;
+               public ResponseData(long _timestamp, Object _result) {
+                       timestamp = _timestamp;
+                       result = _result;
+               }
+       }
+       
+       private static Map<RequestData, ResponseData> cache = new HashMap<RequestData, ResponseData>();
+       
+
+       public GetCommand(Class<T> theclass, String pathToGet, T theCached){
+               this(theclass, pathToGet, true, theCached);
        }
 
-       public GetCommand(Class<T> theclass, String pathToGet, boolean showLoading){
+       public GetCommand(Class<T> theclass, String pathToGet, boolean showLoading, T theCached){
                setShowLoadingIndicator(showLoading);
                if(isShowLoadingIndicator())
                        GSS.get().showLoadingIndicator();
                this.aclass = theclass;
-               final String path;
                if(pathToGet.indexOf("?") != -1)
                        path = pathToGet;
                else
                        path =fixPath(pathToGet);
-               RestRequestBuilder builder = new RestRequestBuilder("GET", path);
-
-               try {
-                       handleHeaders(builder, path);
-                       builder.sendRequest("", new RestCallback(path) {
-
-                               @Override
-                               public Object deserialize(Response response) {
-                                       return deserializeResponse(path, response);
-                               }
-
-                               @Override
-                               public void handleError(Request request, Throwable exception) {
-                                       complete = true;
-                                       GetCommand.this.onError(exception);
-                               }
-
-                               @Override
-                               public void handleSuccess(Object object) {
-                                       result = (T) object;
-                                       complete = true;
-                               }
-
-                       });
-               } catch (Exception ex) {
-                       complete = true;
-                       onError(ex);
-               }
+               this.cached = theCached;
        }
 
-       public GetCommand(Class<T> theclass, String username , String pathToGet){
-               this(theclass,username, pathToGet, true);
+       public GetCommand(Class<T> theclass, String aUsername , String pathToGet, T theCached){
+               this(theclass, aUsername, pathToGet, true, theCached);
        }
 
-       public GetCommand(Class<T> theclass, String username , String pathToGet, boolean showLoading){
+       public GetCommand(Class<T> theclass, String aUsername , String pathToGet, boolean showLoading, T theCached){
                setShowLoadingIndicator(showLoading);
                if(isShowLoadingIndicator())
                        GSS.get().showLoadingIndicator();
                this.aclass = theclass;
-               final String path = fixPath(pathToGet);
-               RestRequestBuilder builder = new RestRequestBuilder("GET", path);
+               path = fixPath(pathToGet);
+               this.username = aUsername;
+               this.cached = theCached;
+       }
 
+       private void sendRequest(){
+               if(requestSent)
+                       return;
+               requestSent=true;
+               RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, path);
+               if(cached!=null && cached.getLastModifiedSince() != null)
+                       builder.setHeader("If-Modified-Since", cached.getLastModifiedSince());
                try {
-                       handleHeaders(username, builder, path);
+                       if(username == null)
+                               handleHeaders(builder, path);
+                       else
+                               handleHeaders(username, builder, path);
                        builder.sendRequest("", new RestCallback(path) {
 
                                @Override
@@ -113,9 +162,16 @@ public abstract class GetCommand<T extends RestResource> extends RestCommand{
                                }
 
                                @Override
-                               public void handleError(Request request, Throwable exception) {
+                               public void handleError(Request request, Throwable _exception) {
+                                       result = null;
                                        complete = true;
-                                       GetCommand.this.onError(exception);
+                                       if(_exception instanceof RestException)
+                                               if(((RestException)_exception).getHttpStatusCode() == 304 && cached != null){
+                                                       GWT.log("Using cache:"+cached.getUri(), null);
+                                                       handleSuccess(cached);
+                                                       return;
+                                               }
+                                       exception = _exception;
                                }
 
                                @Override
@@ -127,10 +183,9 @@ public abstract class GetCommand<T extends RestResource> extends RestCommand{
                        });
                } catch (Exception ex) {
                        complete = true;
-                       onError(ex);
+                       exception = ex;
                }
        }
-
        public boolean isComplete() {
                return complete;
        }
@@ -139,77 +194,130 @@ public abstract class GetCommand<T extends RestResource> extends RestCommand{
                return result;
        }
 
+       @Override
        public boolean execute() {
                boolean com = isComplete();
+               RequestData key = new RequestData(path, username);
+               if (!com) {
+                       if (cache.containsKey(key)) {
+                               ResponseData resp = cache.get(key);
+                               if (resp==null) {
+                                       return true;
+                               }
+                               
+                               // Cache hit
+                               if (System.currentTimeMillis()-resp.timestamp>MAX_CACHE_AGE) {
+                                       // Cache stale, remove
+                                       cache.put(key,null);
+                               }
+                               else {
+                                       // Use cache data
+                                       if(isShowLoadingIndicator())
+                                               GSS.get().hideLoadingIndicator();
+                                       if (resp.result instanceof Throwable) {
+                                               // Error to be handled
+                                               Throwable ex = (Throwable) resp.result;
+                                               onError(ex);
+                                               return false;
+                                       }
+                                       result = (T) resp.result;
+                                       if (result != null) {
+                                               onComplete();
+                                       }
+                                       complete = true;
+                                       return false;
+                               }
+                       }
+               
+                       if(!requestSent) {
+                               cache.put(key,null);
+                               sendRequest();
+                       }
+               }
+               
                if(com){
                        if(isShowLoadingIndicator())
                                GSS.get().hideLoadingIndicator();
-                       if(getResult() != null)
+                       if(getResult() != null) {
+                               // Add to cache
+                               cache.put(key, new ResponseData(System.currentTimeMillis(), getResult()));
                                onComplete();
+                       }
+                       else {
+                               cache.put(key, new ResponseData(System.currentTimeMillis(), exception));
+                               onError(exception);
+                       }
                        return false;
                }
                return true;
        }
 
-       public Object deserializeResponse(String path, Response response) {
+       public Object deserializeResponse(String aPath, Response response) {
                RestResource result1 = null;
                if(aclass.equals(FolderResource.class)){
-                       result1 = new FolderResource(path);
+                       result1 = new FolderResource(aPath);
                        result1.createFromJSON(response.getText());
                }
                else if(aclass.equals(FileResource.class)){
-                       result1 = new FileResource(path);
+                       result1 = new FileResource(aPath);
                        result1.createFromJSON(response.getHeader("X-GSS-Metadata"));
                }
                else if(aclass.equals(GroupsResource.class)){
-                       result1 = new GroupsResource(path);
+                       result1 = new GroupsResource(aPath);
                        result1.createFromJSON(response.getText());
                }
                else if(aclass.equals(TrashResource.class)){
-                       result1 = new TrashResource(path);
+                       result1 = new TrashResource(aPath);
                        result1.createFromJSON(response.getText());
                }
                else if(aclass.equals(SharedResource.class)){
-                       result1 = new SharedResource(path);
+                       result1 = new SharedResource(aPath);
                        result1.createFromJSON(response.getText());
                }
                else if(aclass.equals(OthersResource.class)){
-                       result1 = new OthersResource(path);
+                       result1 = new OthersResource(aPath);
                        result1.createFromJSON(response.getText());
                }
                else if(aclass.equals(OtherUserResource.class)){
-                       result1 = new OtherUserResource(path);
+                       result1 = new OtherUserResource(aPath);
                        result1.createFromJSON(response.getText());
                }
                else if(aclass.equals(GroupResource.class)){
-                       result1 = new GroupResource(path);
+                       result1 = new GroupResource(aPath);
                        result1.createFromJSON(response.getText());
                }
                else if(aclass.equals(GroupUserResource.class)){
-                       result1 = new GroupUserResource(path);
+                       result1 = new GroupUserResource(aPath);
                        result1.createFromJSON(response.getText());
                }
                else if(aclass.equals(UserResource.class)){
-                       result1 = new UserResource(path);
+                       result1 = new UserResource(aPath);
                        result1.createFromJSON(response.getText());
                }
                else if(aclass.equals(TagsResource.class)){
-                       result1 = new TagsResource(path);
+                       result1 = new TagsResource(aPath);
                        result1.createFromJSON(response.getText());
                }
                else if(aclass.equals(SearchResource.class)){
-                       result1 = new SearchResource(path);
+                       result1 = new SearchResource(aPath);
                        result1.createFromJSON(response.getText());
                }
                else if(aclass.equals(UserSearchResource.class)){
-                       result1 = new UserSearchResource(path);
+                       result1 = new UserSearchResource(aPath);
                        result1.createFromJSON(response.getText());
                }
                else if(aclass.equals(UploadStatusResource.class)){
-                       result1 = new UploadStatusResource(path);
+                       result1 = new UploadStatusResource(aPath);
                        result1.createFromJSON(response.getText());
                }
                return result1;
        }
 
+       public T getCached() {
+               return cached;
+       }
+
+       public void setCached(T theCached) {
+               this.cached = theCached;
+       }
 }