Statistics
| Branch: | Tag: | Revision:

root / src / gr / grnet / pithos / web / client / othersharedtree / OtherSharedTreeViewModel.java @ e6e9f6e6

History | View | Annotate | Download (19.5 kB)

1
/*
2
 * Copyright 2011-2013 GRNET S.A. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or
5
 * without modification, are permitted provided that the following
6
 * conditions are met:
7
 *
8
 *   1. Redistributions of source code must retain the above
9
 *      copyright notice, this list of conditions and the following
10
 *      disclaimer.
11
 *
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.
16
 *
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.
29
 *
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.
34
 */
35

    
36
package gr.grnet.pithos.web.client.othersharedtree;
37

    
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.Const;
57
import gr.grnet.pithos.web.client.FolderContextMenu;
58
import gr.grnet.pithos.web.client.Pithos;
59
import gr.grnet.pithos.web.client.SharingUsers;
60
import gr.grnet.pithos.web.client.catalog.UpdateUserCatalogs;
61
import gr.grnet.pithos.web.client.catalog.UserCatalogs;
62
import gr.grnet.pithos.web.client.foldertree.AccountResource;
63
import gr.grnet.pithos.web.client.foldertree.Folder;
64
import gr.grnet.pithos.web.client.othersharedtree.OtherSharedTreeView.Templates;
65
import gr.grnet.pithos.web.client.rest.GetRequest;
66
import gr.grnet.pithos.web.client.rest.RestException;
67

    
68
import java.util.HashMap;
69
import java.util.Iterator;
70
import java.util.List;
71
import java.util.Map;
72

    
73
public class OtherSharedTreeViewModel implements TreeViewModel {
74

    
75
    protected Pithos app;
76

    
77
    final String dummy = "No shares by others yet";
78

    
79
    private Cell<Folder> folderCell = new AbstractCell<Folder>(ContextMenuEvent.getType().getName()) {
80

    
81
        @Override
82
        public void render(Context context, Folder folder, SafeHtmlBuilder safeHtmlBuilder) {
83
//            app.LOG("OtherSharedTreeViewModel::render(), folder=", folder);
84
            String html = AbstractImagePrototype.create(OtherSharedTreeView.images.folderYellow()).getHTML();
85
            safeHtmlBuilder.appendHtmlConstant(html).appendHtmlConstant("&nbsp;");
86
            safeHtmlBuilder.append(Templates.INSTANCE.nameSpan(folder.getName()));
87
        }
88

    
89
        @Override
90
        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) {
91
            app.LOG("OtherSharedTreeViewModel::render(), folder=", folder, ", parent=", parent.getString());
92
            if(event.getType().equals(ContextMenuEvent.getType().getName())) {
93
                final int x = event.getClientX();
94
                final int y = event.getClientY();
95
                OtherSharedTreeViewModel.this.selectionModel.setSelected(folder, true);
96
                app.scheduleFolderHeadCommand(folder, new Command() {
97

    
98
                    @Override
99
                    public void execute() {
100
                        FolderContextMenu menu = new FolderContextMenu(app, OtherSharedTreeView.images, app.getSelectedTree(), folder);
101
                        menu.setPopupPosition(x, y);
102
                        menu.show();
103
                    }
104
                });
105
            }
106
        }
107
    };
108

    
109
    protected ListDataProvider<String> userLevelDataProviderForIDs = new ListDataProvider<String>();
110

    
111
    protected Map<String, ListDataProvider<Folder>> userDataProviderMap = new HashMap<String, ListDataProvider<Folder>>();
112
    private Map<Folder, ListDataProvider<Folder>> dataProviderMap = new HashMap<Folder, ListDataProvider<Folder>>();
113

    
114
    protected SingleSelectionModel<Folder> selectionModel;
115

    
116
    public OtherSharedTreeViewModel(Pithos _app, SingleSelectionModel<Folder> selectionModel) {
117
        app = _app;
118
        this.selectionModel = selectionModel;
119
    }
120

    
121
    @Override
122
    public <T> NodeInfo<?> getNodeInfo(T value) {
123
        if(value == null) {
124
            app.LOG("OtherSharedTreeViewModel::getNodeInfo(null), calling fetchSharingUsers(null)");
125
            fetchSharingUsers(null);
126
            app.LOG("OtherSharedTreeViewModel::getNodeInfo(null), called fetchSharingUsers(null)");
127
            return new DefaultNodeInfo<String>(userLevelDataProviderForIDs, new TextCell(new SafeHtmlRenderer<String>() {
128
                @Override
129
                public SafeHtml render(String object) {
130
                    final String displayName = app.getDisplayNameForUserID(object);
131
                    app.LOG("OtherSharedTreeViewModel::(getNodeInfo)render(String ", object, "), parameter is userID, displayName=", displayName);
132
                    SafeHtmlBuilder builder = new SafeHtmlBuilder();
133
                    render(displayName, builder);
134
                    return builder.toSafeHtml();
135
                }
136

    
137
                @Override
138
                public void render(String object, SafeHtmlBuilder builder) {
139
                    if(!object.equals(dummy)) {
140
                        app.LOG("OtherSharedTreeViewModel::(getNodeInfo)render(String ", object, ") parameter is not [dummy]");
141
                        String html = AbstractImagePrototype.create(OtherSharedTreeView.images.myShared()).getHTML();
142
                        builder.appendHtmlConstant(html).appendHtmlConstant("&nbsp;");
143
                    }
144
                    builder.append(OtherSharedTreeView.Templates.INSTANCE.nameSpan(object));
145
                }
146
            }), null, null);
147
        }
148
        else if(value instanceof String) {
149
            app.LOG("OtherSharedTreeViewModel::getNodeInfo(String ", value, "), parameter is userID");
150
            final String userID = (String) value;
151

    
152
            if(userDataProviderMap.get(userID) == null) {
153
                userDataProviderMap.put(userID, new ListDataProvider<Folder>());
154
            }
155
            final ListDataProvider<Folder> userIDDataProvider = userDataProviderMap.get(userID);
156
            fetchSharedContainers(userID, userIDDataProvider, null);
157

    
158
            return new DefaultNodeInfo<Folder>(userIDDataProvider, folderCell, selectionModel, null);
159
        }
160
        else {
161
            app.LOG("OtherSharedTreeViewModel::getNodeInfo(Folder ", value, ")");
162
            final Folder f = (Folder) value;
163
            if(dataProviderMap.get(f) == null) {
164
                dataProviderMap.put(f, new ListDataProvider<Folder>());
165
            }
166
            final ListDataProvider<Folder> dataProvider = dataProviderMap.get(f);
167
            fetchFolder(f, dataProvider, false, null);
168
            return new DefaultNodeInfo<Folder>(dataProvider, folderCell, selectionModel, null);
169
        }
170
    }
171

    
172
    private void fetchSharingUsers(final Command callback) {
173
        app.LOG("OtherSharedTreeViewModel::fetchSharingUsers() callback=", callback);
174
        GetRequest<SharingUsers> getSharingUsers = new GetRequest<SharingUsers>(SharingUsers.class, app.getApiPath(), "", "?format=json") {
175
            @Override
176
            public void onSuccess(final SharingUsers _result) {
177
                userLevelDataProviderForIDs.getList().clear();
178

    
179
                final List<String> userIDs = _result.getUserIDs();
180
                for(String userID : userIDs) {
181
                    app.LOG("OtherSharedTreeViewModel::fetchSharingUsers()::onSuccess() Sharing userID=", userID);
182
                }
183
                final List<String> userIDsWithUnknownDisplayNames = app.filterUserIDsWithUnknownDisplayName(userIDs);
184
//                for(String userID : userIDsWithUnknownDisplayNames) {
185
//                    app.LOG("OtherSharedTreeViewModel::fetchSharingUsers(): userID (with unknown name) =" + userID);
186
//                }
187

    
188
                userLevelDataProviderForIDs.getList().addAll(userIDs);
189
                if(userLevelDataProviderForIDs.getList().isEmpty()) {
190
                    userLevelDataProviderForIDs.getList().add(dummy);
191
                    app.LOG("OtherSharedTreeViewModel::fetchSharingUsers()::onSuccess() NO sharing users, adding [dummy]=\"", dummy, "\"");
192
                    return; // Only the dummy node is present, nothing to fetch from the server
193
                }
194

    
195
                if(userIDsWithUnknownDisplayNames.size() == 0) {
196
                    // All display names are known, so we proceed directly
197
                    fetchSharedContainers(userLevelDataProviderForIDs.getList().iterator(), callback);
198
                } else {
199
                    // First fetch unknown display names and then proceed
200
                    new UpdateUserCatalogs(app, userIDsWithUnknownDisplayNames) {
201
                        @Override
202
                        public void onSuccess(UserCatalogs requestedUserCatalogs, UserCatalogs updatedUserCatalogs) {
203
                            fetchSharedContainers(userLevelDataProviderForIDs.getList().iterator(), callback);
204
                        }
205

    
206
                        @Override
207
                        public void onError(Request request, Throwable t) {
208
                            super.onError(request, t);
209
                            app.setError(t);
210
                        }
211
                    }.scheduleDeferred();
212
                }
213
            }
214

    
215
            @Override
216
            public void onError(Throwable t) {
217
                GWT.log("Error getting folder", t);
218
                app.setError(t);
219
                if(t instanceof RestException) {
220
                    app.displayError("Error getting folder: " + ((RestException) t).getHttpStatusText());
221
                }
222
                else {
223
                    app.displayError("System error fetching folder: " + t.getMessage());
224
                }
225
            }
226

    
227
            @Override
228
            protected void onUnauthorized(Response response) {
229
                app.sessionExpired();
230
            }
231
        };
232
        getSharingUsers.setHeader(Const.X_AUTH_TOKEN, app.getUserToken());
233
        Scheduler.get().scheduleDeferred(getSharingUsers);
234
    }
235

    
236
    protected void fetchSharedContainers(final Iterator<String> userIDsIterator, final Command callback) {
237
        app.LOG("OtherSharedTreeViewModel::fetchSharedContainers(), userIDsIterator=", userIDsIterator.hasNext(), ", callback=", callback);
238
        if(userIDsIterator.hasNext()) {
239
            String userID = userIDsIterator.next();
240
            if(userDataProviderMap.get(userID) == null) {
241
                userDataProviderMap.put(userID, new ListDataProvider<Folder>());
242
            }
243
            final ListDataProvider<Folder> dataProvider = userDataProviderMap.get(userID);
244
            fetchSharedContainers(userID, dataProvider, new Command() {
245

    
246
                @Override
247
                public void execute() {
248
                    fetchSharedContainers(userIDsIterator, callback);
249

    
250
                }
251
            });
252
        }
253
        else if(callback != null) {
254
            callback.execute();
255
        }
256
    }
257

    
258
    @Override
259
    public boolean isLeaf(Object o) {
260
        if(o == null) {
261
            boolean result =  userLevelDataProviderForIDs.getList().isEmpty();
262
//            app.LOG("isLeaf(null) ==> " + result);
263
            return result;
264
        }
265
        else if(o instanceof Folder) {
266
            Folder folder = (Folder) o;
267
            boolean result = folder.getSubfolders().isEmpty();
268
//            app.LOG("isLeaf(Folder "+folder+") ==> " + result);
269
            return result;
270
        }
271
        else {
272
            ListDataProvider<Folder> dp = userDataProviderMap.get(o);
273
            if(dp != null) {
274
                boolean result =  dp.getList().isEmpty();
275
//                app.LOG("isLeaf("+o.getClass().getName()+" "+o+") ==> " + result);
276
                return result;
277
            }
278
//            app.LOG("isLeaf("+o.getClass().getName()+" "+o+") ==> (true)");
279
            return true;
280
        }
281
    }
282

    
283
    private void fetchSharedContainers(final String userID, final ListDataProvider<Folder> dataProvider, final Command callback) {
284
        app.LOG("OtherSharedTreeViewModel::fetchSharedContainers(), userID=", userID, ", callback=", callback);
285
        GetRequest<AccountResource> getUserSharedContainers = new GetRequest<AccountResource>(AccountResource.class, app.getApiPath(), userID, "?format=json") {
286

    
287
            @Override
288
            public void onSuccess(AccountResource _result) {
289
                final ListDataProvider<Folder> tempProvider = new ListDataProvider<Folder>();
290
                Iterator<Folder> folderIterator = _result.getContainers().iterator();
291
                fetchFolder(userID, folderIterator, tempProvider, new Command() {
292

    
293
                    @Override
294
                    public void execute() {
295
                        dataProvider.getList().clear();
296
                        dataProvider.getList().addAll(tempProvider.getList());
297
                        if(callback != null) {
298
                            callback.execute();
299
                        }
300
                    }
301
                });
302
            }
303

    
304
            @Override
305
            public void onError(Throwable t) {
306
                GWT.log("Error getting account", t);
307
                app.setError(t);
308
                if(t instanceof RestException) {
309
                    app.displayError("Error getting account: " + ((RestException) t).getHttpStatusText());
310
                }
311
                else {
312
                    app.displayError("System error fetching user data: " + t.getMessage());
313
                }
314
            }
315

    
316
            @Override
317
            protected void onUnauthorized(Response response) {
318
                app.sessionExpired();
319
            }
320
        };
321
        getUserSharedContainers.setHeader(Const.X_AUTH_TOKEN, app.getUserToken());
322
        Scheduler.get().scheduleDeferred(getUserSharedContainers);
323
    }
324

    
325
    protected void fetchFolder(final String userID, final Iterator<Folder> folderIterator, final ListDataProvider<Folder> dataProvider, final Command callback) {
326
        app.LOG("OtherSharedTreeViewModel::fetchFolder(), userID=", userID, " folderIterator=", folderIterator.hasNext(), ", callback=", callback);
327
        if(folderIterator.hasNext()) {
328
            final Folder f = folderIterator.next();
329

    
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) {
332
                @Override
333
                public void onSuccess(Folder _result) {
334
                    dataProvider.getList().add(_result);
335
                    fetchFolder(userID, folderIterator, dataProvider, callback);
336
                }
337

    
338
                @Override
339
                public void onError(Throwable t) {
340
                    GWT.log("Error getting folder", t);
341
                    app.setError(t);
342
                    if(t instanceof RestException) {
343
                        app.displayError("Error getting folder: " + ((RestException) t).getHttpStatusText());
344
                    }
345
                    else {
346
                        app.displayError("System error fetching folder: " + t.getMessage());
347
                    }
348
                }
349

    
350
                @Override
351
                protected void onUnauthorized(Response response) {
352
                    app.sessionExpired();
353
                }
354
            };
355
            getFolder.setHeader(Const.X_AUTH_TOKEN, app.getUserToken());
356
            Scheduler.get().scheduleDeferred(getFolder);
357
        }
358
        else if(callback != null) {
359
            callback.execute();
360
        }
361
    }
362

    
363
    public Folder getSelection() {
364
        return selectionModel.getSelectedObject();
365
    }
366

    
367
    public void updateFolder(Folder folder, boolean showfiles, Command callback) {
368
        app.LOG("OtherSharedTreeViewModel::updateFolder(), folder=", folder, ", showfiles=", showfiles, ", callback=", callback);
369
        if(dataProviderMap.get(folder) == null) {
370
            dataProviderMap.put(folder, new ListDataProvider<Folder>());
371
        }
372
        final ListDataProvider<Folder> dataProvider = dataProviderMap.get(folder);
373
        fetchFolder(folder, dataProvider, showfiles, callback);
374
    }
375

    
376
    public void fetchFolder(final Folder f, final ListDataProvider<Folder> dataProvider, final boolean showfiles, final Command callback) {
377
        app.LOG("OtherSharedTreeViewModel::fetchFolder(), folder=", f, ", showfiles=", showfiles, ", callback=", callback);
378
        String path = "/" + f.getContainer() + "?format=json&delimiter=/&prefix=" + URL.encodeQueryString(f.getPrefix());
379
        GetRequest<Folder> getFolder = new GetRequest<Folder>(Folder.class, app.getApiPath(), f.getOwnerID(), path, f) {
380
            @Override
381
            public void onSuccess(final Folder _result) {
382
                if(showfiles) {
383
                    app.showFiles(_result);
384
                }
385
                Iterator<Folder> iter = _result.getSubfolders().iterator();
386
                fetchFolder(_result.getOwnerID(), iter, dataProvider, new Command() {
387
                    @Override
388
                    public void execute() {
389
                        dataProvider.getList().clear();
390
                        dataProvider.getList().addAll(_result.getSubfolders());
391
                        app.getOtherSharedTreeView().updateChildren(f);
392
                        if(callback != null) {
393
                            callback.execute();
394
                        }
395
                    }
396
                });
397
            }
398

    
399
            @Override
400
            public void onError(Throwable t) {
401
                GWT.log("Error getting folder", t);
402
                app.setError(t);
403
                if(t instanceof RestException) {
404
                    app.displayError("Error getting folder: " + ((RestException) t).getHttpStatusText());
405
                }
406
                else {
407
                    app.displayError("System error fetching folder: " + t.getMessage());
408
                }
409
            }
410

    
411
            @Override
412
            protected void onUnauthorized(Response response) {
413
                app.sessionExpired();
414
            }
415
        };
416
        getFolder.setHeader(Const.X_AUTH_TOKEN, app.getUserToken());
417
        Scheduler.get().scheduleDeferred(getFolder);
418
    }
419

    
420
    public void initialize(Command callback) {
421
        app.LOG("OtherSharedTreeViewModel::initialize(), callback=", callback);
422
        fetchSharingUsers(callback);
423
    }
424
}