6694 |
26 Jan 15 |
nicklas |
1 |
/** |
6694 |
26 Jan 15 |
nicklas |
$Id $ |
6694 |
26 Jan 15 |
nicklas |
3 |
|
6694 |
26 Jan 15 |
nicklas |
Copyright (C) 2015 Nicklas Nordborg |
6694 |
26 Jan 15 |
nicklas |
5 |
|
6694 |
26 Jan 15 |
nicklas |
This file is part of BASE - BioArray Software Environment. |
6694 |
26 Jan 15 |
nicklas |
Available at http://base.thep.lu.se/ |
6694 |
26 Jan 15 |
nicklas |
8 |
|
6694 |
26 Jan 15 |
nicklas |
BASE is free software; you can redistribute it and/or |
6694 |
26 Jan 15 |
nicklas |
modify it under the terms of the GNU General Public License |
6694 |
26 Jan 15 |
nicklas |
as published by the Free Software Foundation; either version 3 |
6694 |
26 Jan 15 |
nicklas |
of the License, or (at your option) any later version. |
6694 |
26 Jan 15 |
nicklas |
13 |
|
6694 |
26 Jan 15 |
nicklas |
BASE is distributed in the hope that it will be useful, |
6694 |
26 Jan 15 |
nicklas |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
6694 |
26 Jan 15 |
nicklas |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
6694 |
26 Jan 15 |
nicklas |
GNU General Public License for more details. |
6694 |
26 Jan 15 |
nicklas |
18 |
|
6694 |
26 Jan 15 |
nicklas |
You should have received a copy of the GNU General Public License |
6694 |
26 Jan 15 |
nicklas |
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 |
Manager class for batch inheriting of annotations. The manager is created |
6694 |
26 Jan 15 |
nicklas |
with a list of {@link InheritSpecification}:s, each one holding a rule for |
6694 |
26 Jan 15 |
nicklas |
inheriting a single annotation type. |
6694 |
26 Jan 15 |
nicklas |
45 |
|
6694 |
26 Jan 15 |
nicklas |
Use {@link #process(Annotatable)} to apply all rules to the given item. |
6694 |
26 Jan 15 |
nicklas |
47 |
|
6694 |
26 Jan 15 |
nicklas |
@author nicklas |
6694 |
26 Jan 15 |
nicklas |
@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 |
Process the given item, inheriting and/or removing annotations as specified by |
6694 |
26 Jan 15 |
nicklas |
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 |
// Process annotations to remove |
6694 |
26 Jan 15 |
nicklas |
// 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 |
// 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 |
// Process each inherit specification in turn |
6694 |
26 Jan 15 |
nicklas |
// Keep track of the first one found so we can |
6694 |
26 Jan 15 |
nicklas |
// 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 |
// Check if subtype of parent item matches subtype in specification |
6694 |
26 Jan 15 |
nicklas |
// 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 |
// 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 |
// 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 |
// 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 |
// 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 |
// 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 |
// 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 |
// 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 |
// 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 |
Filter used to find parent items that are annotated and for which the current user has |
6694 |
26 Jan 15 |
nicklas |
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 |
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 |
} |