use of com.b2international.commons.exceptions.ApiError in project snow-owl by b2ihealthcare.
the class CodeSystemUpgradeSynchronizationRequest method execute.
@Override
public Boolean execute(RepositoryContext context) {
final String message = String.format("Merge %s into %s", source, codeSystemId);
CodeSystem codeSystem = CodeSystemRequests.prepareGetCodeSystem(codeSystemId.getResourceId()).build().execute(context);
if (codeSystem.getUpgradeOf() == null) {
throw new BadRequestException("Code System '%s' is not an Upgrade Code System. It cannot be synchronized with '%s'.", codeSystemId, source);
}
final String sourceBranchPath = context.service(ResourceURIPathResolver.class).resolve(context, List.of(source)).stream().findFirst().get();
// merge all changes from the source to the current upgrade of branch
final Merge merge = RepositoryRequests.merging().prepareCreate().setSource(sourceBranchPath).setTarget(codeSystem.getBranchPath()).setUserId(context.service(User.class).getUsername()).setCommitComment(message).setSquash(false).build(codeSystem.getToolingId()).getRequest().execute(context);
if (merge.getStatus() != Merge.Status.COMPLETED) {
// report conflicts
ApiError apiError = merge.getApiError();
Collection<MergeConflict> conflicts = merge.getConflicts();
context.log().error("Failed to sync source CodeSystem content to upgrade CodeSystem. Error: {}. Conflicts: {}", apiError.getMessage(), conflicts);
throw new ConflictException("Upgrade code system synchronization can not be performed due to conflicting content errors.").withAdditionalInfo(Map.of("conflicts", conflicts, "mergeError", apiError.getMessage()));
}
if (!codeSystem.getUpgradeOf().equals(source)) {
return new BranchRequest<>(Branch.MAIN_PATH, new ResourceRepositoryCommitRequestBuilder().setBody((tx) -> {
ResourceDocument entry = tx.lookup(codeSystemId.getResourceId(), ResourceDocument.class);
tx.add(ResourceDocument.builder(entry).upgradeOf(source).build());
tx.commit(String.format("Update upgradeOf from '%s' to '%s'", codeSystem.getUpgradeOf(), source));
return Boolean.TRUE;
}).setCommitComment(String.format("Complete upgrade of %s to %s", codeSystem.getUpgradeOf().getResourceId(), codeSystem.getExtensionOf())).build()).execute(context).getResultAs(Boolean.class);
} else {
return Boolean.TRUE;
}
}
use of com.b2international.commons.exceptions.ApiError in project snow-owl by b2ihealthcare.
the class RemoteJob method run.
@Override
protected final IStatus run(IProgressMonitor monitor) {
final ObjectMapper mapper = this.context.service(ObjectMapper.class);
final IProgressMonitor trackerMonitor = this.context.service(RemoteJobTracker.class).createMonitor(id, monitor);
try {
// override user when necessary
User user = context.service(User.class);
if (User.isSystem(this.user)) {
user = User.SYSTEM;
} else if (!user.getUsername().equals(this.user)) {
user = UserRequests.prepareGet(this.user).build().execute(this.context);
}
// seed the monitor instance into the current context, so the request can use it for progress reporting
final ServiceProvider context = this.context.inject().bind(IProgressMonitor.class, trackerMonitor).bind(RemoteJob.class, this).bind(User.class, user).build();
final Object response = request.execute(context);
if (response != null) {
final Class<? extends Object> responseType = response.getClass();
if (Primitives.isWrapperType(responseType) || String.class.isAssignableFrom(responseType) || UUID.class.isAssignableFrom(responseType)) {
this.response = toJson(mapper, ImmutableMap.of("value", response));
} else {
this.response = toJson(mapper, response);
}
}
final IStatus status = (IStatus) getProperty(REQUEST_STATUS);
return (status != null) ? status : Statuses.ok();
} catch (OperationCanceledException e) {
return Statuses.cancel();
} catch (Throwable e) {
final ApiError apiError;
if (e instanceof ApiException) {
apiError = ((ApiException) e).toApiError();
} else {
apiError = ApiError.builder(e.getMessage()).status(500).developerMessage("Exception caught while executing request in remote job.").addInfo("exception-class", e.getClass().getSimpleName()).build();
}
this.response = toJson(mapper, apiError);
// XXX: Don't delete remote jobs with errors
autoClean = false;
return Statuses.error(CoreActivator.PLUGIN_ID, "Failed to execute long running request", e);
} finally {
if (autoClean) {
context.service(RemoteJobTracker.class).requestDeletes(Collections.singleton(id));
}
}
}
use of com.b2international.commons.exceptions.ApiError in project snow-owl by b2ihealthcare.
the class SnomedRf2ImportRestService method toRf2ImportConfiguration.
private SnomedRf2ImportConfiguration toRf2ImportConfiguration(RemoteJobEntry job) {
ApiError error = null;
ImportResponse response = null;
ObjectMapper mapper = ApplicationContext.getServiceForClass(ObjectMapper.class);
if (RemoteJobState.FAILED == job.getState()) {
error = job.getResultAs(mapper, ApiError.class);
} else if (job.isSuccessful()) {
response = job.getResultAs(mapper, ImportResponse.class);
}
return new SnomedRf2ImportConfiguration(IDs.sha1(job.getId()), job.getState(), error, response);
}
use of com.b2international.commons.exceptions.ApiError in project snow-owl by b2ihealthcare.
the class VersionRestService method createVersion.
@Operation(summary = "Create a new resource version", description = "Creates a new resource version. " + "The version tag (represented by an empty branch) is created on the resource's current working branch. " + "Where applicable, effective times are set on the unpublished content as part of this operation.")
@ApiResponses({ @ApiResponse(responseCode = "201", description = "Created"), @ApiResponse(responseCode = "404", description = "Not found"), @ApiResponse(responseCode = "409", description = "Code system version conflicts with existing branch") })
@PostMapping(consumes = { AbstractRestService.JSON_MEDIA_TYPE })
@ResponseStatus(value = HttpStatus.CREATED)
public ResponseEntity<Void> createVersion(@Parameter(description = "Version parameters") @RequestBody final ResourceRequest<VersionRestInput> input) {
final VersionRestInput change = input.getChange();
ApiValidation.checkInput(change);
String newVersionUri = String.join(Branch.SEPARATOR, change.getResource().toString(), change.getVersion());
String jobId = ResourceRequests.prepareNewVersion().setResource(change.getResource()).setVersion(change.getVersion()).setDescription(change.getDescription()).setEffectiveTime(change.getEffectiveTime()).setForce(change.isForce()).setCommitComment(input.getCommitComment()).buildAsync().runAsJobWithRestart(ResourceRequests.versionJobKey(change.getResource()), "Creating version " + newVersionUri).execute(getBus()).getSync(1, TimeUnit.MINUTES);
RemoteJobEntry job = JobRequests.waitForJob(getBus(), jobId, 500);
if (job.isSuccessful()) {
final URI location = MvcUriComponentsBuilder.fromMethodName(VersionRestService.class, "getVersion", newVersionUri).build().toUri();
return ResponseEntity.created(location).build();
} else if (!Strings.isNullOrEmpty(job.getResult())) {
ApiError error = job.getResultAs(ApplicationContext.getServiceForClass(ObjectMapper.class), ApiError.class);
throw new ApiErrorException(error.withMessage(error.getMessage().replace("Branch name", "Version")));
} else {
throw new SnowowlRuntimeException("Version creation failed.");
}
}
use of com.b2international.commons.exceptions.ApiError in project snow-owl by b2ihealthcare.
the class CodeSystemUpgradeRequest method execute.
@Override
public String execute(RepositoryContext context) {
// get available upgrades
final CodeSystem currentCodeSystem = CodeSystemRequests.prepareGetCodeSystem(resource.getResourceId()).setExpand(CodeSystem.Expand.AVAILABLE_UPGRADES + "()").build().execute(context);
if (currentCodeSystem.getUpgradeOf() != null) {
throw new BadRequestException("Upgrade can not be started on an existing upgrade resource");
}
final List<ResourceURI> availableUpgrades = currentCodeSystem.getAvailableUpgrades();
// report bad request if there are no upgrades available
if (availableUpgrades.isEmpty()) {
throw new BadRequestException("There are no upgrades available for resource '%s'.", resource.getResourceId());
}
// or the selected extensionOf version is not present as a valid available upgrade
if (!availableUpgrades.contains(extensionOf)) {
throw new BadRequestException("Upgrades can only be performed to the next available version dependency.").withDeveloperMessage("Use '%s/<VERSION_ID>', where <VERSION_ID> is one of: '%s'", extensionOf.getResourceId(), availableUpgrades);
}
// auto-generate the resourceId if not provided
// auto-generated upgrade IDs consist of the original Resource's ID and the new extensionOf dependency's path, which is version at this point
final String upgradeResourceId;
if (resourceId == null) {
upgradeResourceId = String.format("%s-%s-UPGRADE", resource.getResourceId(), extensionOf.getPath());
} else if (resourceId.isBlank()) {
throw new BadRequestException("'resourceId' property should not be empty, if provided");
} else {
BranchNameValidator.DEFAULT.checkName(resourceId);
upgradeResourceId = resourceId;
}
String mergeContentFromBranchPath = currentCodeSystem.getBranchPath();
// only allow HEAD or valid code system versions
if (!resource.isHead()) {
mergeContentFromBranchPath = new DefaultResourceURIPathResolver(false).resolve(context, List.of(resource)).stream().findFirst().get();
}
// create the same branch name under the new extensionOf path
String parentBranch = context.service(ResourceURIPathResolver.class).resolve(context, List.of(extensionOf)).stream().findFirst().get();
// merge content in the tooling repository from the current resource's to the upgrade resource's branch
final String upgradeBranch = RepositoryRequests.branching().prepareCreate().setParent(parentBranch).setName(resource.getResourceId()).build(currentCodeSystem.getToolingId()).getRequest().execute(context);
try {
// merge branch content from the current code system to the new upgradeBranch
Merge merge = RepositoryRequests.merging().prepareCreate().setSource(mergeContentFromBranchPath).setTarget(upgradeBranch).setSquash(false).build(currentCodeSystem.getToolingId()).getRequest().execute(context);
if (merge.getStatus() != Merge.Status.COMPLETED) {
// report conflicts
ApiError apiError = merge.getApiError();
Collection<MergeConflict> conflicts = merge.getConflicts();
context.log().error("Failed to sync source CodeSystem content to upgrade CodeSystem. Error: {}. Conflicts: {}", apiError.getMessage(), conflicts);
throw new ConflictException("Upgrade can not be performed due to content synchronization errors.").withAdditionalInfo(Map.of("conflicts", conflicts, "mergeError", apiError.getMessage()));
}
// and lastly create the actual CodeSystem so users will be able to browse, access and complete the upgrade
return CodeSystemRequests.prepareNewCodeSystem().setId(upgradeResourceId).setBranchPath(upgradeBranch).setTitle(String.format("Upgrade of '%s' to '%s'", currentCodeSystem.getTitle(), extensionOf)).setUrl(currentCodeSystem.getUrl() + "?upgrade=" + upgradeResourceId).setLanguage(currentCodeSystem.getLanguage()).setDescription(currentCodeSystem.getDescription()).setStatus("draft").setCopyright(currentCodeSystem.getCopyright()).setOwner(currentCodeSystem.getOwner()).setContact(currentCodeSystem.getContact()).setUsage(currentCodeSystem.getUsage()).setPurpose(currentCodeSystem.getPurpose()).setToolingId(currentCodeSystem.getToolingId()).setExtensionOf(extensionOf).setUpgradeOf(resource).setSettings(currentCodeSystem.getSettings()).commit().setCommitComment(String.format("Start upgrade of '%s' to '%s'", resource, extensionOf)).build().execute(context.openBranch(context, Branch.MAIN_PATH)).getResultAs(String.class);
} catch (Throwable e) {
// delete upgrade branch if any exception have been thrown during the upgrade
RepositoryRequests.branching().prepareDelete(upgradeBranch).build(currentCodeSystem.getToolingId()).getRequest().execute(context);
throw e;
}
}
Aggregations