001 package ca.uhn.hl7v2.conf.store; 002 import java.io.IOException; 003 import ca.uhn.hl7v2.conf.ProfileException; 004 import ca.uhn.log.*; 005 import java.util.regex.*; 006 import java.util.StringTokenizer; 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 HapiLog log = HapiLogFactory.getHapiLog(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