source: trunk/www/views/itemlists/index.jsp @ 6770

Last change on this file since 6770 was 6770, checked in by Nicklas Nordborg, 8 years ago

References #1325: Lists of items

Re-factored the syn with filter implementation. Each item list can now have multiple "Synchronization filters". This is now it's own item (Item.SYNCFILTER) which is a child item to item an item list.

Each filter have settings for the relation to the type of items it filters on (eg. parent or child items).

The ListableChildItems and ListableParentItems annotations was added to make it possible to annotate a class which parent and child item types it can navigate to.

The GUI has been updated to make it possible to create and specify filters for a list, but all synchonrization code has been temporarily removed since it no longer works.

File size: 17.8 KB
Line 
1<%-- $Id$
2  ------------------------------------------------------------------
3  Copyright (C) 2015 Nicklas Nordborg
4
5  This file is part of BASE - BioArray Software Environment.
6  Available at http://base.thep.lu.se/
7
8  BASE is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License
10  as published by the Free Software Foundation; either version 3
11  of the License, or (at your option) any later version.
12
13  BASE is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  GNU General Public License for more details.
17
18  You should have received a copy of the GNU General Public License
19  along with BASE. If not, see <http://www.gnu.org/licenses/>.
20  ------------------------------------------------------------------
21
22  @author Nicklas
23--%>
24<%@ page pageEncoding="UTF-8" session="false"
25  import="net.sf.basedb.core.SessionControl"
26  import="net.sf.basedb.core.DbControl"
27  import="net.sf.basedb.core.Item"
28  import="net.sf.basedb.core.Type"
29  import="net.sf.basedb.core.Include"
30  import="net.sf.basedb.core.ItemList"
31  import="net.sf.basedb.core.RawDataTypes"
32  import="net.sf.basedb.core.ItemSubtype"
33  import="net.sf.basedb.core.ItemQuery"
34  import="net.sf.basedb.core.Permission"
35  import="net.sf.basedb.core.ItemContext"
36  import="net.sf.basedb.core.SyncFilter"
37  import="net.sf.basedb.core.SyncFilter.SourceItemTransform"
38  import="net.sf.basedb.core.ItemResultIterator"
39  import="net.sf.basedb.core.ItemQuery"
40  import="net.sf.basedb.core.MultiPermissions"
41  import="net.sf.basedb.core.OwnedItem"
42  import="net.sf.basedb.core.Listable"
43  import="net.sf.basedb.core.PermissionDeniedException"
44  import="net.sf.basedb.core.ItemAlreadyExistsException"
45  import="net.sf.basedb.core.query.Restrictions"
46  import="net.sf.basedb.core.query.Hql"
47  import="net.sf.basedb.core.query.Expressions"
48  import="net.sf.basedb.util.RemovableUtil"
49  import="net.sf.basedb.util.ShareableUtil"
50  import="net.sf.basedb.util.OwnableUtil"
51  import="net.sf.basedb.util.collections.CollectionTransformer"
52  import="net.sf.basedb.util.biomaterial.ListUtil"
53  import="net.sf.basedb.clients.web.Base"
54  import="net.sf.basedb.clients.web.WebException"
55  import="net.sf.basedb.util.Values"
56  import="net.sf.basedb.clients.web.util.HTML"
57  import="net.sf.basedb.core.plugin.GuiContext"
58  import="net.sf.basedb.util.extensions.ExtensionsInvoker"
59  import="net.sf.basedb.clients.web.extensions.ExtensionsControl"
60  import="net.sf.basedb.clients.web.extensions.JspContext"
61  import="net.sf.basedb.clients.web.extensions.edit.EditUtil"
62  import="net.sf.basedb.clients.web.extensions.edit.OnSaveRenderer"
63  import="net.sf.basedb.clients.web.extensions.list.ListColumnExportRenderer"
64  import="net.sf.basedb.clients.web.extensions.list.ListColumnUtil"
65  import="java.util.Enumeration"
66  import="java.util.Set"
67  import="java.util.HashSet"
68  import="java.util.List"
69  import="java.util.ArrayList"
70  import="java.util.Collections"
71  import="java.util.Arrays"
72%>
73<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
74<%!
75  private static final ItemContext defaultContext = Base.createDefaultContext("name", "name,memberType,size,description");
76  private static final Item itemType = Item.ITEMLIST;
77%>
78<%
79final SessionControl sc = Base.getExistingSessionControl(pageContext, true);
80final String ID = sc.getId();
81final String cmd = request.getParameter("cmd");
82final String root = request.getContextPath()+"/";
83final String mode = request.getParameter("mode");
84final String callback = request.getParameter("callback");
85final String itemId = request.getParameter("item_id");
86final String listPage = "list_lists.jsp?ID="+ID
87  +(mode == null ? "" : "&mode="+mode)
88  +(callback == null ? "" : "&callback="+callback)
89  +(itemId == null ? "" : "&item_id="+itemId);
90final String viewPage = "view_list.jsp?ID="+ID;
91final String editPage = "edit_list.jsp?ID="+ID;
92
93String forward = null;
94String redirect = null;
95String message = null;
96DbControl dc = null;
97
98try
99{
100  if (cmd == null || "List".equals(cmd))
101  {
102    // Display the list page without updatinging the current context
103    Base.getAndSetCurrentContext(sc, itemType, null, defaultContext, true);
104    redirect = listPage;
105  }
106  else if ("UpdateContext".equals(cmd))
107  {
108    // Display the list page after updating the current context from the request parameters
109    Base.getAndSetCurrentContext(sc, itemType, pageContext, defaultContext);
110    redirect = listPage;
111  }
112  else if ("LoadContext".equals(cmd))
113  {
114    // Display the list page after loading a saved context
115    int contextId = Values.getInt(request.getParameter("context"));
116    Base.loadContext(sc, contextId, defaultContext);
117    redirect = listPage;
118  }
119
120  else if ("ViewItem".equals(cmd))
121  {
122    // Display the view page for a single item
123    ItemContext cc = Base.getAndSetCurrentContext(sc, itemType, pageContext, defaultContext);
124    forward = viewPage;
125  }
126  else if ("EditItem".equals(cmd))
127  {
128    // Display the edit page for a single item (should be opened in a popup)
129    ItemContext cc = Base.getAndSetCurrentContext(sc, itemType, pageContext, defaultContext);
130    redirect = editPage;
131  }
132  else if ("NewItem".equals(cmd))
133  {
134    // Display the edit page for a new item (should be opened in a popup)
135    if (!sc.hasPermission(Permission.CREATE, itemType))
136    {
137      throw new PermissionDeniedException(Permission.CREATE, itemType.toString());
138    }
139    ItemContext cc = Base.getAndSetCurrentContext(sc, itemType, pageContext, defaultContext);
140    cc.setId(0);
141    forward = editPage;
142  }
143  else if ("UpdateItem".equals(cmd))
144  {
145    // Update the properties on an item (will close the popup)
146    ItemContext cc = Base.getAndSetCurrentContext(sc, itemType, null, defaultContext);
147    dc = sc.newDbControl();
148    ItemList list = (ItemList)cc.getObject("item");
149    if (list == null)
150    {
151      Item memberType = Item.valueOf(request.getParameter("memberType"));
152      list = ItemList.getNew(dc, memberType);
153      dc.saveItem(list);
154      message = "List created";
155    }
156    else
157    {
158      dc.reattachItem(list, false);
159      message = "List updated";
160    }
161    JspContext jspContext = ExtensionsControl.createContext(dc, pageContext, GuiContext.item(Item.ITEMLIST), list);
162    ExtensionsInvoker invoker = EditUtil.useOnSaveExtensions(jspContext);
163    try
164    {
165      list.setName(Values.getStringOrNull(request.getParameter("name")));
166      list.setExternalId(Values.getStringOrNull(request.getParameter("external_id")));
167      list.setDescription(Values.getStringOrNull(request.getParameter("description")));
168      if (list.getMemberType() == Item.RAWBIOASSAY)
169      {
170        list.setRawDataType(RawDataTypes.getRawDataType(request.getParameter("rawdatatype")));
171      }
172      else
173      {
174        int subtypeId = Values.getInt(request.getParameter("subtype_id"), -1);
175        ItemSubtype subtype = null;
176        if (subtypeId >= 0) // < 0 = denied or unchanged
177        {
178          if (subtypeId > 0) subtype = ItemSubtype.getById(dc, subtypeId);
179          list.setItemSubtype(subtype);
180        }
181      }
182
183      // Annotations tab
184      Base.updateAnnotations(dc, list, list, request);
185
186      if (!list.isInDatabase())
187      {
188        // Add individual items from selected from a list page
189        String source = request.getParameter("source");
190        if (source != null)
191        {
192          String subContext = Values.getString(request.getParameter("subContext"), "");
193          boolean useSyncFilter = false;
194          ItemContext filterContext = sc.getCurrentContext(list.getMemberType(), subContext);
195          ItemQuery<? extends Listable> query = (ItemQuery<? extends Listable>)filterContext.getQuery();
196          if ("all".equals(source))
197          {
198            useSyncFilter = Values.getBoolean(request.getParameter("syncFilter"));
199            query.setFirstResult(0);
200            query.setMaxResults(-1);
201            if (useSyncFilter)
202            {
203              SyncFilter sf = list.newSyncFilter(dc);
204              sf.setName("Origin");
205              sf.setSyncContext(filterContext, SourceItemTransform.NONE);
206              dc.saveItem(sf);
207            }
208          }
209          else if ("selected".equals(source))
210          {
211            query.setFirstResult(0);
212            query.setMaxResults(-1);
213            Integer[] itemIds = Values.getInt(request.getParameter("items").split(","));
214            query.restrict(
215              Restrictions.in(
216                Hql.property("id"),
217                Expressions.parameter("selectedItems")
218              )
219            );
220            query.setParameter("selectedItems", Arrays.asList(itemIds), Type.INT);     
221          }
222          // else -- no modifications to the query mean that we only get the current page
223         
224          if (!useSyncFilter) list.add(query.iterate(dc));
225        }
226       
227        message = "List created with " + list.getSize() + " item(s)";
228      }
229
230     
231      // OnSave extensions
232      invoker.render(OnSaveRenderer.ON_SAVE);
233      dc.commit();
234      invoker.render(OnSaveRenderer.ON_COMMIT);
235    }
236    catch (Exception ex)
237    {
238      invoker.render(OnSaveRenderer.onRollback(ex));
239      throw ex;
240    }
241    finally
242    {
243      cc.removeObject("item");
244    }
245  }
246  /*
247  else if ("ReSyncFilter".equals(cmd))
248  {
249    dc = sc.newDbControl();
250    ItemList list = ItemList.getById(dc, Values.getInt(itemId));
251    list.resyncFilter(dc, ItemList.SynchronizeOption.FULL);
252    dc.commit();
253    forward = viewPage;
254  }
255  */
256  else if ("DeleteItem".equals(cmd))
257  {
258    // Delete a single item and then return to the view page
259    dc = sc.newDbControl();
260    ItemContext cc = Base.getAndSetCurrentContext(sc, itemType, pageContext, defaultContext);
261    RemovableUtil.setRemoved(dc, itemType, Collections.singleton(cc.getId()), true);
262    dc.commit();
263    redirect = viewPage;
264  }
265  else if ("DeleteItems".equals(cmd))
266  {
267    // Delete all selected items on the list page
268    dc = sc.newDbControl();
269    ItemContext cc = Base.getAndSetCurrentContext(sc, itemType, pageContext, defaultContext);
270    int numTotal = cc.getSelected().size();
271    int numRemoved = RemovableUtil.setRemoved(dc, itemType, cc.getSelected(), true);
272    dc.commit();
273    if (numTotal != numRemoved)
274    {
275      message = (numRemoved == 0 ? "No" : "Only "+numRemoved+" of "+numTotal) + " items could be deleted, because you have no DELETE permission";
276    }
277    redirect = listPage;
278  }
279  else if ("RestoreItem".equals(cmd))
280  {
281    // Restore a single item and then return to the view page
282    dc = sc.newDbControl();
283    ItemContext cc = Base.getAndSetCurrentContext(sc, itemType, pageContext, defaultContext);
284    RemovableUtil.setRemoved(dc, itemType, Collections.singleton(cc.getId()), false);
285    dc.commit();
286    redirect = viewPage;
287  }
288  else if ("RestoreItems".equals(cmd))
289  {
290    // Restore all selected items on the list page
291    dc = sc.newDbControl();
292    ItemContext cc = Base.getAndSetCurrentContext(sc, itemType, pageContext, defaultContext);
293    int numTotal = cc.getSelected().size();
294    int numRemoved = RemovableUtil.setRemoved(dc, itemType, cc.getSelected(), false);
295    dc.commit();
296    if (numTotal != numRemoved)
297    {
298      message = (numRemoved == 0 ? "No" : "Only "+numRemoved+" of "+numTotal) + " items could be restored, because you have no WRITE permission";
299    }
300    redirect = listPage;
301  }
302  else if ("ShareItem".equals(cmd))
303  {
304    // Display a popup window for sharing a single item
305    dc = sc.newDbControl();
306    ItemContext cc = Base.getAndSetCurrentContext(sc, itemType, pageContext, defaultContext);
307    MultiPermissions permissions = ShareableUtil.getMultiPermissions(dc, itemType, Collections.singleton(cc.getId()));
308    dc.close();
309    cc.setObject("MultiPermissions", permissions);
310    redirect = "../../common/share/share.jsp?ID="+ID+"&item_type="+itemType.name();
311  }
312  else if ("ShareItems".equals(cmd))
313  {
314    // Display a popup window for sharing all selected items on the list page
315    dc = sc.newDbControl();
316    ItemContext cc = Base.getAndSetCurrentContext(sc, itemType, pageContext, defaultContext);
317    MultiPermissions permissions = ShareableUtil.getMultiPermissions(dc, itemType, cc.getSelected());
318    dc.close();
319    cc.setObject("MultiPermissions", permissions);
320    redirect = "../../common/share/share.jsp?ID="+ID+"&item_type="+itemType.name();
321  }
322  else if ("SetOwnerOfItem".equals(cmd))
323  {
324    // Change owner of items selected on a list page
325    dc = sc.newDbControl();
326    ItemContext cc = Base.getAndSetCurrentContext(sc, itemType, pageContext, defaultContext);
327    OwnedItem item = (OwnedItem)itemType.getById(dc, cc.getId());
328    cc.setObject("OwnedItems", Collections.singleton(item));
329    redirect = "../../common/ownership/ownership.jsp?ID="+ID+"&item_type="+itemType.name();
330  }
331  else if ("SetOwnerOfItems".equals(cmd))
332  {
333    // Change owner of items selected on a list page
334    dc = sc.newDbControl();
335    ItemContext cc = Base.getAndSetCurrentContext(sc, itemType, pageContext, defaultContext);
336    Set<OwnedItem> items = new HashSet<OwnedItem>();
337    for (Integer id : cc.getSelected())
338    {
339      if (id != null) items.add((OwnedItem)itemType.getById(dc, id));
340    }
341    dc.close();
342    cc.setObject("OwnedItems", items);
343    redirect = "../../common/ownership/ownership.jsp?ID="+ID+"&item_type="+itemType.name();
344  }
345  else if ("ExportItems".equals(cmd))
346  {
347    // Run an export plugin in a list context
348    ItemContext cc = Base.getAndSetCurrentContext(sc, itemType, pageContext, defaultContext);
349    final ItemQuery<ItemList> query = ItemList.getQuery();
350    dc = sc.newDbControl();
351    cc.configureQuery(dc, query, true);
352    dc.close();
353    cc.setQuery(query);
354    redirect = "../../common/export/index.jsp?ID="+ID+"&cmd=SelectPlugin&item_type="+itemType.name()+"&context_type=LIST&title=Export+item+lists";
355  }
356  else if ("ExportItem".equals(cmd))
357  {
358    // Run an export plugin in single-item context
359    ItemContext cc = Base.getAndSetCurrentContext(sc, itemType, pageContext, defaultContext);
360    redirect = "../../common/export/index.jsp?ID="+ID+"&cmd=SelectPlugin&item_type="+itemType.name()+"&context_type=ITEM&title=Export+item+list";
361  }
362  else if ("ImportItems".equals(cmd))
363  {
364    // Run an import plugin in a list context
365    ItemContext cc = Base.getAndSetCurrentContext(sc, itemType, pageContext, defaultContext);
366    final ItemQuery<ItemList> query = ItemList.getQuery();
367    dc = sc.newDbControl();
368    cc.configureQuery(dc, query, true);
369    cc.setQuery(query);
370    JspContext jspContext = ExtensionsControl.createContext(dc, pageContext, GuiContext.list(itemType), null);
371    ExtensionsInvoker listInvoker = ListColumnUtil.useExtensions(jspContext);
372    listInvoker.render(new ListColumnExportRenderer(cc));
373    dc.close();
374    redirect = "../../common/import/index.jsp?ID="+ID+"&cmd=SelectPlugin&item_type="+itemType.name()+"&context_type=LIST&title=Import+item+lists";
375  }
376  else if ("ImportItem".equals(cmd))
377  {
378    // Run an import plugin in single-item context
379    ItemContext cc = Base.getAndSetCurrentContext(sc, itemType, pageContext, defaultContext);
380    redirect = "../../common/import/index.jsp?ID="+ID+"&cmd=SelectPlugin&item_type="+itemType.name()+"&context_type=ITEM&title=Import+item+list";
381  }
382  else if ("RunListPlugin".equals(cmd))
383  {
384    // Run another plugin in a list context
385    ItemContext cc = Base.getAndSetCurrentContext(sc, itemType, pageContext, defaultContext);
386    final ItemQuery<ItemList> query = ItemList.getQuery();
387    dc = sc.newDbControl();
388    cc.configureQuery(dc, query, true);
389    dc.close();
390    cc.setQuery(query);
391    redirect = "../../common/plugin/index.jsp?ID="+ID+"&cmd=SelectPlugin&item_type="+itemType.name()+"&context_type=LIST&main_type=OTHER&title=Run+plugin";
392  }
393  else if ("RunPlugin".equals(cmd))
394  {
395    // Run another plugin in single-item context
396    ItemContext cc = Base.getAndSetCurrentContext(sc, itemType, pageContext, defaultContext);
397    redirect = "../../common/plugin/index.jsp?ID="+ID+"&cmd=SelectPlugin&item_type="+itemType.name()+"&context_type=ITEM&main_type=OTHER&title=Run+plugin";
398  }
399  else if ("MergeItem".equals(cmd))
400  {
401    ItemContext cc = Base.getAndSetCurrentContext(sc, itemType, null, defaultContext);
402    dc = sc.newDbControl();
403    ItemList itemList = (ItemList)cc.getObject("item");
404    dc.reattachItem(itemList, false);
405   
406    String mergeType = request.getParameter("mergeType");
407    String sourceMerge = request.getParameter("sourceMerge");
408   
409    String[] sourceListIds = Values.getString(request.getParameter("+ITEMLIST")).split(",");
410    List<ItemList> sourceLists = new ArrayList<ItemList>(sourceListIds.length);
411    for (int i = 0; i < sourceListIds.length; ++i)
412    {
413      int listId = Values.getInt(sourceListIds[i], -1);
414      if (listId != -1) sourceLists.add(ItemList.getById(dc, listId));
415    }
416   
417    int numAdded = 0;
418    int numRemoved = 0;
419    if ("union".equals(mergeType))
420    {
421      if ("union".equals(sourceMerge))
422      {
423        numAdded = itemList.addUnion(sourceLists);
424      }
425      else if ("intersection".equals(sourceMerge))
426      {
427        numAdded = itemList.addIntersection(sourceLists);
428      }
429      message = numAdded + " items added to this list";
430    }
431    else if ("intersection".equals(mergeType))
432    {
433      if ("union".equals(sourceMerge))
434      {
435        numRemoved = itemList.retainUnion(sourceLists);
436      }
437      else if ("intersection".equals(sourceMerge))
438      {
439        numRemoved = itemList.retainIntersection(sourceLists);
440      }
441      message = numRemoved + " items removed from this list";
442    }
443    else if ("complement".equals(mergeType))
444    {
445      if ("union".equals(sourceMerge))
446      {
447        numRemoved = itemList.removeUnion(sourceLists);
448      }
449      else if ("intersection".equals(sourceMerge))
450      {
451        numRemoved = itemList.removeIntersection(sourceLists);
452      }
453      message = numRemoved + " items removed from this list";
454    }
455    dc.commit();
456  } 
457  else
458  {
459    throw new WebException("popup", "Invalid command", "The command {1} is not recognised as a valid command.", cmd);
460  }
461}
462finally
463{
464  if (dc != null) dc.close();
465}
466
467if (forward != null)
468{
469  sc.setSessionSetting("alert-message", message);
470  pageContext.forward(forward);
471}
472else if (redirect != null)
473{
474  sc.setSessionSetting("alert-message", message);
475  response.sendRedirect(redirect);
476}
477else if (message == null)
478{
479  response.sendRedirect(root + "common/close_popup.jsp?refresh_opener=1&wait=0");
480}
481else
482{
483  response.sendRedirect(root + "common/close_popup.jsp?refresh_opener=1&message="+HTML.urlEncode(message));
484}
485%>
486
Note: See TracBrowser for help on using the repository browser.