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

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

References #1941: Store experimental factor values as part experiments

Updated "Item overview" functionality to become compatible with cloned annotations. There may still be some issues with suggested fixes related to inherited annotations since it is not yet clear how those will be managed.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Id
File size: 18.2 KB
Line 
1<%-- $Id: list_annotations.jsp 6939 2015-08-21 12:32:11Z 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              AnnotationSnapshot a = existing != null ? existing.get(at) : null;
280              List<?> values = null;
281              Formatter formatter = null;
282              if (a != null)
283              {
284                Annotation ann = a.getThisAnnotation(dc);
285                values = a.getActualValues(ann.getUnitConverter(null), ann.getValueType());
286                formatter = FormatterFactory.getAnnotationFormatter(sc, ann, null);
287              }
288              if (values != null || !at.isRemoved())
289              {
290                String rowClass = "";
291                if (values == null || values.size() == 0) 
292                {
293                  rowClass += " novalues";
294                }
295                else
296                {
297                  allWithValues++;
298                }
299                if (!annotationTypesInCategory.contains(at)) 
300                {
301                  rowClass += " nocategory";
302                }
303                else
304                {
305                  allOfCategory++;
306                }
307                %>
308                <tbl:row subclass="<%=rowClass%>">
309                  <tbl:cell column="annotation"><base:icon 
310                    image="deleted.png" 
311                    tooltip="This item has been scheduled for deletion" 
312                    visible="<%=at.isRemoved()%>"
313                    /><%=Base.getLinkedName(ID, at, false, true)%></tbl:cell>
314                  <tbl:cell column="values">
315                    <%=values == null || values.size() == 0 ? "<i>- no values -</i>" : Values.getString(values, ", ", true, formatter)%>
316                    <base:icon image="edit.png" subclass="edit-annotation auto-init link" 
317                      data-auto-init="edit-annotation" 
318                      data-annotation="<%=a!=null ? a.getThisAnnotationId() : 0 %>"
319                      data-annotation-type="<%=at.getId()%>"
320                      data-item-type="<%=itemType.name()%>" 
321                      data-item-id="<%=itemId %>"
322                      tooltip="Modify the values of this annotation"
323                      visible="<%=writePermission %>"
324                    />
325                  </tbl:cell>
326                  <tbl:cell column="lastModified" value="<%=a == null ? null : a.getThisLastUpdate() %>" />
327                  <tbl:cell column="description"><%=HTML.encodeTags(at.getDescription())%></tbl:cell>
328                </tbl:row>
329                <%
330              }
331            }
332            %>
333            </tbl:rows>
334          </tbl:data>
335        </tbl:table>
336        <%
337      }
338      %>
339      <div id="annotations-stat" class="datacontainer"
340        data-all-with-values="<%=allWithValues %>"
341        data-all-of-category="<%=allOfCategory%>"
342      ></div>
343    </base:section>
344
345    <%
346    if (protocolParameters != null)
347    {
348      %>
349      <base:section 
350        id="parameterSection" 
351        title="<%="Protocol parameters for " + HTML.encodeTags(protocol.getName()) + 
352          " (" + protocolParameters.size() + ")"%>"
353        >
354        <%
355        if (protocolParameters.size() == 0)
356        {
357          %>
358          <div class="messagecontainer note">
359          No protocol parameters has been defined for the protocol
360          <%=Base.getLinkedName(ID, protocol, !readProtocol, true)%> 
361          (or you don't have permission to view them).
362          </div>
363          <%
364        }
365        else
366        {
367          %>
368          <tbl:table
369            id="parameters"
370            columns="all"
371            >
372            <tbl:columndef 
373              id="parameter"
374              title="Parameter"
375            />
376            <tbl:columndef 
377              id="values"
378              title="Values"
379            />
380            <tbl:columndef
381              id="lastModified"
382              title="Last modified"
383              formatter="<%=dateTimeFormatter%>"
384            />
385            <tbl:columndef 
386              id="description"
387              title="Description"
388            />
389            <tbl:data>
390              <tbl:headers>
391                <tbl:headerrow>
392                  <tbl:columnheaders />
393                </tbl:headerrow>
394              </tbl:headers>
395              <tbl:rows>
396              <%
397              for (AnnotationType at : protocolParameters)
398              {
399                AnnotationSnapshot a = existing != null ? existing.get(at) : null;
400                Formatter formatter = null;
401                List<?> values = null;
402                if (a != null)
403                {
404                  Annotation ann = a.getThisAnnotation(dc);
405                  values = a.getActualValues(ann.getUnitConverter(null), ann.getValueType());
406                  formatter = FormatterFactory.getAnnotationFormatter(sc, ann, null);
407                }
408                if (values != null || !at.isRemoved())
409                {
410                  %>
411                  <tbl:row>
412                    <tbl:cell column="parameter"><base:icon 
413                      image="deleted.png" 
414                      tooltip="This item has been scheduled for deletion" 
415                      visible="<%=at.isRemoved()%>"
416                    /><%=Base.getLinkedName(ID, at, false, true)%></tbl:cell>
417                    <tbl:cell column="values">
418                      <%=values == null || values.size() == 0 ? "<i>- no values -</i>" : Values.getString(values, ", ", true, formatter)%>
419                      <base:icon image="edit.png" subclass="edit-annotation auto-init link" 
420                        data-auto-init="edit-annotation" 
421                          data-annotation="<%=a!=null ? a.getThisAnnotationId() : 0 %>"
422                          data-annotation-type="<%=at.getId()%>"
423                          data-item-type="<%=itemType.name()%>" 
424                          data-item-id="<%=itemId %>"
425                          tooltip="Modify the values of this protocol parameter" 
426                        visible="<%=writePermission %>"
427                      />
428                    </tbl:cell>
429                    <tbl:cell column="lastModified" value="<%=a == null ? null : a.getThisLastUpdate() %>" />
430                    <tbl:cell column="description"><%=HTML.encodeTags(at.getDescription())%></tbl:cell>
431                  </tbl:row>
432                  <%
433                }
434              }
435              %>
436              </tbl:rows>
437            </tbl:data>
438          </tbl:table>
439          <%
440        }
441        %>
442      </base:section>
443      <%
444    }
445    if (!isProxy)
446    {
447      int numInherited = inheritedAnnotations == null ? 0 : inheritedAnnotations.size();
448      %>
449      <base:section 
450        id="inherited"
451        title="<%="Inherited annotations (" + numInherited + ")"%>"         
452        >
453        <%
454        if (numInherited == 0)
455        {
456          %>
457          <div class="messagecontainer note">
458          No annotations are inherited by this item.
459          (or you don't have permission to view them).
460          </div>
461          <%
462        }
463        else
464        {
465        %>
466        <tbl:table
467          id="inheritedAnnotations"
468          columns="all"
469          >
470          <tbl:columndef 
471            id="annotation"
472            title="Annotation"
473          />
474          <tbl:columndef 
475            id="values"
476            title="Values"
477          />
478          <tbl:columndef 
479            id="item"
480            title="Parent item"
481          />
482          <tbl:columndef 
483            id="note"
484            title="Note"
485          />
486          <tbl:columndef
487            id="lastModified"
488            title="Last modified"
489            formatter="<%=dateTimeFormatter %>"
490          />
491          <tbl:columndef 
492            id="description"
493            title="Description"
494          />
495          <tbl:data>
496            <tbl:headers>
497              <tbl:headerrow>
498                <tbl:columnheaders />
499              </tbl:headerrow>
500            </tbl:headers>
501            <tbl:rows>
502            <%
503            for (AnnotationSnapshot a : inheritedAnnotations)
504            {
505              AnnotationType at = a.getAnnotationType(dc);
506              AnnotationSnapshot from = a.getInheritedFrom();
507             
508              // About this annotation
509              String name = HTML.encodeTags(at.getName());
510              String description = HTML.encodeTags(at.getDescription());
511              Date lastModified = a.getThisLastUpdate();
512              boolean isUpToDate = true;
513             
514              // Which item are we inheriting from?
515              Nameable fromItem = null;
516              String fromType = null;
517              boolean writeInherited = false;
518              if (from != null)
519              {
520                fromType = from.getThisItemType().toString();
521                if (lastModified == null)
522                {
523                  lastModified = from.getThisLastUpdate();
524                }
525                else
526                {
527                  isUpToDate = !lastModified.before(from.getThisLastUpdate());
528                }
529                try
530                {
531                  fromItem = (Nameable)from.getThisItem(dc);
532                  writeInherited = fromItem.hasPermission(Permission.WRITE);
533                  if (fromItem instanceof Subtypable)
534                  {
535                    ItemSubtype subtype = ((Subtypable)fromItem).getItemSubtype();
536                    if (subtype != null) fromType = subtype.getName();
537                  }
538                }
539                catch (PermissionDeniedException ex)
540                {}
541              }
542             
543              // Values, units, etc.
544              Formatter formatter = FormatterFactory.getTypeFormatter(sc, at.getValueType());
545              Unit unit = a.getActualUnit(dc);
546              UnitConverter converter = null;
547              if (unit != null)
548              {
549                converter = unit.getUnitConverter(at.getDefaultUnit());
550                formatter = unit.getFormatter(formatter);
551              }
552              List<?> values = a.getActualValues(converter, at.getValueType());
553              %>
554              <tbl:row>
555                <tbl:cell column="annotation"><%=Base.getLinkedName(ID, at, at == null, true)%></tbl:cell>
556                <tbl:cell column="values">
557                  <%=values == null || values.size() == 0 ? 
558                    "<i>- no values -</i>" : Values.getString(values, ", ", true, formatter)%>
559                  <base:icon image="edit.png" subclass="edit-annotation auto-init link" 
560                    data-auto-init="edit-annotation" 
561                    data-annotation="<%= a.getThisAnnotationId()%>"
562                    data-annotation-type="<%=at.getId()%>"
563                    data-item-type="<%=itemType.name()%>" 
564                    data-item-id="<%=itemId %>"
565                    tooltip="Modify the values of this annotation"
566                    visible="<%=writePermission %>"
567                  />
568                </tbl:cell>
569                <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>
570                <tbl:cell column="note"><%=a.getSource() == Annotation.Source.CLONED ? "Cloned" + (isUpToDate ? "; up-to-date" : "; modified") : "" %></tbl:cell>
571                <tbl:cell column="lastModified" value="<%=lastModified %>"></tbl:cell>
572                <tbl:cell column="description"><%=description%></tbl:cell>
573              </tbl:row>
574              <%
575            }
576            %>
577            </tbl:rows>
578          </tbl:data>
579        </tbl:table>
580        <%
581      }
582      %>
583      </base:section>
584     
585      <%
586    }
587    %>
588  </base:body>
589  </base:page>
590  <%
591}
592finally
593{
594  if (dc != null) dc.close();
595}
596
597%>
Note: See TracBrowser for help on using the repository browser.