001/**
002The contents of this file are subject to the Mozilla Public License Version 1.1 
003(the "License"); you may not use this file except in compliance with the License. 
004You may obtain a copy of the License at http://www.mozilla.org/MPL/ 
005Software distributed under the License is distributed on an "AS IS" basis, 
006WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the 
007specific language governing rights and limitations under the License. 
008
009The Original Code is "MessageRuleBuilder.java".  Description: 
010"Rule Builder for MessageRules." 
011
012The Initial Developer of the Original Code is University Health Network. Copyright (C) 
0132012.  All Rights Reserved. 
014
015Contributor(s): ______________________________________. 
016
017Alternatively, the contents of this file may be used under the terms of the 
018GNU General Public License (the "GPL"), in which case the provisions of the GPL are 
019applicable instead of those above.  If you wish to allow use of your version of this 
020file only under the terms of the GPL and not to allow others to use your version 
021of this file under the MPL, indicate your decision by deleting  the provisions above 
022and replace  them with the notice and other provisions required by the GPL License.  
023If you do not delete the provisions above, a recipient may use your version of 
024this file under either the MPL or the GPL. 
025 */
026package ca.uhn.hl7v2.validation.builder;
027
028import java.util.*;
029
030import ca.uhn.hl7v2.Version;
031import ca.uhn.hl7v2.model.MessageVisitorFactory;
032import ca.uhn.hl7v2.validation.MessageRule;
033import ca.uhn.hl7v2.validation.Rule;
034import ca.uhn.hl7v2.validation.builder.support.*;
035import ca.uhn.hl7v2.validation.impl.ConformanceProfileRule;
036import ca.uhn.hl7v2.validation.impl.MessageRuleBinding;
037import ca.uhn.hl7v2.validation.impl.RuleBinding;
038
039/**
040 * Rule Builder for MessageRules
041 * 
042 * @author Christian Ohr
043 */
044@SuppressWarnings("serial")
045public class MessageRuleBuilder extends RuleTypeBuilder<MessageRuleBuilder, MessageRule> {
046
047        private String messageType;
048        private String[] triggerEvents;
049
050        protected MessageRuleBuilder(List<RuleBinding<? extends Rule<?>>> rules, Set<Version> versions,
051                        String messageType, String... triggerEvents) {
052                super(rules, versions);
053                this.messageType = messageType;
054                this.triggerEvents = triggerEvents;
055        }
056        
057        /**
058         * Builds a {@link MessageRule} that extracts a primitive value using a {@link ca.uhn.hl7v2.util.Terser}
059         * expression and evaluates the specified {@link Predicate}.
060         * 
061         * @param spec Terser expression
062         * @param predicate Predicate to evaluate against the value
063         * @return this instance to build more rules
064         */
065        public MessageRuleBuilder terser(String spec, Predicate predicate) {
066                return test(prepareRule(new TerserMessageRule(spec, predicate)));
067        }
068
069    /**
070     * Builds a {@link MessageRule} that runs a
071     * {@link ca.uhn.hl7v2.validation.builder.support.ValidatingMessageVisitor ValidatingMessageVisitor}
072     * over the message that collects {@link ca.uhn.hl7v2.validation.ValidationException ValidationExceptions}
073     * in a single pass.
074     *
075     * @param visitorFactory MessageVisitorFactory that creates ValidatingMessageVisitor instances
076     * @return this instance to build more rules
077     */
078    public MessageRuleBuilder inspect(MessageVisitorFactory<? extends ValidatingMessageVisitor> visitorFactory) {
079        return test(prepareRule(new VisitorMessageRule(visitorFactory)));
080    }
081
082        /**
083         * Builds a {@link MessageRule} that disallows the existence of {@link ca.uhn.hl7v2.model.GenericSegment}s, i.e.
084         * segments that are not defined in the structure of a message.
085         * 
086         * @return this instance to build more rules
087         */
088        public MessageRuleBuilder onlyKnownSegments() {
089                return test(prepareRule(OnlyKnownSegmentsRule.ONLY_KNOWN_SEGMENTS));
090        }
091
092        /**
093         * Builds a {@link MessageRule} that disallows the existence of segments which
094         * are not alowed in a given message type when the message is an instance
095         * of {@link ca.uhn.hl7v2.model.SuperStructure} (e.g. PID2 within an ADT^A01)
096         * 
097         * @return this instance to build more rules
098         */
099        public MessageRuleBuilder onlyAllowableSegmentsInSuperStructure() {
100                return test(prepareRule(OnlyAllowableSegmentsInSuperstructureRule.ONLY_ALLOWABLE_SEGMENTS));
101        }
102
103        /**
104         * Builds a {@link MessageRule} that enforces choice elements. This means that
105         * if several segments are listed as being a possible choice for the first segment
106         * in a group, only one of them may have content.
107         * 
108         * @return this instance to build more rules
109         */
110        public MessageRuleBuilder choiceElementsRespected() {
111                return test(prepareRule(ChoiceElementsRespectedRule.CHOICE_ELEMENTS_RESPECTED));
112        }
113
114        /**
115         * Builds a {@link MessageRule} that disallows the selected HL7 version(s). It is basically
116         * equivalent with:
117         * 
118         * <pre>
119         *    forAllVersions().message(....).terser("MSH-12", in(allowedVersions))
120         * </pre>
121         * 
122         * However, when using this specific rule the builder expression and the resulting exception
123         * message is more specific:
124         * 
125         * <pre>
126         *        forVersion().except(allowedVersions).message(...).wrongVersion()
127         * </pre>
128         * 
129         * @return this instance to build more rules
130         */
131        public MessageRuleBuilder wrongVersion() {
132                return test(prepareRule(WrongVersionRule.WRONG_VERSION));
133        }
134
135        /**
136         * Builds a {@link MessageRule} that evaluates the message against the Conformance Profile
137         * referred to in MSH-21.
138         * 
139         * @return this instance to build more rules
140         */
141        public MessageRuleBuilder conformance() {
142                return conformance(null);
143        }
144
145        /**
146         * Builds a {@link MessageRule} that evaluates the message against the Conformance Profile
147         * referred to by the profileId parameter
148         *
149     * @param profileId conformance profile id (file name)
150         * @return this instance to build more rules
151         */
152        public MessageRuleBuilder conformance(String profileId) {
153                return test(prepareRule(new ConformanceProfileRule(profileId)));
154        }
155
156        // for tests only
157        String getMessageType() {
158                return messageType;
159        }
160
161        // for tests only
162        String[] getTriggerEvents() {
163                return triggerEvents;
164        }
165
166        @Override
167        protected Collection<RuleBinding<MessageRule>> getRuleBindings(MessageRule rule, String version) {
168        List<RuleBinding<MessageRule>> bindings = new ArrayList<RuleBinding<MessageRule>>();
169        for (String triggerEvent : triggerEvents) {
170            bindings.add(new MessageRuleBinding(version, messageType,
171                    triggerEvent, rule));
172        }
173                return activate(bindings);
174        }
175
176}