001package ca.uhn.fhir.jpa.bulk.export.job;
002
003/*-
004 * #%L
005 * HAPI FHIR JPA Server
006 * %%
007 * Copyright (C) 2014 - 2021 Smile CDR, Inc.
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 *
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023import ca.uhn.fhir.jpa.batch.config.BatchConstants;
024import ca.uhn.fhir.jpa.dao.data.IBulkExportJobDao;
025import ca.uhn.fhir.jpa.entity.BulkExportJobEntity;
026import ca.uhn.fhir.rest.api.Constants;
027import org.apache.commons.lang3.StringUtils;
028import org.springframework.batch.core.JobParameters;
029import org.springframework.batch.core.JobParametersInvalidException;
030import org.springframework.batch.core.JobParametersValidator;
031import org.springframework.beans.factory.annotation.Autowired;
032import org.springframework.transaction.PlatformTransactionManager;
033import org.springframework.transaction.support.TransactionTemplate;
034
035import java.util.Arrays;
036import java.util.Optional;
037
038/**
039 * This class will prevent a job from running if the UUID does not exist or is invalid.
040 */
041public class BulkExportJobParameterValidator implements JobParametersValidator {
042
043        @Autowired
044        private IBulkExportJobDao myBulkExportJobDao;
045        @Autowired
046        private PlatformTransactionManager myTransactionManager;
047
048        @Override
049        public void validate(JobParameters theJobParameters) throws JobParametersInvalidException {
050                if (theJobParameters == null) {
051                        throw new JobParametersInvalidException("This job needs Parameters: [readChunkSize], [jobUUID], [filters], [outputFormat], [resourceTypes]");
052                }
053
054                TransactionTemplate txTemplate = new TransactionTemplate(myTransactionManager);
055                String errorMessage = txTemplate.execute(tx -> {
056                        StringBuilder errorBuilder = new StringBuilder();
057                        Long readChunkSize = theJobParameters.getLong(BulkExportJobConfig.READ_CHUNK_PARAMETER);
058                        if (readChunkSize == null || readChunkSize < 1) {
059                                errorBuilder.append("There must be a valid number for readChunkSize, which is at least 1. ");
060                        }
061                        String jobUUID = theJobParameters.getString(BatchConstants.JOB_UUID_PARAMETER);
062                        Optional<BulkExportJobEntity> oJob = myBulkExportJobDao.findByJobId(jobUUID);
063                        if (!StringUtils.isBlank(jobUUID) && !oJob.isPresent()) {
064                                errorBuilder.append("There is no persisted job that exists with UUID: " + jobUUID + ". ");
065                        }
066
067
068                        boolean hasExistingJob = oJob.isPresent();
069                        //Check for to-be-created parameters.
070                        if (!hasExistingJob) {
071                                String resourceTypes = theJobParameters.getString(BulkExportJobConfig.RESOURCE_TYPES_PARAMETER);
072                                if (StringUtils.isBlank(resourceTypes)) {
073                                        errorBuilder.append("You must include [").append(BulkExportJobConfig.RESOURCE_TYPES_PARAMETER).append("] as a Job Parameter");
074                                } else {
075                                        String[] resourceArray = resourceTypes.split(",");
076                                        Arrays.stream(resourceArray).filter(resourceType -> resourceType.equalsIgnoreCase("Binary"))
077                                                .findFirst()
078                                                .ifPresent(resourceType -> {
079                                                        errorBuilder.append("Bulk export of Binary resources is forbidden");
080                                                });
081                                }
082
083                                String outputFormat = theJobParameters.getString("outputFormat");
084                                if (!StringUtils.isBlank(outputFormat) && !Constants.CT_FHIR_NDJSON.equals(outputFormat)) {
085                                        errorBuilder.append("The only allowed format for Bulk Export is currently " + Constants.CT_FHIR_NDJSON);
086                                }
087                        }
088
089                        return errorBuilder.toString();
090                });
091
092                if (!StringUtils.isEmpty(errorMessage)) {
093                        throw new JobParametersInvalidException(errorMessage);
094                }
095        }
096}