source: trunk/www/common/annotations/list_annotations.jsp @ 7206

Last change on this file since 7206 was 7206, checked in by Nicklas Nordborg, 6 years ago

References #2033: Permissions for annotating items may be incorrectly implemented

Changes in the web interface (Annotations tab) so that the "edit" icon is only visible if the user has permission to modify or create an annotation.

The edit dialog will still list all annotations but editing is disabled for read-only annotations.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Id
File size: 18.7 KB
Line 
1<%-- $Id: list_annotations.jsp 7206 2016-10-19 08:25:47Z nicklas $
2  ------------------------------------------------------------------
3  Copyright (C) 2006 Jari Häkkinen, Nicklas Nordborg, Martin Svensson
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  @version 2.0
24--%>
25<%@page import="java.util.Collections"%>
26<%@page import="net.sf.basedb.util.units.UnitConverter"%>
27<%@ page pageEncoding="UTF-8" session="false"
28  import="net.sf.basedb.core.SessionControl"
29  import="net.sf.basedb.core.DbControl"
30  import="net.sf.basedb.core.Item"
31  import="net.sf.basedb.core.Permission"
32  import="net.sf.basedb.core.AnnotationType"
33  import="net.sf.basedb.core.Protocol"
34  import="net.sf.basedb.core.AnnotationSet"
35  import="net.sf.basedb.core.Annotation"
36  import="net.sf.basedb.core.Annotatable"
37  import="net.sf.basedb.core.AnnotatableProxy"
38  import="net.sf.basedb.core.Unit"
39  import="net.sf.basedb.core.Nameable"
40  import="net.sf.basedb.core.Subtypable"
41  import="net.sf.basedb.core.ItemSubtype"
42  import="net.sf.basedb.core.BioPlate"
43  import="net.sf.basedb.core.BioPlateType"
44  import="net.sf.basedb.core.ItemQuery"
45  import="net.sf.basedb.core.ItemResultList"
46  import="net.sf.basedb.core.Include"
47  import="net.sf.basedb.core.PermissionDeniedException"
48  import="net.sf.basedb.core.query.Orders"
49  import="net.sf.basedb.core.query.Hql"
50  import="net.sf.basedb.core.query.Restrictions"
51  import="net.sf.basedb.core.query.Expressions"
52  import="net.sf.basedb.core.snapshot.AnnotationSetSnapshot"
53  import="net.sf.basedb.core.snapshot.AnnotationSnapshot"
54  import="net.sf.basedb.core.snapshot.SnapshotManager"
55  import="net.sf.basedb.clients.web.Base"
56  import="net.sf.basedb.clients.web.util.HTML"
57  import="net.sf.basedb.util.NameableComparator"
58  import="net.sf.basedb.util.formatter.Formatter"
59  import="net.sf.basedb.util.formatter.PrefixSuffixFormatter"
60  import="net.sf.basedb.clients.web.formatter.FormatterFactory"
61  import="net.sf.basedb.util.Values"
62  import="java.util.ArrayList"
63  import="java.util.List"
64  import="java.util.Set"
65  import="java.util.HashSet"
66  import="java.util.TreeSet"
67  import="java.util.Map"
68  import="java.util.HashMap"
69  import="java.util.Date"
70%>
71<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
72<%@ taglib prefix="tbl" uri="/WEB-INF/table.tld" %>
73
74<%
75final SessionControl sc = Base.getExistingSessionControl(pageContext, true);
76final String ID = sc.getId();
77final Item itemType = Item.valueOf(request.getParameter("item_type"));
78final int itemId = Values.getInt(request.getParameter("item_id"));
79final float scale = Base.getScale(sc);
80final DbControl dc = sc.newDbControl();
81
82Set<AnnotationType> annotationTypes = null;
83Set<AnnotationType> protocolParameters = null;
84Map<AnnotationType, AnnotationSnapshot> existing = null;
85
86try
87{
88  final Annotatable item = (Annotatable)itemType.getById(dc, itemId);
89  final boolean writePermission = item.hasPermission(Permission.WRITE);
90  final SnapshotManager manager = new SnapshotManager();
91 
92  ItemQuery<AnnotationType> annotationTypeQuery = null;
93  String message = null;
94  boolean isProxy = item instanceof AnnotatableProxy;
95
96  // Load all annotation types that are possible for this item type
97  if (isProxy)
98  {
99    AnnotatableProxy proxy = (AnnotatableProxy)item;
100    annotationTypeQuery = Base.getAnnotationTypesQuery(proxy);
101    message = proxy.getAnnotationMessage();
102  }
103  else
104  {
105    annotationTypeQuery = Base.getAnnotationTypesQuery(itemType, false);
106  }
107  annotationTypes = new TreeSet<AnnotationType>(new NameableComparator(false));
108  annotationTypes.addAll(annotationTypeQuery.list(dc));
109
110  final AnnotationSetSnapshot snapshot = item.isAnnotated() ? 
111      manager.getSnapshot(dc, item.getAnnotationSet().getId()) : null;
112  List<AnnotationSnapshot> inheritedAnnotations = null;
113  if (snapshot != null)
114  {
115    // Load the existing primary and inherited annotations
116    existing = new HashMap<AnnotationType, AnnotationSnapshot>();
117    inheritedAnnotations = new ArrayList<AnnotationSnapshot>();
118    for (AnnotationSnapshot a : manager.findAnnotations(dc, snapshot, null, true))
119    {
120      AnnotationType at = a.getAnnotationType(dc);
121      if (a.getSource() == Annotation.Source.PRIMARY)
122      {
123        existing.put(a.getAnnotationType(dc), a);
124      }
125      else
126      {
127        inheritedAnnotations.add(a);
128      }
129    }
130    Collections.sort(inheritedAnnotations, AnnotationSnapshot.sortByAnnotationType(dc));
131    annotationTypes.addAll(existing.keySet());
132  }
133 
134  // Load the possible protocol parameters
135  Protocol protocol = null;
136  boolean readProtocol = true;
137  try
138  {
139    protocol = item.getProtocol();
140  }
141  catch (PermissionDeniedException ex)
142  {
143    readProtocol = false;
144  }
145  ItemQuery<AnnotationType> parameterQuery = Base.getProtocolParametersQuery(protocol);
146  if (parameterQuery != null)
147  {
148    protocolParameters = new HashSet<AnnotationType>(parameterQuery.list(dc));
149    annotationTypes.removeAll(protocolParameters);
150  }
151  // Load the current subtype
152  // NOTE! User may have selected a different subtype in the form than what is
153  // currently saved so if a subtype_id is sent in the request we use that
154  String selectedCategoryName = null;
155  try
156  {
157    ItemSubtype subtype = null;
158    if (item instanceof Subtypable)
159    {
160      subtype = ((Subtypable)item).getItemSubtype();
161    }
162    else if (item instanceof BioPlate)
163    {
164      BioPlateType bpt = ((BioPlate)item).getBioPlateType();
165      subtype = bpt.getItemSubtype();
166      if (subtype == null) selectedCategoryName = bpt.getName();
167    }
168    if (subtype != null) selectedCategoryName = subtype.getName();
169  }
170  catch (PermissionDeniedException ex)
171  {}
172  Set<AnnotationType> annotationTypesInCategory = new HashSet<AnnotationType>();
173  if (selectedCategoryName != null)
174  {
175    ItemQuery<AnnotationType> query = AnnotationType.getQuery(item.getType());
176    query.setIncludes(Include.ALL);
177    query.join(Hql.innerJoin("categories", "ct"));
178    query.restrict(Restrictions.eq(Hql.property("ct", "name"), Expressions.string(selectedCategoryName)));
179    annotationTypesInCategory.addAll(query.list(dc));
180  }
181  Formatter<Date> dateTimeFormatter = FormatterFactory.getDateTimeFormatter(sc);
182  %>
183  <base:page type="iframe" id="list-annotations">
184  <base:head scripts="~list.js" styles="table.css">
185  <style>
186    #annotations-data.all
187    {}
188   
189    #annotations-data.values .novalues
190    {
191      display: none;
192    }
193   
194    #annotations-data.category .nocategory
195    {
196      display: none;
197    }
198   
199    .edit-annotation
200    {
201      float: right;
202    }
203  </style>
204  </base:head>
205  <base:body>
206    <%
207    if (message != null)
208    {
209      %>
210      <div class="messagecontainer note"><%=message%></div>
211      <%
212    }
213    %>
214    <base:section
215      id="primaryAnnotations"
216      title="<%="Primary annotations (" + annotationTypes.size() + ")"%>"
217      >
218      <%
219      int allWithValues = 0;
220      int allOfCategory = 0;
221      if (annotationTypes.size() == 0)
222      {
223        %>
224        <div class="messagecontainer note">
225        No annotation types has been defined for this type of item
226        (or you don't have permission to view them).
227        </div>
228        <%
229      }
230      else
231      {
232        %>
233        <tbl:table
234          id="annotations"
235          columns="all"
236          >
237          <tbl:columndef 
238            id="annotation"
239            title="Annotation"
240          />
241          <tbl:columndef 
242            id="values"
243            title="Values"
244          />
245          <tbl:columndef
246            id="lastModified"
247            title="Last modified"
248            formatter="<%=dateTimeFormatter%>"
249          />
250          <tbl:columndef 
251            id="description"
252            title="Description"
253          />
254          <div class="panelgroup topborder leftborder rightborder bg-filled-100">
255            <tbl:panel style="height: auto; padding: 2px;">
256              <b>View:</b> 
257              <%
258              if (selectedCategoryName != null)
259              {
260                %>
261                <label><input type="radio" name="view" id="view_category" value="category" checked>All of <i><%=HTML.encodeTags(selectedCategoryName)%></i> category</label> (<span id="allOfCategory">?</span>)
262                <%
263              }
264              %>
265              <label><input type="radio" name="view" id="view_values" value="values" <%=selectedCategoryName == null ? "checked" : ""%>>All with values</label> (<span id="allWithValues">?</span>)
266              <label><input type="radio" name="view" id="view_all" value="all">All annotations</label> (<%=annotationTypes.size()%>)
267            </tbl:panel>
268          </div>
269          <tbl:data id="annotations-data">
270            <tbl:headers>
271              <tbl:headerrow>
272                <tbl:columnheaders />
273              </tbl:headerrow>
274            </tbl:headers>
275            <tbl:rows>
276            <%
277            for (AnnotationType at : annotationTypes)
278            {
279              // Permission for creating a new annotation
280              boolean annotatePermission = writePermission & at.hasPermission(Permission.USE);
281              AnnotationSnapshot a = existing != null ? existing.get(at) : null;
282              List<?> values = null;
283              Formatter formatter = null;
284              if (a != null)
285              {
286                Annotation ann = a.getThisAnnotation(dc);
287                // Permission on this annotation
288                annotatePermission = ann.hasPermission(Permission.WRITE);
289                values = a.getActualValues(ann.getUnitConverter(null), ann.getValueType());
290                formatter = FormatterFactory.getAnnotationFormatter(sc, ann, null);
291              }
292              if (values != null || !at.isRemoved())
293              {
294                String rowClass = "";
295                if (values == null || values.size() == 0) 
296                {
297                  rowClass += " novalues";
298                }
299                else
300                {
301                  allWithValues++;
302                }
303                if (!annotationTypesInCategory.contains(at)) 
304                {
305                  rowClass += " nocategory";
306                }
307                else
308                {
309                  allOfCategory++;
310                }
311                %>
312                <tbl:row subclass="<%=rowClass%>">
313                  <tbl:cell column="annotation"><base:icon 
314                    image="deleted.png" 
315                    tooltip="This item has been scheduled for deletion" 
316                    visible="<%=at.isRemoved()%>"
317                    /><%=Base.getLinkedName(ID, at, false, true)%></tbl:cell>
318                  <tbl:cell column="values">
319                    <%=values == null || values.size() == 0 ? "<i>- no values -</i>" : Values.getString(values, ", ", true, formatter)%>
320                    <base:icon image="edit.png" subclass="edit-annotation auto-init link" 
321                      data-auto-init="edit-annotation" 
322                      data-annotation="<%=a!=null ? a.getThisAnnotationId() : 0 %>"
323                      data-annotation-type="<%=at.getId()%>"
324                      data-item-type="<%=itemType.name()%>" 
325                      data-item-id="<%=itemId %>"
326                      tooltip="Modify the values of this annotation"
327                      visible="<%=annotatePermission %>"
328                    />
329                  </tbl:cell>
330                  <tbl:cell column="lastModified" value="<%=a == null ? null : a.getThisLastUpdate() %>" />
331                  <tbl:cell column="description"><%=HTML.encodeTags(at.getDescription())%></tbl:cell>
332                </tbl:row>
333                <%
334              }
335            }
336            %>
337            </tbl:rows>
338          </tbl:data>
339        </tbl:table>
340        <%
341      }
342      %>
343      <div id="annotations-stat" class="datacontainer"
344        data-all-with-values="<%=allWithValues %>"
345        data-all-of-category="<%=allOfCategory%>"
346      ></div>
347    </base:section>
348
349    <%
350    if (protocolParameters != null)
351    {
352      %>
353      <base:section 
354        id="parameterSection" 
355        title="<%="Protocol parameters for " + HTML.encodeTags(protocol.getName()) + 
356          " (" + protocolParameters.size() + ")"%>"
357        >
358        <%
359        if (protocolParameters.size() == 0)
360        {
361          %>
362          <div class="messagecontainer note">
363          No protocol parameters has been defined for the protocol
364          <%=Base.getLinkedName(ID, protocol, !readProtocol, true)%> 
365          (or you don't have permission to view them).
366          </div>
367          <%
368        }
369        else
370        {
371          %>
372          <tbl:table
373            id="parameters"
374            columns="all"
375            >
376            <tbl:columndef 
377              id="parameter"
378              title="Parameter"
379            />
380            <tbl:columndef 
381              id="values"
382              title="Values"
383            />
384            <tbl:columndef
385              id="lastModified"
386              title="Last modified"
387              formatter="<%=dateTimeFormatter%>"
388            />
389            <tbl:columndef 
390              id="description"
391              title="Description"
392            />
393            <tbl:data>
394              <tbl:headers>
395                <tbl:headerrow>
396                  <tbl:columnheaders />
397                </tbl:headerrow>
398              </tbl:headers>
399              <tbl:rows>
400              <%
401              for (AnnotationType at : protocolParameters)
402              {
403                // Permission for creating a new annotation
404                boolean annotatePermission = writePermission & at.hasPermission(Permission.USE);
405                AnnotationSnapshot a = existing != null ? existing.get(at) : null;
406                Formatter formatter = null;
407                List<?> values = null;
408                if (a != null)
409                {
410                  Annotation ann = a.getThisAnnotation(dc);
411                  // Permission on this annotation
412                  annotatePermission = ann.hasPermission(Permission.WRITE);
413                  values = a.getActualValues(ann.getUnitConverter(null), ann.getValueType());
414                  formatter = FormatterFactory.getAnnotationFormatter(sc, ann, null);
415                }
416                if (values != null || !at.isRemoved())
417                {
418                  %>
419                  <tbl:row>
420                    <tbl:cell column="parameter"><base:icon 
421                      image="deleted.png" 
422                      tooltip="This item has been scheduled for deletion" 
423                      visible="<%=at.isRemoved()%>"
424                    /><%=Base.getLinkedName(ID, at, false, true)%></tbl:cell>
425                    <tbl:cell column="values">
426                      <%=values == null || values.size() == 0 ? "<i>- no values -</i>" : Values.getString(values, ", ", true, formatter)%>
427                      <base:icon image="edit.png" subclass="edit-annotation auto-init link" 
428                        data-auto-init="edit-annotation" 
429                        data-annotation="<%=a!=null ? a.getThisAnnotationId() : 0 %>"
430                        data-annotation-type="<%=at.getId()%>"
431                        data-item-type="<%=itemType.name()%>" 
432                        data-item-id="<%=itemId %>"
433                        tooltip="Modify the values of this protocol parameter" 
434                        visible="<%=annotatePermission %>"
435                      />
436                    </tbl:cell>
437                    <tbl:cell column="lastModified" value="<%=a == null ? null : a.getThisLastUpdate() %>" />
438                    <tbl:cell column="description"><%=HTML.encodeTags(at.getDescription())%></tbl:cell>
439                  </tbl:row>
440                  <%
441                }
442              }
443              %>
444              </tbl:rows>
445            </tbl:data>
446          </tbl:table>
447          <%
448        }
449        %>
450      </base:section>
451      <%
452    }
453    if (!isProxy)
454    {
455      int numInherited = inheritedAnnotations == null ? 0 : inheritedAnnotations.size();
456      %>
457      <base:section 
458        id="inherited"
459        title="<%="Inherited annotations (" + numInherited + ")"%>"         
460        >
461        <%
462        if (numInherited == 0)
463        {
464          %>
465          <div class="messagecontainer note">
466          No annotations are inherited by this item.
467          (or you don't have permission to view them).
468          </div>
469          <%
470        }
471        else
472        {
473        %>
474        <tbl:table
475          id="inheritedAnnotations"
476          columns="all"
477          >
478          <tbl:columndef 
479            id="annotation"
480            title="Annotation"
481          />
482          <tbl:columndef 
483            id="values"
484            title="Values"
485          />
486          <tbl:columndef 
487            id="item"
488            title="Parent item"
489          />
490          <tbl:columndef 
491            id="note"
492            title="Note"
493          />
494          <tbl:columndef
495            id="lastModified"
496            title="Last modified"
497            formatter="<%=dateTimeFormatter %>"
498          />
499          <tbl:columndef 
500            id="description"
501            title="Description"
502          />
503          <tbl:data>
504            <tbl:headers>
505              <tbl:headerrow>
506                <tbl:columnheaders />
507              </tbl:headerrow>
508            </tbl:headers>
509            <tbl:rows>
510            <%
511            for (AnnotationSnapshot a : inheritedAnnotations)
512            {
513              boolean annotatePermission = a.hasPermission(dc, Permission.WRITE);
514              AnnotationType at = a.getAnnotationType(dc);
515              AnnotationSnapshot from = a.getInheritedFrom();
516             
517              // About this annotation
518              String name = HTML.encodeTags(at.getName());
519              String description = HTML.encodeTags(at.getDescription());
520              Date lastModified = a.getThisLastUpdate();
521              boolean isUpToDate = a.isUpToDate();
522             
523              // Which item are we inheriting from?
524              Nameable fromItem = null;
525              String fromType = null;
526              boolean writeInherited = false;
527              if (from != null)
528              {
529                fromType = from.getThisItemType().toString();
530                if (lastModified == null)
531                {
532                  lastModified = from.getThisLastUpdate();
533                }
534                try
535                {
536                  fromItem = (Nameable)from.getThisItem(dc);
537                  writeInherited = fromItem.hasPermission(Permission.WRITE);
538                  if (fromItem instanceof Subtypable)
539                  {
540                    ItemSubtype subtype = ((Subtypable)fromItem).getItemSubtype();
541                    if (subtype != null) fromType = subtype.getName();
542                  }
543                }
544                catch (PermissionDeniedException ex)
545                {}
546              }
547             
548              // Values, units, etc.
549              Formatter formatter = FormatterFactory.getTypeFormatter(sc, at.getValueType());
550              Unit unit = a.getActualUnit(dc);
551              UnitConverter converter = null;
552              if (unit != null)
553              {
554                converter = unit.getUnitConverter(at.getDefaultUnit());
555                formatter = unit.getFormatter(formatter);
556              }
557              List<?> values = a.getActualValues(converter, at.getValueType());
558              %>
559              <tbl:row>
560                <tbl:cell column="annotation"><%=Base.getLinkedName(ID, at, at == null, true)%></tbl:cell>
561                <tbl:cell column="values">
562                  <%=values == null || values.size() == 0 ? 
563                    "<i>- no values -</i>" : Values.getString(values, ", ", true, formatter)%>
564                  <base:icon image="<%=isUpToDate ? "edit.png" : "edit-outofsync.png"%>" 
565                    subclass="edit-annotation auto-init link" 
566                    data-auto-init="edit-annotation" 
567                    data-annotation="<%= a.getThisAnnotationId()%>"
568                    data-annotation-type="<%=at.getId()%>"
569                    data-item-type="<%=itemType.name()%>" 
570                    data-item-id="<%=itemId %>"
571                    tooltip="Modify the values of this annotation"
572                    visible="<%=annotatePermission %>"
573                  />
574                </tbl:cell>
575                <tbl:cell column="item"><%=from == null ? "<i>- missing -</i>" : Base.getLinkedName(ID, fromItem, fromItem == null, true)%><%=fromItem != null ? " <span class=\"itemsubtype\">("+fromType+")</span>" : ""%></tbl:cell>
576                <tbl:cell column="note"><%=a.getSource() == Annotation.Source.CLONED ? "Cloned" + (isUpToDate ? "; up-to-date" : "; modified") : "" %></tbl:cell>
577                <tbl:cell column="lastModified" value="<%=lastModified %>"></tbl:cell>
578                <tbl:cell column="description"><%=description%></tbl:cell>
579              </tbl:row>
580              <%
581            }
582            %>
583            </tbl:rows>
584          </tbl:data>
585        </tbl:table>
586        <%
587      }
588      %>
589      </base:section>
590     
591      <%
592    }
593    %>
594  </base:body>
595  </base:page>
596  <%
597}
598finally
599{
600  if (dc != null) dc.close();
601}
602
603%>
Note: See TracBrowser for help on using the repository browser.