001 package ca.uhn.hl7v2.conf.store;
002 import java.util.StringTokenizer;
003 import java.util.regex.Pattern;
004
005 import org.slf4j.Logger;
006 import org.slf4j.LoggerFactory;
007
008 /**
009 * Created on 27-Aug-2003
010 * @author Neal Acharya
011 * Abstract class for used retreiving and validating codes from user defined and HL7 specific tables
012 * that correspond to a conformance profile.
013 */
014 public abstract class AbstractCodeStore implements CodeStore {
015
016 private static Logger log = LoggerFactory.getLogger(AbstractCodeStore.class);
017 private WildcardPattern[] wildcards;
018
019 /**
020 * @param codeSystem
021 * @param code
022 * @return boolean
023 * @see ca.uhn.hl7v2.conf.store.CodeStore#isValidCode(java.lang.String, java.lang.String, java.lang.String)
024 *
025 * Validates the input code value against the input conformance profile and corresponding input
026 * codeSystem. Returns true if the code is valid and false if it isn't.
027 */
028 public boolean isValidCode(String codeSystem, String code) {
029 try {
030 String[] validCodes = getValidCodes(codeSystem);
031 boolean found = false;
032 for (int i = 0; i < validCodes.length && !found; i++) {
033 if (checkCode(code, validCodes[i])) {
034 found = true;
035 } //end if
036 } //end for
037 return found;
038 } //end try
039 catch (Exception e) {
040 log.error("Error checking code " + code + " in code system " + codeSystem, e);
041 return false;
042 } //end catch
043 } //end method
044
045 /**
046 * Checks a code for an exact match, and using certain sequences where some
047 * characters are wildcards (e.g. HL7nnnn). If the pattern contains one of
048 * " or ", " OR ", or "," each operand is checked.
049 */
050 private boolean checkCode(String code, String pattern) {
051 boolean match = false;
052 //mod by Neal acharya - Do full match on with the pattern. If code matches pattern then return true
053 //else parse pattern to look for wildcard characters
054 if (code.equals(pattern)) {
055 match = true;
056 } //end if
057 else {
058 if (pattern.indexOf(' ') >= 0 || pattern.indexOf(',') >= 0) {
059 StringTokenizer tok = new StringTokenizer(pattern, ", ", false);
060 while (tok.hasMoreTokens() && !match) {
061 String t = tok.nextToken();
062 if (!t.equalsIgnoreCase("or"))
063 match = checkCode(code, t);
064 }//end while
065 }//end if
066 else {
067 if (code.equals(pattern)) {
068 match = true;
069 }//end if
070 else {
071 WildcardPattern[] wc = getWildcards();
072 for (int i = 0; i < wc.length && !match; i++) {
073 if (pattern.equals(wc[i].pattern))
074 match = wc[i].regex.matcher(code).matches();
075 }//end for
076 }//end else
077 }//end else
078 } //end else
079 return match;
080 }//end method
081
082 /** Returns a list of wildcard-containing patterns and corresponding regular expressions */
083 private synchronized WildcardPattern[] getWildcards() {
084 if (wildcards == null) {
085 wildcards = new WildcardPattern[4];
086 wildcards[0] = new WildcardPattern("ISOnnnn", "ISO\\d\\d\\d\\d");
087 wildcards[1] = new WildcardPattern("HL7nnnn", "HL7\\d\\d\\d\\d");
088 wildcards[2] = new WildcardPattern("99zzz", "99[\\w]*");
089 wildcards[3] = new WildcardPattern("NNxxx", "99[\\w]*");
090 }
091 return wildcards;
092 }
093
094 /** A struct of a wildcard-containing code pattern and corresponding regex */
095 private static class WildcardPattern {
096 public String pattern;
097 public Pattern regex;
098 public WildcardPattern(String p, String r) {
099 pattern = p;
100 regex = Pattern.compile(r);
101 }
102 }
103
104 } //end class