Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (18.5 kB)

1
/*
2
 * Copyright 2011-2012 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.json.client.JSONObject;
49
import com.google.gwt.safehtml.shared.SafeHtml;
50
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
51
import com.google.gwt.text.shared.SafeHtmlRenderer;
52
import com.google.gwt.user.client.Command;
53
import com.google.gwt.user.client.ui.AbstractImagePrototype;
54
import com.google.gwt.view.client.ListDataProvider;
55
import com.google.gwt.view.client.SingleSelectionModel;
56
import com.google.gwt.view.client.TreeViewModel;
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.GetUserCatalogs;
61
import gr.grnet.pithos.web.client.catalog.UpdateUserCatalogs;
62
import gr.grnet.pithos.web.client.catalog.UserCatalogs;
63
import gr.grnet.pithos.web.client.foldertree.AccountResource;
64
import gr.grnet.pithos.web.client.foldertree.Folder;
65
import gr.grnet.pithos.web.client.othersharedtree.OtherSharedTreeView.Templates;
66
import gr.grnet.pithos.web.client.rest.GetRequest;
67
import gr.grnet.pithos.web.client.rest.RestException;
68

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

    
74
public class OtherSharedTreeViewModel implements TreeViewModel {
75

    
76
    protected Pithos app;
77

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

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

    
82
        @Override
83
        public void render(Context context, Folder folder, SafeHtmlBuilder safeHtmlBuilder) {
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
            if(event.getType().equals(ContextMenuEvent.getType().getName())) {
92
                final int x = event.getClientX();
93
                final int y = event.getClientY();
94
                OtherSharedTreeViewModel.this.selectionModel.setSelected(folder, true);
95
                app.scheduleFolderHeadCommand(folder, new Command() {
96

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

    
108
    protected ListDataProvider<String> userLevelDataProviderForIDs = new ListDataProvider<String>();
109
//    protected ListDataProvider<String> userLevelDataProviderForDisplayNames = 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
//            LOG("getNodeInfo(null), calling fetchSharingUsers(null)");
125
            fetchSharingUsers(null);
126
//            LOG("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.getUserDisplayNameForID(object);
131
//                    LOG("render(userID = "+object+"), 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
//                        LOG("render(userID [not dummy] = "+object+")");
141
                        String html = AbstractImagePrototype.create(OtherSharedTreeView.images.myShared()).getHTML();
142
                        builder.appendHtmlConstant(html).appendHtmlConstant("&nbsp;");
143
                    }
144
                    final String displayName = app.getUserDisplayNameForID(object);
145
                    builder.append(OtherSharedTreeView.Templates.INSTANCE.nameSpan(object));
146
                }
147
            }), null, null);
148
        }
149
        else if(value instanceof String) {
150
//            LOG("getNodeInfo(String "+value+"), called with userID");
151
            final String userID = (String) value;
152

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

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

    
173
//    native void LOG(String message) /*-{
174
//      console.log(message );
175
//    }-*/;
176

    
177
    private void fetchSharingUsers(final Command callback) {
178
        GetRequest<SharingUsers> getSharingUsers = new GetRequest<SharingUsers>(SharingUsers.class, app.getApiPath(), "", "?format=json") {
179
            @Override
180
            public void onSuccess(final SharingUsers _result) {
181
                userLevelDataProviderForIDs.getList().clear();
182

    
183
                final List<String> userIDs = _result.getUserIDs();
184
//                for(String userID : userIDs) {
185
//                    LOG("fetchSharingUsers(): userID =" + userID);
186
//                }
187
                final List<String> userIDsWithUnknownDisplayNames = app.filterUserIDsWithUnknownDisplayName(userIDs);
188
//                for(String userID : userIDsWithUnknownDisplayNames) {
189
//                    LOG("fetchSharingUsers(): userID (with unknown name) =" + userID);
190
//                }
191

    
192
                userLevelDataProviderForIDs.getList().addAll(userIDs);
193
                if(userLevelDataProviderForIDs.getList().isEmpty()) {
194
                    userLevelDataProviderForIDs.getList().add(dummy);
195
//                    userLevelDataProviderForDisplayNames.getList().add(dummy);
196
                } else {
197
//                    userLevelDataProviderForDisplayNames.getList().addAll(app.getUserDisplayNamesForIDs(userIDs));
198
                }
199

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

    
211
                        @Override
212
                        public void onError(Request request, Throwable t) {
213
                            super.onError(request, t);
214
                            app.setError(t);
215
                        }
216
                    }.scheduleDeferred();
217
                }
218
            }
219

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

    
232
            @Override
233
            protected void onUnauthorized(Response response) {
234
                app.sessionExpired();
235
            }
236
        };
237
        getSharingUsers.setHeader("X-Auth-Token", app.getUserToken());
238
        Scheduler.get().scheduleDeferred(getSharingUsers);
239
    }
240

    
241
    protected void fetchSharedContainers(final Iterator<String> userIDsIterator, final Command callback) {
242
        if(userIDsIterator.hasNext()) {
243
            String userID = userIDsIterator.next();
244
            if(userDataProviderMap.get(userID) == null) {
245
                userDataProviderMap.put(userID, new ListDataProvider<Folder>());
246
            }
247
            final ListDataProvider<Folder> dataProvider = userDataProviderMap.get(userID);
248
            fetchSharedContainers(userID, dataProvider, new Command() {
249

    
250
                @Override
251
                public void execute() {
252
                    fetchSharedContainers(userIDsIterator, callback);
253

    
254
                }
255
            });
256
        }
257
        else if(callback != null) {
258
            callback.execute();
259
        }
260
    }
261

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

    
287
    private void fetchSharedContainers(final String userID, final ListDataProvider<Folder> dataProvider, final Command callback) {
288
        GetRequest<AccountResource> getUserSharedContainers = new GetRequest<AccountResource>(AccountResource.class, app.getApiPath(), userID, "?format=json") {
289

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

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

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

    
319
            @Override
320
            protected void onUnauthorized(Response response) {
321
                app.sessionExpired();
322
            }
323
        };
324
        getUserSharedContainers.setHeader("X-Auth-Token", app.getUserToken());
325
        Scheduler.get().scheduleDeferred(getUserSharedContainers);
326
    }
327

    
328
    protected void fetchFolder(final String userID, final Iterator<Folder> folderIterator, final ListDataProvider<Folder> dataProvider, final Command callback) {
329
        if(folderIterator.hasNext()) {
330
            final Folder f = folderIterator.next();
331

    
332
            String path = "/" + f.getContainer() + "?format=json&delimiter=/&prefix=" + URL.encodeQueryString(f.getPrefix());
333
            GetRequest<Folder> getFolder = new GetRequest<Folder>(Folder.class, app.getApiPath(), userID, path, f) {
334
                @Override
335
                public void onSuccess(Folder _result) {
336
                    dataProvider.getList().add(_result);
337
                    fetchFolder(userID, folderIterator, dataProvider, callback);
338
                }
339

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

    
352
                @Override
353
                protected void onUnauthorized(Response response) {
354
                    app.sessionExpired();
355
                }
356
            };
357
            getFolder.setHeader("X-Auth-Token", app.getUserToken());
358
            Scheduler.get().scheduleDeferred(getFolder);
359
        }
360
        else if(callback != null) {
361
            callback.execute();
362
        }
363
    }
364

    
365
    public Folder getSelection() {
366
        return selectionModel.getSelectedObject();
367
    }
368

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

    
377
    public void fetchFolder(final Folder f, final ListDataProvider<Folder> dataProvider, final boolean showfiles, final Command 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("X-Auth-Token", app.getUserToken());
417
        Scheduler.get().scheduleDeferred(getFolder);
418
    }
419

    
420
    public void initialize(Command callback) {
421
        fetchSharingUsers(callback);
422
    }
423
}