-
Notifications
You must be signed in to change notification settings - Fork 28
/
CodeSystemUtils.java
296 lines (231 loc) · 11.8 KB
/
CodeSystemUtils.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
/*
* Copyright 2011-2015 B2i Healthcare Pte Ltd, http:https://b2i.sg
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http:https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.b2international.snowowl.datastore;
import static com.b2international.snowowl.core.ApplicationContext.getServiceForClass;
import static com.b2international.snowowl.datastore.BranchPathUtils.isMain;
import static com.b2international.snowowl.datastore.ICodeSystem.TO_BRANCH_PATH_FUNCTION;
import static com.google.common.base.Strings.nullToEmpty;
import java.util.Comparator;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import javax.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.b2international.snowowl.core.ApplicationContext;
import com.b2international.snowowl.core.CoreTerminologyBroker;
import com.b2international.snowowl.core.api.IBranchPath;
import com.b2international.snowowl.core.api.NullBranchPath;
import com.b2international.snowowl.core.api.SnowowlRuntimeException;
import com.b2international.snowowl.core.date.Dates;
import com.b2international.snowowl.datastore.cdo.ICDOConnection;
import com.b2international.snowowl.datastore.cdo.ICDOConnectionManager;
import com.b2international.snowowl.datastore.cdo.ICDOManagedItem;
import com.b2international.snowowl.datastore.tasks.TaskManager;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
/**
* Contains various continent methods for {@link ICodeSystem} and {@link ICodeSystemVersion}.
*
*/
public class CodeSystemUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(CodeSystemUtils.class);
private static final class SameRepositoryCodeSystemPredicate implements Predicate<ICodeSystem> {
private final String repositoryUUID;
private SameRepositoryCodeSystemPredicate(String repositoryUUID) {
this.repositoryUUID = Preconditions.checkNotNull(repositoryUUID, "repository UUID cannot be null");
}
@Override
public boolean apply(ICodeSystem input) {
return input.getRepositoryUuid().equals(repositoryUUID);
}
}
private static final LoadingCache<String, ICDOManagedItem<?>> TOOLING_ID_MANAGED_ITEM_CACHE = CacheBuilder.newBuilder().build(new CacheLoader<String, ICDOManagedItem<?>>() {
@Override public ICDOManagedItem<?> load(final String toolingId) throws Exception {
Preconditions.checkNotNull(toolingId, "Snow Owl terminology ID argument cannot be null.");
final String terminologyId = CoreTerminologyBroker.getInstance().getAllRegisteredTerminologies().contains(toolingId)
? toolingId
: CoreTerminologyBroker.getInstance().getTerminologyIdForTerminologyComponentId(toolingId);
for (final ICDOManagedItem<?> item : getServiceForClass(ICDOConnectionManager.class)) {
if (terminologyId.equals(item.getSnowOwlTerminologyComponentId())) {
return item;
}
}
throw new NullPointerException("Cannot find managed item for: '" + toolingId + "'.");
}
});
/**
* Comparator for sorting repository UUIDs in an alphabetic order based on the corresponding tooling feature name.
*/
public static final Comparator<String> TOOLING_FEATURE_NAME_COMPARATOR = new Comparator<String>() {
public int compare(final String leftUuid, final String rightUuid) {
final String leftName = nullToEmpty(CodeSystemUtils.getSnowOwlToolingName(leftUuid));
final String rightName = nullToEmpty(CodeSystemUtils.getSnowOwlToolingName(rightUuid));
return leftName.compareToIgnoreCase(rightName);
}
};
/**
* Returns with the {@link ICodeSystemVersion version} matching with the branch path argument from the given iterable of code system versions
* @param branchPath the branch path.
* @param versions an iterable of code system version.
* @return the matching code system version, or {@code null} if not found.
*/
@Nullable public static ICodeSystemVersion findMatchingVersion(IBranchPath branchPath, final Iterable<? extends ICodeSystemVersion> versions) {
Preconditions.checkNotNull(branchPath, "Branch path argument cannot be null.");
Preconditions.checkNotNull(versions, "Versions argument cannot be null.");
while (NullBranchPath.INSTANCE != branchPath) {
final String versionIdForRepository = branchPath.lastSegment();
for (final ICodeSystemVersion candidate : versions) {
if (candidate.getVersionId().equals(versionIdForRepository)) {
return candidate;
}
}
branchPath = branchPath.getParent();
}
return null;
}
/**
* Checks if the branchPath passed-in, corresponds to a version's branch path. If so, it returns the argument wrapped in an {@link Optional}.
* If not, it iterates upward on the branch's parentage, checking if parent's path is a version's branchPath.
* If none of the branchPaths in the parentage correspond to a version branchPath, it returns {@link Optional#absent()}.
* @param activeBranchPath
* @return
*/
public static Optional<IBranchPath> tryFindVersionBranchPath(final IBranchPath branchPath) {
if (BranchPathUtils.isMain(branchPath))
return Optional.absent();
if(isParsableDate(branchPath.lastSegment())) {
return Optional.of(branchPath);
}
return tryFindVersionBranchPath(branchPath.getParent());
}
private static boolean isParsableDate(String dateString) {
try {
Dates.parse(dateString);
return true;
} catch (SnowowlRuntimeException | NullPointerException e) {
return false;
}
}
public static ICodeSystem findMatchingCodeSystem(String branchPath, String repositoryUuid) {
return findMatchingCodeSystem(BranchPathUtils.createPath(branchPath), repositoryUuid);
}
public static ICodeSystem findMatchingCodeSystem(IBranchPath branchPath, String repositoryUuid) {
// branchPath can be: main, task branch, version/tag branch Path, extension branchPath
Iterable<ICodeSystem> codeSystemsInRepositoryUuid = Iterables.filter(getTerminologyRegistryService().getCodeSystems(new UserBranchPathMap()), sameRepositoryCodeSystemPredicate(repositoryUuid));
Map<String, ICodeSystem> branchPathToCodeSystemMap = Maps.uniqueIndex(codeSystemsInRepositoryUuid, TO_BRANCH_PATH_FUNCTION);
// if (branchPathToCodeSystemMap.containsKey(branchPath.getPath()))
// return branchPathToCodeSystemMap.get(branchPath.getPath());
for (IBranchPath path = branchPath; !isMain(path); path = path.getParent()) {
if (branchPathToCodeSystemMap.containsKey(path.getPath())) {
return branchPathToCodeSystemMap.get(path.getPath());
}
}
// falling back to the repositoryUUID's main code system.
return Iterables.find(codeSystemsInRepositoryUuid, ICodeSystem.IS_MAIN_BRANCH_PATH_PREDICATE);
}
/**
* Returns with the UUID of the repository associated with the given
* application specific tooling ID.
* @param snowOwlToolingId the application specific tooling ID. Could be both terminology and terminology component IDs.
* @return the UUID of the repository which is associated with a Snow Owl specific tooling feature.
*/
@Nullable public static String getRepositoryUuid(final String snowOwlToolingId) {
Preconditions.checkNotNull(snowOwlToolingId, "Snow Owl tooling ID argument cannot be null.");
return getAttribute(snowOwlToolingId, new Function<ICDOManagedItem<?>, String>() {
@Override public String apply(final ICDOManagedItem<?> item) {
return item.getUuid();
}
});
}
/**
* Returns with the human readable name of the repository associated with the given
* application specific tooling ID.
* @param snowOwlToolingId the application specific tooling ID. Could be both terminology and terminology component IDs.
* @return the human readable name of the repository which is associated with a Snow Owl specific tooling feature.
*/
@Nullable public static String getRepositoryName(final String snowOwlToolingId) {
Preconditions.checkNotNull(snowOwlToolingId, "Snow Owl tooling ID argument cannot be null.");
return getAttribute(snowOwlToolingId, new Function<ICDOManagedItem<?>, String>() {
@Override public String apply(final ICDOManagedItem<?> item) {
return item.getRepositoryName();
}
});
}
/**Sugar for {@link #getRepositoryUuid(String)}.<br>Returns with the repository UUID for the application specific
*component identifier.*/
@Nullable public static String getRepositoryUuid(final short terminologyComponentId) {
if (CoreTerminologyBroker.UNSPECIFIED_NUMBER_SHORT == terminologyComponentId) {
return null;
}
final String terminologyComponentIdAsString = CoreTerminologyBroker.getInstance().getTerminologyComponentId(terminologyComponentId);
return CodeSystemUtils.getRepositoryUuid(terminologyComponentIdAsString);
}
/**
* Returns with the application specific human readable tooling name associated with a repository given by its unique UUID.
* @param repositoryUuid the unique UUID of a repository.
* @return the application specific tooling name.
*/
public static String getSnowOwlToolingName(final String repositoryUuid) {
Preconditions.checkNotNull(repositoryUuid, "Repository UUID argument cannot be null.");
return getConnection(repositoryUuid).getSnowOwlTerminologyComponentName();
}
/**
* Returns with the application specific tooling ID associated with a repository given by its unique UUID.
* @param repositoryUuid the unique UUID of a repository.
* @return the application specific tooling ID.
*/
public static String getSnowOwlToolingId(final String repositoryUuid) {
Preconditions.checkNotNull(repositoryUuid, "Repository UUID argument cannot be null.");
return getConnection(repositoryUuid).getSnowOwlTerminologyComponentId();
}
public static Predicate<ICodeSystem> sameRepositoryCodeSystemPredicate(final String repositoryUUID) {
return new SameRepositoryCodeSystemPredicate(repositoryUUID);
}
/*returns with the connection for the given repository UUID*/
private static ICDOConnection getConnection(final String repositoryUuid) {
return getConnectionManager().getByUuid(repositoryUuid);
}
/*returns with the connection manager service*/
private static ICDOConnectionManager getConnectionManager() {
return ApplicationContext.getInstance().getService(ICDOConnectionManager.class);
}
/*returns with the task manager service*/
private static TaskManager getTaskManager() {
return ApplicationContext.getInstance().getService(TaskManager.class);
}
/*returns with the terminology registry service*/
private static TerminologyRegistryService getTerminologyRegistryService() {
return ApplicationContext.getInstance().getService(TerminologyRegistryService.class);
}
/*applies the given function on a CDO manager item which application specific tooling ID equals with the argument.
*both terminology and terminology component IDs are allowed as Snow Owl tooling ID.*/
private static <T> T getAttribute(final String toolingId, final Function<ICDOManagedItem<?>, T> f) {
try {
Preconditions.checkNotNull(toolingId, "Snow Owl terminology ID argument cannot be null.");
return f.apply(TOOLING_ID_MANAGED_ITEM_CACHE.get(toolingId));
} catch (final ExecutionException e) {
LOGGER.error("Cannot get property on managed item for ID: " + toolingId, e);
return null;
}
}
}