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

Last change on this file since 6938 was 6938, checked in by Nicklas Nordborg, 7 years ago

References #1941: Store experimental factor values as part experiments

Started with redesigning the annotations edit dialog. The idea is to include both primary and inherited/cloned annotations in the "Annotations" tab and manage all types of annotations there. The "Inherited annotations" tab will be removed.

So far, the new implementation will list all types of annotations. PRIMARY and CLONED annotations are editable, INHERITED annotations only display some information. Support for multi-valued annotations is not implemeted.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Id
File size: 18.4 KB
Line 
1<%-- $Id: list_annotations.jsp 6938 2015-08-19 07:17:33Z 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:before
200    {
201      display: inline-block;
202      content: "∙";
203      color: #999999;
204      padding-right: 0.25em;
205      padding-left: 1px;
206      text-decoration: none;
207    }
208  </style>
209  </base:head>
210  <base:body>
211    <%
212    if (message != null)
213    {
214      %>
215      <div class="messagecontainer note"><%=message%></div>
216      <%
217    }
218    %>
219    <base:section
220      id="primaryAnnotations"
221      title="<%="Primary annotations (" + annotationTypes.size() + ")"%>"
222      >
223      <%
224      int allWithValues = 0;
225      int allOfCategory = 0;
226      if (annotationTypes.size() == 0)
227      {
228        %>
229        <div class="messagecontainer note">
230        No annotation types has been defined for this type of item
231        (or you don't have permission to view them).
232        </div>
233        <%
234      }
235      else
236      {
237        %>
238        <tbl:table
239          id="annotations"
240          columns="all"
241          >
242          <tbl:columndef 
243            id="annotation"
244            title="Annotation"
245          />
246          <tbl:columndef 
247            id="values"
248            title="Values"
249          />
250          <tbl:columndef
251            id="lastModified"
252            title="Last modified"
253            formatter="<%=dateTimeFormatter%>"
254          />
255          <tbl:columndef 
256            id="description"
257            title="Description"
258          />
259          <div class="panelgroup topborder leftborder rightborder bg-filled-100">
260            <tbl:panel style="height: auto; padding: 2px;">
261              <b>View:</b> 
262              <%
263              if (selectedCategoryName != null)
264              {
265                %>
266                <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>)
267                <%
268              }
269              %>
270              <label><input type="radio" name="view" id="view_values" value="values" <%=selectedCategoryName == null ? "checked" : ""%>>All with values</label> (<span id="allWithValues">?</span>)
271              <label><input type="radio" name="view" id="view_all" value="all">All annotations</label> (<%=annotationTypes.size()%>)
272            </tbl:panel>
273          </div>
274          <tbl:data id="annotations-data">
275            <tbl:headers>
276              <tbl:headerrow>
277                <tbl:columnheaders />
278              </tbl:headerrow>
279            </tbl:headers>
280            <tbl:rows>
281            <%
282            for (AnnotationType at : annotationTypes)
283            {
284              AnnotationSnapshot a = existing != null ? existing.get(at) : null;
285              List<?> values = null;
286              Formatter formatter = null;
287              if (a != null)
288              {
289                Annotation ann = a.getAnnotation(dc);
290                values = a.getValues(ann.getUnitConverter(null), ann.getValueType());
291                formatter = FormatterFactory.getAnnotationFormatter(sc, ann, null);
292              }
293              if (values != null || !at.isRemoved())
294              {
295                String rowClass = "";
296                if (values == null || values.size() == 0) 
297                {
298                  rowClass += " novalues";
299                }
300                else
301                {
302                  allWithValues++;
303                }
304                if (!annotationTypesInCategory.contains(at)) 
305                {
306                  rowClass += " nocategory";
307                }
308                else
309                {
310                  allOfCategory++;
311                }
312                %>
313                <tbl:row subclass="<%=rowClass%>">
314                  <tbl:cell column="annotation"><base:icon 
315                    image="deleted.png" 
316                    tooltip="This item has been scheduled for deletion" 
317                    visible="<%=at.isRemoved()%>"
318                  /><%=Base.getLinkedName(ID, at, false, true)%></tbl:cell>
319                  <tbl:cell column="values"><%=values == null || values.size() == 0 ? "<i>- no values -</i>" : Values.getString(values, ", ", true, formatter)%>
320                    <%
321                    if (writePermission)
322                    {
323                      %><base:icon image="edit.png" subclass="edit-annotation auto-init link" 
324                        data-auto-init="edit-annotation" 
325                        data-annotation="<%=a!=null ? a.getThisAnnotationId() : 0 %>"
326                        data-annotation-type="<%=at.getId()%>"
327                        data-item-type="<%=itemType.name()%>" 
328                        data-item-id="<%=itemId %>"
329                        tooltip="Modify the values of this annotation"
330                      />
331                      <%
332                    }
333                    %>
334                  </tbl:cell>
335                  <tbl:cell column="lastModified" value="<%=a == null ? null : a.getThisLastUpdate() %>" />
336                  <tbl:cell column="description"><%=HTML.encodeTags(at.getDescription())%></tbl:cell>
337                </tbl:row>
338                <%
339              }
340            }
341            %>
342            </tbl:rows>
343          </tbl:data>
344        </tbl:table>
345        <%
346      }
347      %>
348      <div id="annotations-stat" class="datacontainer"
349        data-all-with-values="<%=allWithValues %>"
350        data-all-of-category="<%=allOfCategory%>"
351      ></div>
352    </base:section>
353
354    <%
355    if (protocolParameters != null)
356    {
357      %>
358      <base:section 
359        id="parameterSection" 
360        title="<%="Protocol parameters for " + HTML.encodeTags(protocol.getName()) + 
361          " (" + protocolParameters.size() + ")"%>"
362        >
363        <%
364        if (protocolParameters.size() == 0)
365        {
366          %>
367          <div class="messagecontainer note">
368          No protocol parameters has been defined for the protocol
369          <%=Base.getLinkedName(ID, protocol, !readProtocol, true)%> 
370          (or you don't have permission to view them).
371          </div>
372          <%
373        }
374        else
375        {
376          %>
377          <tbl:table
378            id="parameters"
379            columns="all"
380            >
381            <tbl:columndef 
382              id="parameter"
383              title="Parameter"
384            />
385            <tbl:columndef 
386              id="values"
387              title="Values"
388            />
389            <tbl:columndef
390              id="lastModified"
391              title="Last modified"
392              formatter="<%=dateTimeFormatter%>"
393            />
394            <tbl:columndef 
395              id="description"
396              title="Description"
397            />
398            <tbl:data>
399              <tbl:headers>
400                <tbl:headerrow>
401                  <tbl:columnheaders />
402                </tbl:headerrow>
403              </tbl:headers>
404              <tbl:rows>
405              <%
406              for (AnnotationType at : protocolParameters)
407              {
408                AnnotationSnapshot a = existing != null ? existing.get(at) : null;
409                Formatter formatter = null;
410                List<?> values = null;
411                if (a != null)
412                {
413                  Annotation ann = a.getAnnotation(dc);
414                  values = a.getValues(ann.getUnitConverter(null), ann.getValueType());
415                  formatter = FormatterFactory.getAnnotationFormatter(sc, ann, null);
416                }
417                if (values != null || !at.isRemoved())
418                {
419                  %>
420                  <tbl:row>
421                    <tbl:cell column="parameter"><base:icon 
422                      image="deleted.png" 
423                      tooltip="This item has been scheduled for deletion" 
424                      visible="<%=at.isRemoved()%>"
425                    /><%=Base.getLinkedName(ID, at, false, true)%></tbl:cell>
426                    <tbl:cell column="values">
427                      <%=values == null || values.size() == 0 ? "<i>- no values -</i>" : Values.getString(values, ", ", true, formatter)%>
428                      <%
429                      if (writePermission)
430                      {
431                        %><base:icon image="edit.png" subclass="edit-annotation auto-init link" 
432                          data-auto-init="edit-annotation" 
433                          data-annotation="<%=a!=null ? a.getThisAnnotationId() : 0 %>"
434                          data-annotation-type="<%=at.getId()%>"
435                          data-item-type="<%=itemType.name()%>" 
436                          data-item-id="<%=itemId %>"
437                          tooltip="Modify the values of this protocol parameter" 
438                        />
439                        <%
440                      }
441                      %>
442                    </tbl:cell>
443                    <tbl:cell column="lastModified" value="<%=a == null ? null : a.getThisLastUpdate() %>" />
444                    <tbl:cell column="description"><%=HTML.encodeTags(at.getDescription())%></tbl:cell>
445                  </tbl:row>
446                  <%
447                }
448              }
449              %>
450              </tbl:rows>
451            </tbl:data>
452          </tbl:table>
453          <%
454        }
455        %>
456      </base:section>
457      <%
458    }
459    if (!isProxy)
460    {
461      int numInherited = inheritedAnnotations == null ? 0 : inheritedAnnotations.size();
462      %>
463      <base:section 
464        id="inherited"
465        title="<%="Inherited annotations (" + numInherited + ")"%>"         
466        >
467        <%
468        if (numInherited == 0)
469        {
470          %>
471          <div class="messagecontainer note">
472          No annotations are inherited by this item.
473          (or you don't have permission to view them).
474          </div>
475          <%
476        }
477        else
478        {
479        %>
480        <tbl:table
481          id="inheritedAnnotations"
482          columns="all"
483          >
484          <tbl:columndef 
485            id="annotation"
486            title="Annotation"
487          />
488          <tbl:columndef 
489            id="values"
490            title="Values"
491          />
492          <tbl:columndef 
493            id="source"
494            title="Cloned"
495          />
496          <tbl:columndef 
497            id="item"
498            title="From item"
499          />
500          <tbl:columndef
501            id="lastModified"
502            title="Last modified"
503            formatter="<%=dateTimeFormatter %>"
504          />
505          <tbl:columndef 
506            id="description"
507            title="Description"
508          />
509          <tbl:data>
510            <tbl:headers>
511              <tbl:headerrow>
512                <tbl:columnheaders />
513              </tbl:headerrow>
514            </tbl:headers>
515            <tbl:rows>
516            <%
517            for (AnnotationSnapshot a : inheritedAnnotations)
518            {
519              AnnotationType at = a.getAnnotationType(dc);
520              AnnotationSnapshot from = a.getInheritedFrom();
521             
522              // About this annotation
523              String name = HTML.encodeTags(at.getName());
524              String description = HTML.encodeTags(at.getDescription());
525              Date lastModified = a.getThisLastUpdate();
526              boolean isUpToDate = true;
527             
528              // Which item are we inheriting from?
529              Nameable fromItem = null;
530              String fromType = null;
531              boolean writeInherited = false;
532              if (from != null)
533              {
534                fromType = from.getThisItemType().toString();
535                if (lastModified == null)
536                {
537                  lastModified = from.getThisLastUpdate();
538                }
539                else
540                {
541                  isUpToDate = !lastModified.before(from.getThisLastUpdate());
542                }
543                try
544                {
545                  fromItem = (Nameable)from.getThisItem(dc);
546                  writeInherited = fromItem.hasPermission(Permission.WRITE);
547                  if (fromItem instanceof Subtypable)
548                  {
549                    ItemSubtype subtype = ((Subtypable)fromItem).getItemSubtype();
550                    if (subtype != null) fromType = subtype.getName();
551                  }
552                }
553                catch (PermissionDeniedException ex)
554                {}
555              }
556             
557              // Values, units, etc.
558              Formatter formatter = FormatterFactory.getTypeFormatter(sc, at.getValueType());
559              Unit unit = a.getActualUnit(dc);
560              UnitConverter converter = null;
561              if (unit != null)
562              {
563                converter = unit.getUnitConverter(at.getDefaultUnit());
564                formatter = unit.getFormatter(formatter);
565              }
566              List<?> values = a.getActualValues(converter, at.getValueType());
567              %>
568              <tbl:row>
569                <tbl:cell column="annotation"><%=Base.getLinkedName(ID, at, at == null, true)%></tbl:cell>
570                <tbl:cell column="source"><%=a.getSource() == Annotation.Source.CLONED ? "Yes" + (isUpToDate ? "; up-to-date" : "; modified") : "" %></tbl:cell>
571                <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>
572                <tbl:cell column="values">
573                  <%=values == null || values.size() == 0 ? 
574                    "<i>- no values -</i>" : Values.getString(values, ", ", true, formatter)%>
575                  <%
576                  if (writePermission)
577                  {
578                    %><base:icon image="edit.png" subclass="edit-annotation auto-init link" 
579                      data-auto-init="edit-annotation" 
580                      data-annotation="<%= a.getThisAnnotationId()%>"
581                      data-annotation-type="<%=at.getId()%>"
582                      data-item-type="<%=itemType.name()%>" 
583                      data-item-id="<%=itemId %>"
584                      tooltip="Modify the values of this annotation"
585                    />
586                    <%
587                  }
588                  %>
589                </tbl:cell>
590                <tbl:cell column="lastModified" value="<%=lastModified %>"></tbl:cell>
591                <tbl:cell column="description"><%=description%></tbl:cell>
592              </tbl:row>
593              <%
594            }
595            %>
596            </tbl:rows>
597          </tbl:data>
598        </tbl:table>
599        <%
600      }
601      %>
602      </base:section>
603     
604      <%
605    }
606    %>
607  </base:body>
608  </base:page>
609  <%
610}
611finally
612{
613  if (dc != null) dc.close();
614}
615
616%>
Note: See TracBrowser for help on using the repository browser.