src/core/net/sf/basedb/util/annotations/InheritAnnotationsManager.java

Code
Comments
Other
Rev Date Author Line
6694 26 Jan 15 nicklas 1 /**
6694 26 Jan 15 nicklas 2   $Id $
6694 26 Jan 15 nicklas 3
6694 26 Jan 15 nicklas 4   Copyright (C) 2015 Nicklas Nordborg
6694 26 Jan 15 nicklas 5
6694 26 Jan 15 nicklas 6   This file is part of BASE - BioArray Software Environment.
6694 26 Jan 15 nicklas 7   Available at http://base.thep.lu.se/
6694 26 Jan 15 nicklas 8
6694 26 Jan 15 nicklas 9   BASE is free software; you can redistribute it and/or
6694 26 Jan 15 nicklas 10   modify it under the terms of the GNU General Public License
6694 26 Jan 15 nicklas 11   as published by the Free Software Foundation; either version 3
6694 26 Jan 15 nicklas 12   of the License, or (at your option) any later version.
6694 26 Jan 15 nicklas 13
6694 26 Jan 15 nicklas 14   BASE is distributed in the hope that it will be useful,
6694 26 Jan 15 nicklas 15   but WITHOUT ANY WARRANTY; without even the implied warranty of
6694 26 Jan 15 nicklas 16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
6694 26 Jan 15 nicklas 17   GNU General Public License for more details.
6694 26 Jan 15 nicklas 18
6694 26 Jan 15 nicklas 19   You should have received a copy of the GNU General Public License
6694 26 Jan 15 nicklas 20   along with BASE. If not, see <http://www.gnu.org/licenses/>.
6694 26 Jan 15 nicklas 21 */
6694 26 Jan 15 nicklas 22 package net.sf.basedb.util.annotations;
6694 26 Jan 15 nicklas 23
6694 26 Jan 15 nicklas 24 import java.util.ArrayList;
6694 26 Jan 15 nicklas 25 import java.util.HashSet;
6694 26 Jan 15 nicklas 26 import java.util.List;
6694 26 Jan 15 nicklas 27 import java.util.Set;
6694 26 Jan 15 nicklas 28
6694 26 Jan 15 nicklas 29 import net.sf.basedb.core.Annotatable;
6926 03 Jun 15 nicklas 30 import net.sf.basedb.core.Annotation;
6694 26 Jan 15 nicklas 31 import net.sf.basedb.core.AnnotationSet;
6694 26 Jan 15 nicklas 32 import net.sf.basedb.core.DbControl;
6694 26 Jan 15 nicklas 33 import net.sf.basedb.core.Permission;
6694 26 Jan 15 nicklas 34 import net.sf.basedb.core.signal.ThreadSignalHandler;
6694 26 Jan 15 nicklas 35 import net.sf.basedb.core.snapshot.AnnotationSetSnapshot;
6694 26 Jan 15 nicklas 36 import net.sf.basedb.core.snapshot.AnnotationSnapshot;
6694 26 Jan 15 nicklas 37 import net.sf.basedb.core.snapshot.SnapshotManager;
6694 26 Jan 15 nicklas 38 import net.sf.basedb.util.AnnotationUtil;
6694 26 Jan 15 nicklas 39 import net.sf.basedb.util.filter.Filter;
6694 26 Jan 15 nicklas 40
6694 26 Jan 15 nicklas 41 /**
6694 26 Jan 15 nicklas 42   Manager class for batch inheriting of annotations. The manager is created
6694 26 Jan 15 nicklas 43   with a list of {@link InheritSpecification}:s, each one holding a rule for
6694 26 Jan 15 nicklas 44   inheriting a single annotation type.
6694 26 Jan 15 nicklas 45   
6694 26 Jan 15 nicklas 46   Use {@link #process(Annotatable)} to apply all rules to the given item.
6694 26 Jan 15 nicklas 47   
6694 26 Jan 15 nicklas 48   @author nicklas
6694 26 Jan 15 nicklas 49   @since 3.5
6694 26 Jan 15 nicklas 50 */
6694 26 Jan 15 nicklas 51 public class InheritAnnotationsManager 
6694 26 Jan 15 nicklas 52 {
6694 26 Jan 15 nicklas 53
6694 26 Jan 15 nicklas 54   private final DbControl dc;
6694 26 Jan 15 nicklas 55   private final SnapshotManager snapshotManager;
6926 03 Jun 15 nicklas 56   private final AnnotationTypeFilter removeFilter;
6926 03 Jun 15 nicklas 57   private final AnnotationTypeFilter resyncFilter;
6694 26 Jan 15 nicklas 58   private final List<InheritSpecification> specifications;
6694 26 Jan 15 nicklas 59   
6694 26 Jan 15 nicklas 60   public InheritAnnotationsManager(DbControl dc, SnapshotManager snapshotManager, List<InheritSpecification> specifications)
6694 26 Jan 15 nicklas 61   {
6694 26 Jan 15 nicklas 62     this.dc = dc;
6694 26 Jan 15 nicklas 63     this.snapshotManager = snapshotManager;
6926 03 Jun 15 nicklas 64     this.removeFilter = new AnnotationTypeFilter(null);
6926 03 Jun 15 nicklas 65     this.resyncFilter = new AnnotationTypeFilter(Annotation.Source.CLONED);
6694 26 Jan 15 nicklas 66     this.specifications = new ArrayList<InheritSpecification>();
6694 26 Jan 15 nicklas 67     for (InheritSpecification spec : specifications)
6694 26 Jan 15 nicklas 68     {
6694 26 Jan 15 nicklas 69       if (spec.getRemove())
6694 26 Jan 15 nicklas 70       {
6694 26 Jan 15 nicklas 71         removeFilter.add(spec);
6694 26 Jan 15 nicklas 72       }
6926 03 Jun 15 nicklas 73       else if (spec.getResync())
6926 03 Jun 15 nicklas 74       {
6926 03 Jun 15 nicklas 75         resyncFilter.add(spec);
6926 03 Jun 15 nicklas 76       }
6694 26 Jan 15 nicklas 77       else
6694 26 Jan 15 nicklas 78       {
6694 26 Jan 15 nicklas 79         this.specifications.add(spec);
6694 26 Jan 15 nicklas 80       }
6694 26 Jan 15 nicklas 81     }
6694 26 Jan 15 nicklas 82   }
6694 26 Jan 15 nicklas 83
6694 26 Jan 15 nicklas 84   /**
6694 26 Jan 15 nicklas 85     Process the given item, inheriting and/or removing annotations as specified by
6694 26 Jan 15 nicklas 86     the rules.
6694 26 Jan 15 nicklas 87   */
6694 26 Jan 15 nicklas 88   public void process(Annotatable item)
6694 26 Jan 15 nicklas 89   {
6694 26 Jan 15 nicklas 90     AnnotationSetSnapshot snapshot = null;
6694 26 Jan 15 nicklas 91     AnnotationSet as = null;
6694 26 Jan 15 nicklas 92     if (item.isAnnotated())
6694 26 Jan 15 nicklas 93     {
6694 26 Jan 15 nicklas 94       as = item.getAnnotationSet();
6694 26 Jan 15 nicklas 95       snapshot = snapshotManager.getSnapshot(dc, as.getId());
6694 26 Jan 15 nicklas 96       
6694 26 Jan 15 nicklas 97       // Process annotations to remove
6694 26 Jan 15 nicklas 98       // Only works with directly inherited annotations
6694 26 Jan 15 nicklas 99       for (AnnotationSnapshot inherited : snapshotManager.findAnnotations(dc, snapshot, removeFilter, false, true))
6694 26 Jan 15 nicklas 100       {
6937 07 Aug 15 nicklas 101         as.removeInheritedAnnotation(inherited.getThisAnnotation(dc));
6694 26 Jan 15 nicklas 102       }
6926 03 Jun 15 nicklas 103       
6926 03 Jun 15 nicklas 104       // Process annotations to re-sync
6926 03 Jun 15 nicklas 105       for (AnnotationSnapshot inherited : snapshotManager.findAnnotations(dc, snapshot, resyncFilter, false, true))
6926 03 Jun 15 nicklas 106       {
6926 03 Jun 15 nicklas 107         inherited.getThisAnnotation(dc).resyncCloned();
6926 03 Jun 15 nicklas 108       }
6926 03 Jun 15 nicklas 109       
6694 26 Jan 15 nicklas 110     }
6694 26 Jan 15 nicklas 111     
6694 26 Jan 15 nicklas 112     if (specifications.size() == 0) return;  // Nothing more to do
6694 26 Jan 15 nicklas 113     
6694 26 Jan 15 nicklas 114     as = item.getAnnotationSet();
6694 26 Jan 15 nicklas 115     
6694 26 Jan 15 nicklas 116     Set<Annotatable> allParents = AnnotationUtil.getAllAnnotatableParentItems(dc, item, new UsableParentFilter());
6694 26 Jan 15 nicklas 117     for (InheritSpecification spec : specifications)
6694 26 Jan 15 nicklas 118     {
6694 26 Jan 15 nicklas 119       // Process each inherit specification in turn
6694 26 Jan 15 nicklas 120       // Keep track of the first one found so we can
6694 26 Jan 15 nicklas 121       // handle the case when removeExisting=true and noDuplicates=false
6694 26 Jan 15 nicklas 122       boolean isFirst = true;
6694 26 Jan 15 nicklas 123       
6694 26 Jan 15 nicklas 124       for (Annotatable parent : allParents)
6694 26 Jan 15 nicklas 125       {
6694 26 Jan 15 nicklas 126         ThreadSignalHandler.checkInterrupted();
6694 26 Jan 15 nicklas 127         // Check if subtype of parent item matches subtype in specification
6694 26 Jan 15 nicklas 128         // If not set, all parents are accepted
6694 26 Jan 15 nicklas 129         if (spec.isAcceptableParent(parent))
6694 26 Jan 15 nicklas 130         {
6694 26 Jan 15 nicklas 131           AnnotationSet pas = parent.getAnnotationSet();
6694 26 Jan 15 nicklas 132           AnnotationSetSnapshot parentSnapshot = snapshotManager.getSnapshot(dc, pas.getId());
6694 26 Jan 15 nicklas 133         
6694 26 Jan 15 nicklas 134           // Find annotation on the parent item (the list can have at most one entry)
6694 26 Jan 15 nicklas 135           List<AnnotationSnapshot> tmp = snapshotManager.findAnnotations(dc, parentSnapshot, spec, true, false);
6694 26 Jan 15 nicklas 136           if (tmp.size() > 0)
6694 26 Jan 15 nicklas 137           {
6694 26 Jan 15 nicklas 138             // We have an annotation that we should inherit
6694 26 Jan 15 nicklas 139             AnnotationSnapshot toInherit = tmp.get(0);
6694 26 Jan 15 nicklas 140
6694 26 Jan 15 nicklas 141             // Check if there are any existing annotation in case we need to act on them
6694 26 Jan 15 nicklas 142             if (isFirst && (spec.getReplaceExisting() || spec.getNoDuplicates()))
6694 26 Jan 15 nicklas 143             {
6694 26 Jan 15 nicklas 144               isFirst = false;
6694 26 Jan 15 nicklas 145               List<AnnotationSnapshot> existing = snapshotManager.findAnnotations(dc, snapshot, spec, false, true);
6694 26 Jan 15 nicklas 146               
6694 26 Jan 15 nicklas 147               if (existing.size() > 0)
6694 26 Jan 15 nicklas 148               {
6694 26 Jan 15 nicklas 149                 // Replace existing annotations
6694 26 Jan 15 nicklas 150                 if (spec.getReplaceExisting())
6694 26 Jan 15 nicklas 151                 {
6694 26 Jan 15 nicklas 152                   for (AnnotationSnapshot e : existing)
6694 26 Jan 15 nicklas 153                   {
6924 03 Jun 15 nicklas 154                     if (e.getInheritedAnnotationId() != toInherit.getThisAnnotationId())
6694 26 Jan 15 nicklas 155                     {
6926 03 Jun 15 nicklas 156                       // We only remove the annotation if it is not the same we are going to add later
6937 07 Aug 15 nicklas 157                       as.removeInheritedAnnotation(e.getThisAnnotation(dc));
6694 26 Jan 15 nicklas 158                     }
6926 03 Jun 15 nicklas 159                     else
6926 03 Jun 15 nicklas 160                     {
6926 03 Jun 15 nicklas 161                       // Found existing annotation;  re-sync if it is a cloned annotation
6926 03 Jun 15 nicklas 162                       e.getThisAnnotation(dc).resyncCloned();
6926 03 Jun 15 nicklas 163                     }
6694 26 Jan 15 nicklas 164                   }
6694 26 Jan 15 nicklas 165                 }
6694 26 Jan 15 nicklas 166                 // Continue with next specification if not allowing duplicates
6694 26 Jan 15 nicklas 167                 else if (spec.getNoDuplicates())
6694 26 Jan 15 nicklas 168                 {
6694 26 Jan 15 nicklas 169                   break;
6694 26 Jan 15 nicklas 170                 }
6694 26 Jan 15 nicklas 171               }
6694 26 Jan 15 nicklas 172             }
6694 26 Jan 15 nicklas 173     
6925 03 Jun 15 nicklas 174             as.inheritAnnotation(toInherit.getThisAnnotation(dc), spec.getClone());
6694 26 Jan 15 nicklas 175             
6694 26 Jan 15 nicklas 176             // Continue with next specification if not allowing duplicates
6694 26 Jan 15 nicklas 177             if (spec.getNoDuplicates()) break;
6694 26 Jan 15 nicklas 178           }
6694 26 Jan 15 nicklas 179         }
6694 26 Jan 15 nicklas 180         
6694 26 Jan 15 nicklas 181       }
6694 26 Jan 15 nicklas 182     }
6694 26 Jan 15 nicklas 183     
6694 26 Jan 15 nicklas 184   }
6694 26 Jan 15 nicklas 185   
6694 26 Jan 15 nicklas 186   /**
6694 26 Jan 15 nicklas 187     Filter used to find parent items that are annotated and for which the current user has
6694 26 Jan 15 nicklas 188     permission to USE the annotations.
6694 26 Jan 15 nicklas 189   */
6694 26 Jan 15 nicklas 190   static class UsableParentFilter
6694 26 Jan 15 nicklas 191     implements Filter<Annotatable>
6694 26 Jan 15 nicklas 192   {
6694 26 Jan 15 nicklas 193     
6694 26 Jan 15 nicklas 194     UsableParentFilter()
6694 26 Jan 15 nicklas 195     {}
6694 26 Jan 15 nicklas 196     
6694 26 Jan 15 nicklas 197     @Override
6694 26 Jan 15 nicklas 198     public boolean evaluate(Annotatable a)
6694 26 Jan 15 nicklas 199     {
6694 26 Jan 15 nicklas 200       return a.isAnnotated() && a.hasPermission(Permission.USE);
6694 26 Jan 15 nicklas 201     }
6694 26 Jan 15 nicklas 202   }
6694 26 Jan 15 nicklas 203   
6694 26 Jan 15 nicklas 204   /**
6926 03 Jun 15 nicklas 205      Filter for finding annotation types to process.
6694 26 Jan 15 nicklas 206   */
6926 03 Jun 15 nicklas 207   static class AnnotationTypeFilter 
6694 26 Jan 15 nicklas 208     implements Filter<AnnotationSnapshot>
6694 26 Jan 15 nicklas 209   {
6694 26 Jan 15 nicklas 210
6926 03 Jun 15 nicklas 211     private final Annotation.Source source;
6926 03 Jun 15 nicklas 212     private final Set<Integer> annotationTypes;
6694 26 Jan 15 nicklas 213   
6926 03 Jun 15 nicklas 214     AnnotationTypeFilter(Annotation.Source source) 
6694 26 Jan 15 nicklas 215     {
6926 03 Jun 15 nicklas 216       this.source = source;
6926 03 Jun 15 nicklas 217       this.annotationTypes = new HashSet<Integer>();
6694 26 Jan 15 nicklas 218     }
6694 26 Jan 15 nicklas 219
6694 26 Jan 15 nicklas 220     @Override
6694 26 Jan 15 nicklas 221     public boolean evaluate(AnnotationSnapshot snapshot) 
6694 26 Jan 15 nicklas 222     {
6926 03 Jun 15 nicklas 223       boolean sourceMatch = source == null || source.equals(snapshot.getSource());
6926 03 Jun 15 nicklas 224       boolean typeMatch = annotationTypes.contains(snapshot.getAnnotationTypeId());
6926 03 Jun 15 nicklas 225       return sourceMatch && typeMatch;
6694 26 Jan 15 nicklas 226     }
6694 26 Jan 15 nicklas 227     
6694 26 Jan 15 nicklas 228     void add(InheritSpecification spec)
6694 26 Jan 15 nicklas 229     {
6926 03 Jun 15 nicklas 230       annotationTypes.add(spec.getAnnotationType().getId());
6694 26 Jan 15 nicklas 231     }
6694 26 Jan 15 nicklas 232   }
6694 26 Jan 15 nicklas 233 }