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

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

References #1941: Store experimental factor values as part experiments

Removing the annotation on a parent item will nullify the link from cloned annotations instead of removing the clones.

Other changes are related to fixing various NullPointerExceptions and other problems resulting from having "inherited" annotations without a parent item.

But more work is needed on this since the cloned annotations now end up in a state that is almost impossible to manage via the gui. The "batch inherit annotations" can be used to remove or update cloned annotation.

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