2 * Copyright 2011-2012 GRNET S.A. All rights reserved.
4 * Redistribution and use in source and binary forms, with or
5 * without modification, are permitted provided that the following
8 * 1. Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the following
12 * 2. Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
30 * The views and conclusions contained in the software and
31 * documentation are those of the authors and should not be
32 * interpreted as representing official policies, either expressed
33 * or implied, of GRNET S.A.
36 package gr.grnet.pithos.web.client.othersharedtree;
38 import com.google.gwt.cell.client.AbstractCell;
39 import com.google.gwt.cell.client.Cell;
40 import com.google.gwt.cell.client.TextCell;
41 import com.google.gwt.cell.client.ValueUpdater;
42 import com.google.gwt.core.client.GWT;
43 import com.google.gwt.core.client.Scheduler;
44 import com.google.gwt.event.dom.client.ContextMenuEvent;
45 import com.google.gwt.http.client.Request;
46 import com.google.gwt.http.client.Response;
47 import com.google.gwt.http.client.URL;
48 import com.google.gwt.safehtml.shared.SafeHtml;
49 import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
50 import com.google.gwt.text.shared.SafeHtmlRenderer;
51 import com.google.gwt.user.client.Command;
52 import com.google.gwt.user.client.ui.AbstractImagePrototype;
53 import com.google.gwt.view.client.ListDataProvider;
54 import com.google.gwt.view.client.SingleSelectionModel;
55 import com.google.gwt.view.client.TreeViewModel;
56 import gr.grnet.pithos.web.client.FolderContextMenu;
57 import gr.grnet.pithos.web.client.Pithos;
58 import gr.grnet.pithos.web.client.SharingUsers;
59 import gr.grnet.pithos.web.client.catalog.UpdateUserCatalogs;
60 import gr.grnet.pithos.web.client.catalog.UserCatalogs;
61 import gr.grnet.pithos.web.client.foldertree.AccountResource;
62 import gr.grnet.pithos.web.client.foldertree.Folder;
63 import gr.grnet.pithos.web.client.othersharedtree.OtherSharedTreeView.Templates;
64 import gr.grnet.pithos.web.client.rest.GetRequest;
65 import gr.grnet.pithos.web.client.rest.RestException;
67 import java.util.HashMap;
68 import java.util.Iterator;
69 import java.util.List;
72 public class OtherSharedTreeViewModel implements TreeViewModel {
76 final String dummy = "No shares by others yet";
78 private Cell<Folder> folderCell = new AbstractCell<Folder>(ContextMenuEvent.getType().getName()) {
81 public void render(Context context, Folder folder, SafeHtmlBuilder safeHtmlBuilder) {
82 String html = AbstractImagePrototype.create(OtherSharedTreeView.images.folderYellow()).getHTML();
83 safeHtmlBuilder.appendHtmlConstant(html).appendHtmlConstant(" ");
84 safeHtmlBuilder.append(Templates.INSTANCE.nameSpan(folder.getName()));
88 public void onBrowserEvent(Context context, com.google.gwt.dom.client.Element parent, final Folder folder, com.google.gwt.dom.client.NativeEvent event, ValueUpdater<Folder> valueUpdater) {
89 if(event.getType().equals(ContextMenuEvent.getType().getName())) {
90 final int x = event.getClientX();
91 final int y = event.getClientY();
92 OtherSharedTreeViewModel.this.selectionModel.setSelected(folder, true);
93 app.scheduleFolderHeadCommand(folder, new Command() {
96 public void execute() {
97 FolderContextMenu menu = new FolderContextMenu(app, OtherSharedTreeView.images, app.getSelectedTree(), folder);
98 menu.setPopupPosition(x, y);
106 protected ListDataProvider<String> userLevelDataProviderForIDs = new ListDataProvider<String>();
107 // protected ListDataProvider<String> userLevelDataProviderForDisplayNames = new ListDataProvider<String>();
109 protected Map<String, ListDataProvider<Folder>> userDataProviderMap = new HashMap<String, ListDataProvider<Folder>>();
110 private Map<Folder, ListDataProvider<Folder>> dataProviderMap = new HashMap<Folder, ListDataProvider<Folder>>();
112 protected SingleSelectionModel<Folder> selectionModel;
114 public OtherSharedTreeViewModel(Pithos _app, SingleSelectionModel<Folder> selectionModel) {
116 this.selectionModel = selectionModel;
120 public <T> NodeInfo<?> getNodeInfo(T value) {
122 // LOG("getNodeInfo(null), calling fetchSharingUsers(null)");
123 fetchSharingUsers(null);
124 // LOG("getNodeInfo(null), called fetchSharingUsers(null)");
125 return new DefaultNodeInfo<String>(userLevelDataProviderForIDs, new TextCell(new SafeHtmlRenderer<String>() {
127 public SafeHtml render(String object) {
128 final String displayName = app.getDisplayNameForUserID(object);
129 // LOG("render(userID = "+object+"), displayName = " + displayName);
130 SafeHtmlBuilder builder = new SafeHtmlBuilder();
131 render(displayName, builder);
132 return builder.toSafeHtml();
136 public void render(String object, SafeHtmlBuilder builder) {
137 if(!object.equals(dummy)) {
138 // LOG("render(userID [not dummy] = "+object+")");
139 String html = AbstractImagePrototype.create(OtherSharedTreeView.images.myShared()).getHTML();
140 builder.appendHtmlConstant(html).appendHtmlConstant(" ");
142 final String displayName = app.getDisplayNameForUserID(object);
143 builder.append(OtherSharedTreeView.Templates.INSTANCE.nameSpan(object));
147 else if(value instanceof String) {
148 // LOG("getNodeInfo(String "+value+"), called with userID");
149 final String userID = (String) value;
151 if(userDataProviderMap.get(userID) == null) {
152 userDataProviderMap.put(userID, new ListDataProvider<Folder>());
154 final ListDataProvider<Folder> userIDDataProvider = userDataProviderMap.get(userID);
155 fetchSharedContainers(userID, userIDDataProvider, null);
157 return new DefaultNodeInfo<Folder>(userIDDataProvider, folderCell, selectionModel, null);
160 // LOG("getNodeInfo(Folder "+value+"), called with a folder");
161 final Folder f = (Folder) value;
162 if(dataProviderMap.get(f) == null) {
163 dataProviderMap.put(f, new ListDataProvider<Folder>());
165 final ListDataProvider<Folder> dataProvider = dataProviderMap.get(f);
166 fetchFolder(f, dataProvider, false, null);
167 return new DefaultNodeInfo<Folder>(dataProvider, folderCell, selectionModel, null);
171 // native void LOG(String message) /*-{
172 // console.log(message );
175 private void fetchSharingUsers(final Command callback) {
176 GetRequest<SharingUsers> getSharingUsers = new GetRequest<SharingUsers>(SharingUsers.class, app.getApiPath(), "", "?format=json") {
178 public void onSuccess(final SharingUsers _result) {
179 userLevelDataProviderForIDs.getList().clear();
181 final List<String> userIDs = _result.getUserIDs();
182 // for(String userID : userIDs) {
183 // LOG("fetchSharingUsers(): userID =" + userID);
185 final List<String> userIDsWithUnknownDisplayNames = app.filterUserIDsWithUnknownDisplayName(userIDs);
186 // for(String userID : userIDsWithUnknownDisplayNames) {
187 // LOG("fetchSharingUsers(): userID (with unknown name) =" + userID);
190 userLevelDataProviderForIDs.getList().addAll(userIDs);
191 if(userLevelDataProviderForIDs.getList().isEmpty()) {
192 userLevelDataProviderForIDs.getList().add(dummy);
193 // userLevelDataProviderForDisplayNames.getList().add(dummy);
195 // userLevelDataProviderForDisplayNames.getList().addAll(app.getUserDisplayNamesForIDs(userIDs));
198 if(userIDsWithUnknownDisplayNames.size() == 0) {
199 // All display names are known, so we proceed directly
200 fetchSharedContainers(userLevelDataProviderForIDs.getList().iterator(), callback);
202 // First fetch unknown display names and then proceed
203 new UpdateUserCatalogs(app, userIDsWithUnknownDisplayNames) {
205 public void onSuccess(UserCatalogs requestedUserCatalogs, UserCatalogs updatedUserCatalogs) {
206 fetchSharedContainers(userLevelDataProviderForIDs.getList().iterator(), callback);
210 public void onError(Request request, Throwable t) {
211 super.onError(request, t);
214 }.scheduleDeferred();
219 public void onError(Throwable t) {
220 GWT.log("Error getting folder", t);
222 if(t instanceof RestException) {
223 app.displayError("Error getting folder: " + ((RestException) t).getHttpStatusText());
226 app.displayError("System error fetching folder: " + t.getMessage());
231 protected void onUnauthorized(Response response) {
232 app.sessionExpired();
235 getSharingUsers.setHeader("X-Auth-Token", app.getUserToken());
236 Scheduler.get().scheduleDeferred(getSharingUsers);
239 protected void fetchSharedContainers(final Iterator<String> userIDsIterator, final Command callback) {
240 if(userIDsIterator.hasNext()) {
241 String userID = userIDsIterator.next();
242 if(userDataProviderMap.get(userID) == null) {
243 userDataProviderMap.put(userID, new ListDataProvider<Folder>());
245 final ListDataProvider<Folder> dataProvider = userDataProviderMap.get(userID);
246 fetchSharedContainers(userID, dataProvider, new Command() {
249 public void execute() {
250 fetchSharedContainers(userIDsIterator, callback);
255 else if(callback != null) {
261 public boolean isLeaf(Object o) {
263 boolean result = userLevelDataProviderForIDs.getList().isEmpty();
264 // LOG("isLeaf(null) ==> " + result);
267 else if(o instanceof Folder) {
268 Folder folder = (Folder) o;
269 boolean result = folder.getSubfolders().isEmpty();
270 // LOG("isLeaf(Folder "+folder+") ==> " + result);
274 ListDataProvider<Folder> dp = userDataProviderMap.get(o);
276 boolean result = dp.getList().isEmpty();
277 // LOG("isLeaf("+o.getClass().getName()+" "+o+") ==> " + result);
280 // LOG("isLeaf("+o.getClass().getName()+" "+o+") ==> (true)");
285 private void fetchSharedContainers(final String userID, final ListDataProvider<Folder> dataProvider, final Command callback) {
286 GetRequest<AccountResource> getUserSharedContainers = new GetRequest<AccountResource>(AccountResource.class, app.getApiPath(), userID, "?format=json") {
289 public void onSuccess(AccountResource _result) {
290 final ListDataProvider<Folder> tempProvider = new ListDataProvider<Folder>();
291 Iterator<Folder> folderIterator = _result.getContainers().iterator();
292 fetchFolder(userID, folderIterator, tempProvider, new Command() {
295 public void execute() {
296 dataProvider.getList().clear();
297 dataProvider.getList().addAll(tempProvider.getList());
298 if(callback != null) {
306 public void onError(Throwable t) {
307 GWT.log("Error getting account", t);
309 if(t instanceof RestException) {
310 app.displayError("Error getting account: " + ((RestException) t).getHttpStatusText());
313 app.displayError("System error fetching user data: " + t.getMessage());
318 protected void onUnauthorized(Response response) {
319 app.sessionExpired();
322 getUserSharedContainers.setHeader("X-Auth-Token", app.getUserToken());
323 Scheduler.get().scheduleDeferred(getUserSharedContainers);
326 protected void fetchFolder(final String userID, final Iterator<Folder> folderIterator, final ListDataProvider<Folder> dataProvider, final Command callback) {
327 if(folderIterator.hasNext()) {
328 final Folder f = folderIterator.next();
330 String path = "/" + f.getContainer() + "?format=json&delimiter=/&prefix=" + URL.encodeQueryString(f.getPrefix());
331 GetRequest<Folder> getFolder = new GetRequest<Folder>(Folder.class, app.getApiPath(), userID, path, f) {
333 public void onSuccess(Folder _result) {
334 dataProvider.getList().add(_result);
335 fetchFolder(userID, folderIterator, dataProvider, callback);
339 public void onError(Throwable t) {
340 GWT.log("Error getting folder", t);
342 if(t instanceof RestException) {
343 app.displayError("Error getting folder: " + ((RestException) t).getHttpStatusText());
346 app.displayError("System error fetching folder: " + t.getMessage());
351 protected void onUnauthorized(Response response) {
352 app.sessionExpired();
355 getFolder.setHeader("X-Auth-Token", app.getUserToken());
356 Scheduler.get().scheduleDeferred(getFolder);
358 else if(callback != null) {
363 public Folder getSelection() {
364 return selectionModel.getSelectedObject();
367 public void updateFolder(Folder folder, boolean showfiles, Command callback) {
368 if(dataProviderMap.get(folder) == null) {
369 dataProviderMap.put(folder, new ListDataProvider<Folder>());
371 final ListDataProvider<Folder> dataProvider = dataProviderMap.get(folder);
372 fetchFolder(folder, dataProvider, showfiles, callback);
375 public void fetchFolder(final Folder f, final ListDataProvider<Folder> dataProvider, final boolean showfiles, final Command callback) {
376 String path = "/" + f.getContainer() + "?format=json&delimiter=/&prefix=" + URL.encodeQueryString(f.getPrefix());
377 GetRequest<Folder> getFolder = new GetRequest<Folder>(Folder.class, app.getApiPath(), f.getOwnerID(), path, f) {
379 public void onSuccess(final Folder _result) {
381 app.showFiles(_result);
383 Iterator<Folder> iter = _result.getSubfolders().iterator();
384 fetchFolder(_result.getOwnerID(), iter, dataProvider, new Command() {
386 public void execute() {
387 dataProvider.getList().clear();
388 dataProvider.getList().addAll(_result.getSubfolders());
389 app.getOtherSharedTreeView().updateChildren(f);
390 if(callback != null) {
398 public void onError(Throwable t) {
399 GWT.log("Error getting folder", t);
401 if(t instanceof RestException) {
402 app.displayError("Error getting folder: " + ((RestException) t).getHttpStatusText());
405 app.displayError("System error fetching folder: " + t.getMessage());
410 protected void onUnauthorized(Response response) {
411 app.sessionExpired();
414 getFolder.setHeader("X-Auth-Token", app.getUserToken());
415 Scheduler.get().scheduleDeferred(getFolder);
418 public void initialize(Command callback) {
419 fetchSharingUsers(callback);