Updated copyright notice
[pithos-web-client] / src / gr / grnet / pithos / web / client / FileList.java
1 /*
2  * Copyright (c) 2011 Greek Research and Technology Network
3  */
4
5 package gr.grnet.pithos.web.client;
6
7 import static com.google.gwt.query.client.GQuery.$;
8
9 import gr.grnet.pithos.web.client.commands.UploadFileCommand;
10 import gr.grnet.pithos.web.client.rest.GetCommand;
11 import gr.grnet.pithos.web.client.rest.RestCommand;
12 import gr.grnet.pithos.web.client.rest.resource.FileResource;
13 import gr.grnet.pithos.web.client.rest.resource.OtherUserResource;
14 import gr.grnet.pithos.web.client.rest.resource.OthersFolderResource;
15 import gr.grnet.pithos.web.client.rest.resource.OthersResource;
16 import gr.grnet.pithos.web.client.rest.resource.RestResource;
17 import gr.grnet.pithos.web.client.rest.resource.RestResourceWrapper;
18 import gr.grnet.pithos.web.client.rest.resource.SharedResource;
19 import gr.grnet.pithos.web.client.rest.resource.TrashFolderResource;
20 import gr.grnet.pithos.web.client.rest.resource.TrashResource;
21 import gr.grnet.pithos.web.client.rest.resource.UserResource;
22 import gr.grnet.pithos.web.client.rest.resource.UserSearchResource;
23 import gwtquery.plugins.draggable.client.DraggableOptions;
24 import gwtquery.plugins.draggable.client.StopDragException;
25 import gwtquery.plugins.draggable.client.DraggableOptions.DragFunction;
26 import gwtquery.plugins.draggable.client.DraggableOptions.RevertOption;
27 import gwtquery.plugins.draggable.client.events.DragContext;
28 import gwtquery.plugins.draggable.client.events.DragStartEvent;
29 import gwtquery.plugins.draggable.client.events.DragStopEvent;
30 import gwtquery.plugins.draggable.client.events.DragStartEvent.DragStartEventHandler;
31 import gwtquery.plugins.draggable.client.events.DragStopEvent.DragStopEventHandler;
32 import gwtquery.plugins.droppable.client.gwt.DragAndDropCellTable;
33 import gwtquery.plugins.droppable.client.gwt.DragAndDropColumn;
34
35 import java.util.ArrayList;
36 import java.util.Collections;
37 import java.util.Comparator;
38 import java.util.Iterator;
39 import java.util.List;
40
41 import com.google.gwt.cell.client.AbstractCell;
42 import com.google.gwt.cell.client.ImageResourceCell;
43 import com.google.gwt.cell.client.SafeHtmlCell;
44 import com.google.gwt.cell.client.TextCell;
45 import com.google.gwt.cell.client.ValueUpdater;
46 import com.google.gwt.core.client.GWT;
47 import com.google.gwt.core.client.Scheduler;
48 import com.google.gwt.core.client.Scheduler.RepeatingCommand;
49 import com.google.gwt.dom.client.Style.Cursor;
50 import com.google.gwt.event.dom.client.ClickEvent;
51 import com.google.gwt.event.dom.client.ClickHandler;
52 import com.google.gwt.http.client.URL;
53 import com.google.gwt.i18n.client.DateTimeFormat;
54 import com.google.gwt.resources.client.ClientBundle;
55 import com.google.gwt.resources.client.ImageResource;
56 import com.google.gwt.safehtml.client.SafeHtmlTemplates;
57 import com.google.gwt.safehtml.shared.SafeHtml;
58 import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
59 import com.google.gwt.user.cellview.client.CellTable;
60 import com.google.gwt.user.cellview.client.GssSimplePager;
61 import com.google.gwt.user.client.DOM;
62 import com.google.gwt.user.client.DeferredCommand;
63 import com.google.gwt.user.client.Event;
64 import com.google.gwt.user.client.Window;
65 import com.google.gwt.user.client.ui.AbstractImagePrototype;
66 import com.google.gwt.user.client.ui.Button;
67 import com.google.gwt.user.client.ui.Composite;
68 import com.google.gwt.user.client.ui.HorizontalPanel;
69 import com.google.gwt.user.client.ui.VerticalPanel;
70 import com.google.gwt.view.client.ListDataProvider;
71 import com.google.gwt.view.client.MultiSelectionModel;
72 import com.google.gwt.view.client.ProvidesKey;
73 import com.google.gwt.view.client.SelectionChangeEvent;
74 import com.google.gwt.view.client.SelectionChangeEvent.Handler;
75
76 /**
77  * A composite that displays the list of files in a particular folder.
78  */
79 public class FileList extends Composite {
80         ListDataProvider<FileResource> provider = new ListDataProvider<FileResource>();
81         interface TableResources extends DragAndDropCellTable.Resources {
82             @Source({CellTable.Style.DEFAULT_CSS, "GssCellTable.css"})
83             TableStyle cellTableStyle();
84           }
85         
86         static interface Templates extends SafeHtmlTemplates {
87             Templates INSTANCE = GWT.create(Templates.class);
88
89             @Template("<div id='dragHelper' style='border:1px solid black; background-color:#ffffff; color:black; width:150px;z-index:100'></div>")
90             SafeHtml outerHelper();
91
92         @Template("<span id='{0}'>{0}</span>")
93         public SafeHtml filenameSpan(String filename);
94
95         @Template("<a href='{0}' title='{1}' rel='lytebox[mnf]' onclick='myLytebox.start(this, false, false); return false;'>(view)</a>")
96         public SafeHtml viewLink(String link, String title);
97
98         @Template("<table><tr><td rowspan='3'>{0}</td><td style='font-size:95%;' id='{1}'>{1}</td></tr><tr><td>{2}</td></tr></table>")
99         public SafeHtml rendelContactCell(String imageHtml, String name, String fileSize);
100
101         @Template("<span id='{0}' class='{1}'>{2}</span>")
102         public SafeHtml spanWithIdAndClass(String id, String cssClass, String content);
103           }
104         
105         
106         /**
107            * The styles applied to the table.
108            */
109           interface TableStyle extends CellTable.Style {
110           }
111
112         private String showingStats = "";
113
114         private int startIndex = 0;
115
116         /**
117          * A constant that denotes the completion of an IncrementalCommand.
118          */
119         public static final boolean DONE = false;
120
121         
122         
123         private final DateTimeFormat formatter = DateTimeFormat.getFormat("d/M/yyyy h:mm a");
124
125         /**
126          * Specifies that the images available for this composite will be the ones
127          * available in FileContextMenu.
128          */
129         public interface Images extends ClientBundle,FileContextMenu.Images, CellTreeView.Images {
130
131                 @Source("gr/grnet/pithos/resources/blank.gif")
132                 ImageResource blank();
133
134                 @Source("gr/grnet/pithos/resources/asc.png")
135                 ImageResource asc();
136
137                 @Source("gr/grnet/pithos/resources/desc.png")
138                 ImageResource desc();
139
140                 @Source("gr/grnet/pithos/resources/mimetypes/document_shared.png")
141                 ImageResource documentShared();
142
143                 @Source("gr/grnet/pithos/resources/mimetypes/kcmfontinst.png")
144                 ImageResource wordprocessor();
145
146                 @Source("gr/grnet/pithos/resources/mimetypes/log.png")
147                 ImageResource spreadsheet();
148
149                 @Source("gr/grnet/pithos/resources/mimetypes/kpresenter_kpr.png")
150                 ImageResource presentation();
151
152                 @Source("gr/grnet/pithos/resources/mimetypes/acroread.png")
153                 ImageResource pdf();
154
155                 @Source("gr/grnet/pithos/resources/mimetypes/image.png")
156                 ImageResource image();
157
158                 @Source("gr/grnet/pithos/resources/mimetypes/video2.png")
159                 ImageResource video();
160
161                 @Source("gr/grnet/pithos/resources/mimetypes/knotify.png")
162                 ImageResource audio();
163
164                 @Source("gr/grnet/pithos/resources/mimetypes/html.png")
165                 ImageResource html();
166
167                 @Source("gr/grnet/pithos/resources/mimetypes/txt.png")
168                 ImageResource txt();
169
170                 @Source("gr/grnet/pithos/resources/mimetypes/ark2.png")
171                 ImageResource zip();
172
173                 @Source("gr/grnet/pithos/resources/mimetypes/kcmfontinst_shared.png")
174                 ImageResource wordprocessorShared();
175
176                 @Source("gr/grnet/pithos/resources/mimetypes/log_shared.png")
177                 ImageResource spreadsheetShared();
178
179                 @Source("gr/grnet/pithos/resources/mimetypes/kpresenter_kpr_shared.png")
180                 ImageResource presentationShared();
181
182                 @Source("gr/grnet/pithos/resources/mimetypes/acroread_shared.png")
183                 ImageResource pdfShared();
184
185                 @Source("gr/grnet/pithos/resources/mimetypes/image_shared.png")
186                 ImageResource imageShared();
187
188                 @Source("gr/grnet/pithos/resources/mimetypes/video2_shared.png")
189                 ImageResource videoShared();
190
191                 @Source("gr/grnet/pithos/resources/mimetypes/knotify_shared.png")
192                 ImageResource audioShared();
193
194                 @Source("gr/grnet/pithos/resources/mimetypes/html_shared.png")
195                 ImageResource htmlShared();
196
197                 @Source("gr/grnet/pithos/resources/mimetypes/txt_shared.png")
198                 ImageResource txtShared();
199
200                 @Source("gr/grnet/pithos/resources/mimetypes/ark2_shared.png")
201                 ImageResource zipShared();
202
203         }
204         
205         DragStopEventHandler dragStop = new DragStopEventHandler() {
206                 
207                 @Override
208                 public void onDragStop(DragStopEvent event) {
209                         GWT.log("DRAG STOPPED");
210                         
211                 }
212         };
213         
214         private static class ContactCell extends AbstractCell<gr.grnet.pithos.web.client.rest.resource.FileResource> {
215
216             /**
217              * The html of the image used for contacts.
218              * 
219              */
220             private final String imageHtml;
221
222             public ContactCell(ImageResource image) {
223               this.imageHtml = AbstractImagePrototype.create(image).getHTML();
224             }
225
226             
227
228                 
229
230             @Override
231             public void render(Context context, FileResource value, SafeHtmlBuilder sb) {
232               // Value can be null, so do a null check..
233               if (value == null) {
234                 return;
235               }
236
237           sb.append(Templates.INSTANCE.rendelContactCell(imageHtml, value.getName(), value.getFileSizeAsString()));
238             }
239
240
241           }
242         /**
243          * Retrieve the celltable.
244          *
245          * @return the celltable
246          */
247         public DragAndDropCellTable<FileResource> getCelltable() {
248                 return celltable;
249         }
250         
251         
252         /**
253          * The number of files in this folder.
254          */
255         int folderFileCount;
256
257         /**
258          * Total folder size
259          */
260         long folderTotalSize;
261
262         /**
263          * A cache of the files in the list.
264          */
265         private List<FileResource> files;
266
267         /**
268          * The widget's image bundle.
269          */
270         private final Images images;
271         
272         private FileContextMenu menuShowing;
273         private DragAndDropCellTable<FileResource> celltable;
274         private final MultiSelectionModel<FileResource> selectionModel;
275         private final List<SortableHeader> allHeaders = new ArrayList<SortableHeader>();
276         SortableHeader nameHeader;
277         GssSimplePager pagerBottom;
278         GssSimplePager pagerTop;
279         Button uploadButtonBottom;
280         Button uploadButtonTop;
281         /**
282          * Construct the file list widget. This entails setting up the widget
283          * layout, fetching the number of files in the current folder from the
284          * server and filling the local file cache of displayed files with data from
285          * the server, as well.
286          *
287          * @param _images
288          */
289         public FileList(Images _images) {
290                 images = _images;
291                 DragAndDropCellTable.Resources resources = GWT.create(TableResources.class);
292                 ProvidesKey<FileResource> keyProvider = new ProvidesKey<FileResource>(){
293
294                         @Override
295                         public Object getKey(FileResource item) {
296                                 return item.getUri();
297                         }
298                         
299                 };
300                 celltable = new DragAndDropCellTable<FileResource>(GSS.VISIBLE_FILE_COUNT,resources,keyProvider);
301                 
302                 DragAndDropColumn<FileResource, ImageResource> status = new DragAndDropColumn<FileResource, ImageResource>(new ImageResourceCell(){
303                         @Override
304                   public boolean handlesSelection() {
305                             return false;
306                           }
307                 }) {
308                   @Override
309                   public ImageResource getValue(FileResource entity) {
310                     return getFileIcon(entity);
311                   }
312                   
313                };
314             celltable.addColumn(status,"");
315             
316             initDragOperation(status);
317                 final DragAndDropColumn<FileResource,SafeHtml> nameColumn = new DragAndDropColumn<FileResource,SafeHtml>(new SafeHtmlCell()) {
318
319                         @Override
320                         public SafeHtml getValue(FileResource object) {
321                                 SafeHtmlBuilder sb = new SafeHtmlBuilder();
322                 sb.append(Templates.INSTANCE.filenameSpan(object.getName()));
323                                 if (object.getContentType().endsWith("png") || object.getContentType().endsWith("gif") || object.getContentType().endsWith("jpeg") ){
324                                         sb.appendHtmlConstant("&nbsp;").append(Templates.INSTANCE.viewLink(GSS.get().getTopPanel().getFileMenu().getDownloadURL(object), object.getOwner() + " : " + object.getPath() + object.getName()));
325                                 }
326                                 
327                                 return sb.toSafeHtml();
328                         }
329                         
330                 };
331                 initDragOperation(nameColumn);
332                 celltable.addColumn(nameColumn,nameHeader = new SortableHeader("Name"));
333                 allHeaders.add(nameHeader);
334                 //nameHeader.setSorted(true);
335                 //nameHeader.toggleReverseSort();
336                 nameHeader.setUpdater(new FileValueUpdater(nameHeader, "name"));
337                 celltable.redrawHeaders();
338                 
339                 
340             
341             
342             SortableHeader aheader;
343             DragAndDropColumn<FileResource,String> aColumn;
344                 celltable.addColumn(aColumn=new DragAndDropColumn<FileResource,String>(new TextCell()) {
345                         @Override
346                         public String getValue(FileResource object) {
347                                 return GSS.get().findUserFullName(object.getOwner());
348                         }                       
349                 },aheader = new SortableHeader("Owner"));
350                 initDragOperation(aColumn);
351                 allHeaders.add(aheader);
352                 aheader.setUpdater(new FileValueUpdater(aheader, "owner"));
353                 celltable.addColumn(aColumn=new DragAndDropColumn<FileResource,String>(new TextCell()) {
354                         @Override
355                         public String getValue(FileResource object) {
356                                 // TODO Auto-generated method stub
357                                 return object.getPath();
358                         }                       
359                 },aheader = new SortableHeader("Path"));
360                 initDragOperation(aColumn);
361                 allHeaders.add(aheader);
362                 
363                 aheader.setUpdater(new FileValueUpdater(aheader, "path"));      
364                 celltable.addColumn(aColumn=new DragAndDropColumn<FileResource,String>(new TextCell()) {
365                         @Override
366                         public String getValue(FileResource object) {
367                                 if(object.isVersioned())
368                                         return object.getVersion().toString();
369                                 return "-";
370                         }                       
371                 },aheader = new SortableHeader("Version"));
372                 initDragOperation(aColumn);
373                 allHeaders.add(aheader);
374                 aheader.setUpdater(new FileValueUpdater(aheader, "version"));
375                 celltable.addColumn(aColumn=new DragAndDropColumn<FileResource,String>(new TextCell()) {
376                         @Override
377                         public String getValue(FileResource object) {
378                                 // TODO Auto-generated method stub
379                                 return object.getFileSizeAsString();
380                         }                       
381                 },aheader = new SortableHeader("Size"));
382                 initDragOperation(aColumn);
383                 allHeaders.add(aheader);
384                 aheader.setUpdater(new FileValueUpdater(aheader, "size"));      
385                 celltable.addColumn(aColumn=new DragAndDropColumn<FileResource,String>(new TextCell()) {
386                         @Override
387                         public String getValue(FileResource object) {
388                                 return formatter.format(object.getModificationDate());
389                         }                       
390                 },aheader = new SortableHeader("Last Modified"));
391                 allHeaders.add(aheader);
392                 aheader.setUpdater(new FileValueUpdater(aheader, "date"));
393                
394                 
395                 provider.addDataDisplay(celltable);
396                 celltable.addDragStopHandler(dragStop);
397                 celltable.addDragStartHandler(new DragStartEventHandler() {
398
399                       public void onDragStart(DragStartEvent event) {
400                         FileResource value = event.getDraggableData();
401                         
402                         com.google.gwt.dom.client.Element helper = event.getHelper();
403                         SafeHtmlBuilder sb = new SafeHtmlBuilder();
404                         sb.appendHtmlConstant("<b>");
405                         DisplayHelper.log(value.getName());
406                         if(getSelectedFiles().size()==1)
407                                 sb.appendEscaped(value.getName());
408                         else
409                                 sb.appendEscaped(getSelectedFiles().size()+" files");
410                         sb.appendHtmlConstant("</b>");
411                         helper.setInnerHTML(sb.toSafeHtml().asString());
412
413                       }
414                     });
415                 
416                 
417                 
418                 
419                 
420                 
421                 VerticalPanel vp = new VerticalPanel();
422                 vp.setWidth("100%");
423                 pagerTop = new GssSimplePager(GssSimplePager.TextLocation.CENTER);
424                 pagerTop.setDisplay(celltable); 
425                 uploadButtonTop=new Button("<span id='topMenu.file.upload'>" + AbstractImagePrototype.create(images.fileUpdate()).getHTML() + "&nbsp;Upload</span>");
426                 uploadButtonTop.addClickHandler(new ClickHandler() {
427                         
428                         @Override
429                         public void onClick(ClickEvent event) {
430                                 new UploadFileCommand(null).execute();
431                         }
432                 });
433                 HorizontalPanel topPanel = new HorizontalPanel();
434                 topPanel.add(pagerTop);
435                 topPanel.add(uploadButtonTop);
436                 vp.add(topPanel);
437                 celltable.setWidth("100%");
438                 vp.add(celltable);
439                 pagerBottom = new GssSimplePager(GssSimplePager.TextLocation.CENTER);
440                 pagerBottom.setDisplay(celltable);
441                 HorizontalPanel bottomPanel = new HorizontalPanel();
442                 bottomPanel.add(pagerBottom);
443                 uploadButtonBottom=new Button("<span id='topMenu.file.upload'>" + AbstractImagePrototype.create(images.fileUpdate()).getHTML() + "&nbsp;Upload</span>");
444                 uploadButtonBottom.addClickHandler(new ClickHandler() {
445                         
446                         @Override
447                         public void onClick(ClickEvent event) {
448                                 new UploadFileCommand(null).execute();
449                         }
450                 });
451                 bottomPanel.add(uploadButtonBottom);
452                 vp.add(bottomPanel);
453                 vp.setCellWidth(celltable, "100%");
454                 
455                 initWidget(vp);
456                 pagerBottom.setVisible(false);
457                 pagerTop.setVisible(false);
458
459                 celltable.setStyleName("pithos-List");
460                 selectionModel = new MultiSelectionModel<FileResource>(keyProvider);
461                 
462
463                  Handler selectionHandler = new SelectionChangeEvent.Handler() { 
464              @Override 
465              public void onSelectionChange(com.google.gwt.view.client.SelectionChangeEvent event) {
466                  if(getSelectedFiles().size()==1)
467                          GSS.get().setCurrentSelection(getSelectedFiles().get(0));
468                  else
469                          GSS.get().setCurrentSelection(getSelectedFiles());
470              }
471          };
472          selectionModel.addSelectionChangeHandler(selectionHandler);
473          
474                 celltable.setSelectionModel(selectionModel,GSSSelectionEventManager.<FileResource>createDefaultManager());
475                 celltable.setPageSize(GSS.VISIBLE_FILE_COUNT);
476                 
477                 //celltable.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);
478                 Scheduler.get().scheduleIncremental(new RepeatingCommand() {
479
480                         @Override
481                         public boolean execute() {
482                                 return fetchRootFolder();
483                         }
484                 });
485                 sinkEvents(Event.ONCONTEXTMENU);
486                 sinkEvents(Event.ONMOUSEUP);
487                 sinkEvents(Event.ONMOUSEDOWN);
488                 sinkEvents(Event.ONCLICK);
489                 sinkEvents(Event.ONKEYDOWN);
490                 sinkEvents(Event.ONDBLCLICK);
491                 GSS.preventIESelection();
492         }
493         
494         //public native void fireClickEvent(Element element) /*-{
495           //  var evObj = $doc.createEvent('MouseEvents');
496             //evObj.initEvent('click', true, true);
497             //element.dispatchEvent(evObj);
498         //}-*/;
499         
500         
501         
502          public List<FileResource> getSelectedFiles() {
503          return new ArrayList<FileResource>(selectionModel.getSelectedSet());
504          }
505         
506          private void initDragOperation(DragAndDropColumn<?, ?> column) {
507
508                     // retrieve draggableOptions on the column
509                     DraggableOptions draggableOptions = column.getDraggableOptions();
510                     // use template to construct the helper. The content of the div will be set
511                     // after
512                     draggableOptions.setHelper($(Templates.INSTANCE.outerHelper().asString()));
513                     //draggableOptions.setZIndex(100);
514                     // opacity of the helper
515                     draggableOptions.setAppendTo("body"); 
516                     //draggableOptions.setOpacity((float) 0.8);
517                     draggableOptions.setContainment("document");
518                     // cursor to use during the drag operation
519                     draggableOptions.setCursor(Cursor.MOVE);
520                     // set the revert option
521                     draggableOptions.setRevert(RevertOption.ON_INVALID_DROP);
522                     // prevents dragging when user click on the category drop-down list
523                     draggableOptions.setCancel("select");
524                     
525                     
526                     draggableOptions.setOnBeforeDragStart(new DragFunction() {
527                                 
528                                 @Override
529                                 public void f(DragContext context) {
530                                          FileResource value = context.getDraggableData();
531                                      if(!selectionModel.isSelected(value)){
532                                         throw new StopDragException();
533                                       }
534                                         
535                                 }
536                         });
537                   }
538         
539          public void showContextMenu(Event event){
540                  menuShowing = new FileContextMenu(images, false, true);
541                         menuShowing=menuShowing.onEmptyEvent(event);
542          }
543         @Override
544         public void onBrowserEvent(Event event) {
545                 
546                 if (files == null || files.size() == 0) {
547                         if (DOM.eventGetType(event) == Event.ONCONTEXTMENU && getSelectedFiles().size() == 0) {
548                                 menuShowing = new FileContextMenu(images, false, true);
549                                 menuShowing=menuShowing.onEmptyEvent(event);
550                                 event.preventDefault();
551                                 event.cancelBubble(true);
552                         }
553                         return;
554                 }
555                 if (DOM.eventGetType(event) == Event.ONCONTEXTMENU && getSelectedFiles().size() != 0) {
556                         GWT.log("*****GOING TO SHOW CONTEXT MENU ****", null);
557                         menuShowing =  new FileContextMenu(images, false, false);
558                         menuShowing=menuShowing.onEvent(event);
559                         event.cancelBubble(true);
560                         event.preventDefault();
561                 } else if (DOM.eventGetType(event) == Event.ONCONTEXTMENU && getSelectedFiles().size() == 0) {
562                         menuShowing = new FileContextMenu(images, false, true);
563                         menuShowing=menuShowing.onEmptyEvent(event);
564                         event.cancelBubble(true);
565                         event.preventDefault();
566                 } else if (DOM.eventGetType(event) == Event.ONDBLCLICK)
567                         if (getSelectedFiles().size() == 1) {
568                                 GSS app = GSS.get();
569                                 FileResource file = getSelectedFiles().get(0);
570                                 String dateString = RestCommand.getDate();
571                                 String resource = file.getUri().substring(app.getApiPath().length() - 1, file.getUri().length());
572                                 String sig = app.getCurrentUserResource().getUsername() + " " +
573                                                 RestCommand.calculateSig("GET", dateString, resource,
574                                                 RestCommand.base64decode(app.getToken()));
575                                 Window.open(file.getUri() + "?Authorization=" + URL.encodeComponent(sig) + "&Date=" + URL.encodeComponent(dateString), "_blank", "");
576                                 event.preventDefault();
577                                 return;
578                         }
579                 super.onBrowserEvent(event);
580         }
581
582         /**
583          * Retrieve the root folder for the current user.
584          *
585          * @return true if the retrieval was successful
586          */
587         protected boolean fetchRootFolder() {
588                 UserResource user = GSS.get().getCurrentUserResource();
589                 if (user == null)
590                         return !DONE;
591                 // Update cache and clear selection.
592                 updateFileCache(true);
593                 return DONE;
594         }
595
596
597         /**
598          * Update the display of the file list.
599          */
600         void update(boolean sort) {
601                 int count = folderFileCount;
602                 int max = startIndex + GSS.VISIBLE_FILE_COUNT;
603                 if (max > count)
604                         max = count;
605                 folderTotalSize = 0;
606                 
607                 copyListAndContinue(files);
608                 for(FileResource f : files){
609                         folderTotalSize += f.getContentLength();
610                 }
611                 if (folderFileCount == 0) {
612                         showingStats = "no files";
613                 } else if (folderFileCount < GSS.VISIBLE_FILE_COUNT) {
614                         if (folderFileCount == 1)
615                                 showingStats = "1 file";
616                         else
617                                 showingStats = folderFileCount + " files";
618                         showingStats += " (" + FileResource.getFileSizeAsString(folderTotalSize) + ")";
619                 } else {
620                         showingStats = "" + (startIndex + 1) + " - " + max + " of " + count + " files" + " (" + FileResource.getFileSizeAsString(folderTotalSize) + ")";
621                 }
622                 showCellTable();
623                 updateCurrentlyShowingStats();
624
625         }
626
627         /**
628          * Return the proper icon based on the MIME type of the file.
629          *
630          * @param file
631          * @return the icon
632          */
633         private ImageResource getFileIcon(FileResource file) {
634                 String mimetype = file.getContentType();
635                 boolean shared = false;
636                 if(GSS.get().getTreeView().getSelection()!=null && (GSS.get().getTreeView().getSelection() instanceof OtherUserResource || GSS.get().getTreeView().getSelection() instanceof OthersFolderResource)){
637                         OtherUserResource otherUser = null;
638                         if(GSS.get().getTreeView().getSelection() instanceof OtherUserResource)
639                                 otherUser = (OtherUserResource) GSS.get().getTreeView().getSelection();
640                         else if (GSS.get().getTreeView().getSelection() instanceof OthersFolderResource){
641                                 otherUser = GSS.get().getTreeView().getOtherUserResourceOfOtherFolder((OthersFolderResource) GSS.get().getTreeView().getSelection());
642                         }
643                         if(otherUser ==null)
644                                 shared=false;
645                         else{
646                                 String uname = otherUser.getUsername();
647                                 if(uname==null)
648                                         uname = GSS.get().getTreeView().getOthers().getUsernameOfUri(otherUser.getUri());
649                                 if(uname != null)
650                                         shared = file.isShared();
651                         }
652                 }
653                 else
654                         shared = file.isShared();
655                 if (mimetype == null)
656                         return shared ? images.documentShared() : images.document();
657                 mimetype = mimetype.toLowerCase();
658                 if (mimetype.startsWith("application/pdf"))
659                         return shared ? images.pdfShared() : images.pdf();
660                 else if (mimetype.endsWith("excel"))
661                         return shared ? images.spreadsheetShared() : images.spreadsheet();
662                 else if (mimetype.endsWith("msword"))
663                         return shared ? images.wordprocessorShared() : images.wordprocessor();
664                 else if (mimetype.endsWith("powerpoint"))
665                         return shared ? images.presentationShared() : images.presentation();
666                 else if (mimetype.startsWith("application/zip") ||
667                                         mimetype.startsWith("application/gzip") ||
668                                         mimetype.startsWith("application/x-gzip") ||
669                                         mimetype.startsWith("application/x-tar") ||
670                                         mimetype.startsWith("application/x-gtar"))
671                         return shared ? images.zipShared() : images.zip();
672                 else if (mimetype.startsWith("text/html"))
673                         return shared ? images.htmlShared() : images.html();
674                 else if (mimetype.startsWith("text/plain"))
675                         return shared ? images.txtShared() : images.txt();
676                 else if (mimetype.startsWith("image/"))
677                         return shared ? images.imageShared() : images.image();
678                 else if (mimetype.startsWith("video/"))
679                         return shared ? images.videoShared() : images.video();
680                 else if (mimetype.startsWith("audio/"))
681                         return shared ? images.audioShared() : images.audio();
682                 return shared ? images.documentShared() : images.document();
683         }
684
685         /**
686          * Update status panel with currently showing file stats.
687          */
688         public void updateCurrentlyShowingStats() {
689                 GSS.get().getStatusPanel().updateCurrentlyShowing(showingStats);
690         }
691         
692         public void updateFileCache(boolean clearSelection){
693                 if(clearSelection){
694                         clearSelectedRows();
695                 }
696                 
697                 final RestResource folderItem = GSS.get().getTreeView().getSelection();
698                 // Validation.
699                 if (folderItem == null || folderItem.equals(GSS.get().getTreeView().getOthers())) {
700                         setFiles(new ArrayList<FileResource>());
701                         update(true);
702                         return;
703                 }
704                 else if (folderItem instanceof RestResourceWrapper) {
705                         setFiles(((RestResourceWrapper) folderItem).getResource().getFiles());
706                         update(true);
707                 }
708                 else if (folderItem instanceof SharedResource) {
709                         setFiles(((SharedResource) folderItem).getFiles());
710                         update(true);
711                 }
712                 else if (folderItem instanceof OtherUserResource) {
713                         setFiles(((OtherUserResource) folderItem).getFiles());
714                         update(true);
715                 }
716                 else if (folderItem instanceof TrashResource) {
717                         setFiles(((TrashResource) folderItem).getFiles());
718                         update(true);
719                 }
720         }
721         
722
723         /**
724          * Fill the file cache with data.
725          */
726         public void setFiles(final List<FileResource> _files) {
727                 if (_files.size() > 0 && ! (GSS.get().getTreeView().getSelection() instanceof TrashResource)) {
728                         files = new ArrayList<FileResource>();
729                         for (FileResource fres : _files)
730                                 if (!fres.isDeleted())
731                                         files.add(fres);
732                 }
733                 else
734                         files = _files;
735                 Collections.sort(files, new Comparator<FileResource>() {
736
737                         @Override
738                         public int compare(FileResource arg0, FileResource arg1) {
739                                 return arg0.getName().compareTo(arg1.getName());
740                         }
741
742                 });
743                 folderFileCount = files.size();
744                 
745                 nameHeader.setSorted(true);
746                 nameHeader.toggleReverseSort();
747                 for (SortableHeader otherHeader : allHeaders) {
748                   if (otherHeader != nameHeader) {
749                     otherHeader.setSorted(false);
750                     otherHeader.setReverseSort(true);
751                   }
752                 }
753                 //
754         }
755
756         
757
758         
759         /**
760          * Does the list contains the requested filename
761          *
762          * @param fileName
763          * @return true/false
764          */
765         public boolean contains(String fileName) {
766                 for (int i = 0; i < files.size(); i++)
767                         if (files.get(i).getName().equals(fileName))
768                                 return true;
769                 return false;
770         }
771
772         public void clearSelectedRows() {
773                 Iterator<FileResource> it = selectionModel.getSelectedSet().iterator();
774                 while(it.hasNext()){
775                         selectionModel.setSelected(it.next(),false);
776                 }
777         }
778         
779
780         /**
781          *
782          */
783         public void selectAllRows() {
784                 Iterator<FileResource> it = provider.getList().iterator();
785                 while(it.hasNext()){
786                         selectionModel.setSelected(it.next(),true);
787                 }
788
789
790         }
791
792         
793         private void sortFiles(final String sortingProperty, final boolean sortingType){
794                 Collections.sort(files, new Comparator<FileResource>() {
795
796             @Override
797             public int compare(FileResource arg0, FileResource arg1) {
798                     AbstractImagePrototype descPrototype = AbstractImagePrototype.create(images.desc());
799                     AbstractImagePrototype ascPrototype = AbstractImagePrototype.create(images.asc());
800                     if (sortingType){
801                             if (sortingProperty.equals("version")) {
802                                     return arg0.getVersion().compareTo(arg1.getVersion());
803                             } else if (sortingProperty.equals("owner")) {
804                                     return arg0.getOwner().compareTo(arg1.getOwner());
805                             } else if (sortingProperty.equals("date")) {
806                                     return arg0.getModificationDate().compareTo(arg1.getModificationDate());
807                             } else if (sortingProperty.equals("size")) {
808                                     return arg0.getContentLength().compareTo(arg1.getContentLength());
809                             } else if (sortingProperty.equals("name")) {
810                                     return arg0.getName().compareTo(arg1.getName());
811                             } else if (sortingProperty.equals("path")) {
812                                     return arg0.getUri().compareTo(arg1.getUri());
813                             } else {
814                                     return arg0.getName().compareTo(arg1.getName());
815                             }
816                     }
817                     else if (sortingProperty.equals("version")) {
818                             
819                             return arg1.getVersion().compareTo(arg0.getVersion());
820                     } else if (sortingProperty.equals("owner")) {
821                             
822                             return arg1.getOwner().compareTo(arg0.getOwner());
823                     } else if (sortingProperty.equals("date")) {
824                             
825                             return arg1.getModificationDate().compareTo(arg0.getModificationDate());
826                     } else if (sortingProperty.equals("size")) {
827                             
828                             return arg1.getContentLength().compareTo(arg0.getContentLength());
829                     } else if (sortingProperty.equals("name")) {
830                             
831                             return arg1.getName().compareTo(arg0.getName());
832                     } else if (sortingProperty.equals("path")) {
833                             
834                             return arg1.getUri().compareTo(arg0.getUri());
835                     } else {
836                             
837                             return arg1.getName().compareTo(arg0.getName());
838                     }
839             }
840
841                 });
842         }
843         
844         final class FileValueUpdater implements ValueUpdater<String>{
845                 private String property;
846                 private SortableHeader header;
847                 /**
848                  * 
849                  */
850                 public FileValueUpdater(SortableHeader header,String property) {
851                         this.property=property;
852                         this.header=header;
853                 }
854                 @Override
855                 public void update(String value) {
856                         header.setSorted(true);
857                         header.toggleReverseSort();
858
859                 for (SortableHeader otherHeader : allHeaders) {
860                   if (otherHeader != header) {
861                     otherHeader.setSorted(false);
862                     otherHeader.setReverseSort(true);
863                   }
864                 }
865                 celltable.redrawHeaders();
866                 sortFiles(property, header.getReverseSort());
867                 FileList.this.update(true);                     
868                 }
869                 
870         }
871         /**
872          * Creates a new ArrayList<FileResources> from the given files ArrayList 
873          * in order that the input files remain untouched 
874          * and continues to find user's full names of each FileResource element
875          * in the new ArrayList
876          *    
877          * @param filesInput
878          */
879         private void copyListAndContinue(List<FileResource> filesInput){
880                 List<FileResource> copiedFiles = new ArrayList<FileResource>();         
881                 for(FileResource file : filesInput) {
882                         copiedFiles.add(file);
883                 }
884                 handleFullNames(copiedFiles);
885         }
886         
887         /**
888          * Examines whether or not the user's full name exists in the 
889          * userFullNameMap in the GSS.java for every element of the input list.
890          * If the user's full name does not exist in the map then a command is being made.  
891          * 
892          * @param filesInput
893          */
894         private void handleFullNames(List<FileResource> filesInput){            
895                 if(filesInput.size() == 0){
896                         showCellTable();
897                         return;
898                 }               
899
900                 if(GSS.get().findUserFullName(filesInput.get(0).getOwner()) == null){
901                         findFullNameAndUpdate(filesInput);              
902                         return;
903                 }
904                                 
905                 if(filesInput.size() >= 1){
906                         filesInput.remove(filesInput.get(0));
907                         if(filesInput.isEmpty()){
908                                 showCellTable();                                
909                         }else{
910                                 handleFullNames(filesInput);
911                         }
912                 }               
913         }
914         
915         /**
916          * Makes a command to search for full name from a given username. 
917          * Only after the completion of the command the celltable is shown
918          * or the search for the next full name continues.
919          *  
920          * @param filesInput
921          */
922         private void findFullNameAndUpdate(final List<FileResource> filesInput){                
923                 String aUserName = filesInput.get(0).getOwner();
924                 String path = GSS.get().getApiPath() + "users/" + aUserName; 
925
926                 GetCommand<UserSearchResource> gg = new GetCommand<UserSearchResource>(UserSearchResource.class, path, false,null) {
927                         @Override
928                         public void onComplete() {
929                                 final UserSearchResource result = getResult();
930                                 for (UserResource user : result.getUsers()){
931                                         String username = user.getUsername();
932                                         String userFullName = user.getName();
933                                         GSS.get().putUserToMap(username, userFullName);
934                                         if(filesInput.size() >= 1){
935                                                 filesInput.remove(filesInput.get(0));
936                                                 if(filesInput.isEmpty()){
937                                                         showCellTable();
938                                                 }else{
939                                                         handleFullNames(filesInput);
940                                                 }                                                                                               
941                                         }                                                                       
942                                 }
943                         }
944                         @Override
945                         public void onError(Throwable t) {
946                                 GWT.log("", t);
947                                 GSS.get().displayError("Unable to fetch user's full name from the given username " + filesInput.get(0).getOwner());
948                                 if(filesInput.size() >= 1){
949                                         filesInput.remove(filesInput.get(0));
950                                         handleFullNames(filesInput);                                    
951                                 }
952                         }
953                 };
954                 DeferredCommand.addCommand(gg);
955         
956         }
957         /**
958          * Shows the files in the cellTable 
959          */
960
961         private void showCellTable(){
962                 if(files.size()>GSS.VISIBLE_FILE_COUNT){
963                         pagerBottom.setVisible(true);
964                         pagerTop.setVisible(true);
965                 }
966                 else{
967                         pagerTop.setVisible(false);
968                         pagerBottom.setVisible(false);
969                 }
970                 RestResource selectedItem = GSS.get().getTreeView().getSelection();
971                 boolean uploadVisible = !(selectedItem != null && (selectedItem instanceof TrashResource || selectedItem instanceof TrashFolderResource || selectedItem instanceof SharedResource || selectedItem instanceof OthersResource || selectedItem instanceof OtherUserResource));
972                 uploadButtonBottom.setVisible(uploadVisible&&files.size()>=GSS.VISIBLE_FILE_COUNT);
973                 uploadButtonTop.setVisible(uploadVisible&&files.size()>=GSS.VISIBLE_FILE_COUNT);
974                 provider.setList(files);
975                 
976                 provider.refresh();
977                 
978                 //celltable.redraw();
979                 celltable.redrawHeaders();              
980         }
981
982         
983 }