001/*-
002 * #%L
003 * HAPI FHIR - Server Framework
004 * %%
005 * Copyright (C) 2014 - 2024 Smile CDR, Inc.
006 * %%
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 * You may obtain a copy of the License at
010 *
011 *      http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 * #L%
019 */
020package ca.uhn.fhir.rest.server.interceptor.validation;
021
022import ca.uhn.fhir.interceptor.api.Hook;
023import ca.uhn.fhir.interceptor.api.Interceptor;
024import ca.uhn.fhir.interceptor.api.Pointcut;
025import ca.uhn.fhir.validation.SingleValidationMessage;
026import ca.uhn.fhir.validation.ValidationResult;
027
028import java.util.ArrayList;
029import java.util.Arrays;
030import java.util.List;
031import java.util.regex.Pattern;
032
033import static org.apache.commons.lang3.StringUtils.isNotBlank;
034
035@Interceptor
036public class ValidationMessageSuppressingInterceptor {
037
038        private List<Pattern> mySuppressPatterns = new ArrayList<>();
039
040        /**
041         * Constructor
042         */
043        public ValidationMessageSuppressingInterceptor() {
044                super();
045        }
046
047        /**
048         * Supplies one or more patterns to suppress. Any validation messages (of any severity) will be suppressed
049         * if they match this pattern. Patterns are in Java Regular Expression format (as defined by the {@link Pattern} class)
050         * and are treated as partial maches. They are also case insensitive.
051         * <p>
052         *    For example, a pattern of <code>loinc.*1234</code> would suppress the following message:<br/>
053         *    <code>The LOINC code 1234 is not valid</code>
054         * </p>
055         */
056        public ValidationMessageSuppressingInterceptor addMessageSuppressionPatterns(String... thePatterns) {
057                return addMessageSuppressionPatterns(Arrays.asList(thePatterns));
058        }
059
060        /**
061         * Supplies one or more patterns to suppress. Any validation messages (of any severity) will be suppressed
062         * if they match this pattern. Patterns are in Java Regular Expression format (as defined by the {@link Pattern} class)
063         * and are treated as partial maches. They are also case insensitive.
064         * <p>
065         *    For example, a pattern of <code>loinc.*1234</code> would suppress the following message:<br/>
066         *    <code>The LOINC code 1234 is not valid</code>
067         * </p>
068         */
069        public ValidationMessageSuppressingInterceptor addMessageSuppressionPatterns(List<String> thePatterns) {
070                for (String next : thePatterns) {
071                        if (isNotBlank(next)) {
072                                Pattern pattern = Pattern.compile(next, Pattern.CASE_INSENSITIVE);
073                                mySuppressPatterns.add(pattern);
074                        }
075                }
076                return this;
077        }
078
079        @Hook(Pointcut.VALIDATION_COMPLETED)
080        public ValidationResult handle(ValidationResult theResult) {
081
082                List<SingleValidationMessage> newMessages =
083                                new ArrayList<>(theResult.getMessages().size());
084                for (SingleValidationMessage next : theResult.getMessages()) {
085
086                        String nextMessage = next.getMessage();
087                        boolean suppress = false;
088                        for (Pattern nextSuppressPattern : mySuppressPatterns) {
089                                if (nextSuppressPattern.matcher(nextMessage).find()) {
090                                        suppress = true;
091                                        break;
092                                }
093                        }
094
095                        if (!suppress) {
096                                newMessages.add(next);
097                        }
098                }
099
100                if (newMessages.size() == theResult.getMessages().size()) {
101                        return null;
102                }
103
104                return new ValidationResult(theResult.getContext(), newMessages);
105        }
106}