001package ca.uhn.hl7v2.conf.store;
002
003import java.util.StringTokenizer;
004
005import org.slf4j.Logger;
006import org.slf4j.LoggerFactory;
007
008/**
009 * Abstract class for used retrieving and validating codes from user defined and HL7 specific tables
010 * that correspond to a conformance profile.
011 * 
012 * @author Neal Acharya
013 */
014public abstract class AbstractCodeStore implements CodeStore {
015
016    private static Logger log = LoggerFactory.getLogger(AbstractCodeStore.class);
017    
018    private static final RegisteredPattern[] WILDCARDS = { 
019            new RegisteredPattern("ISOnnnn", "ISO\\d\\d\\d\\d"),
020            new RegisteredPattern("HL7nnnn", "HL7\\d\\d\\d\\d"), 
021            new RegisteredPattern("99zzz", "99[\\w]*"),
022            new RegisteredPattern("NNxxx", "99[\\w]*") 
023            };
024
025    /**
026     * @see ca.uhn.hl7v2.conf.store.CodeStore#isValidCode(java.lang.String, java.lang.String)
027     */
028    public boolean isValidCode(String codeSystem, String code) {
029        try {
030            for (String validCode : getValidCodes(codeSystem)) {
031                if (checkCode(code, validCode)) return true;
032            }
033            return false;
034        }
035        catch (Exception e) {
036            log.error("Error checking code " + code + " in code system " + codeSystem, e);
037            return false;
038        } 
039    }
040
041    /**
042     * Checks a code for an exact match, and using certain sequences where some characters are
043     * wildcards (e.g. HL7nnnn). If the pattern contains one of " or ", " OR ", or "," each operand
044     * is checked.
045     */
046    private boolean checkCode(String code, String pattern) {
047        // mod by Neal acharya - Do full match on with the pattern. If code matches pattern then
048        // return true
049        // else parse pattern to look for wildcard characters
050        if (code.equals(pattern)) return true;
051        
052        if (pattern.indexOf(' ') >= 0 || pattern.indexOf(',') >= 0) {
053            StringTokenizer tok = new StringTokenizer(pattern, ", ", false);
054            while (tok.hasMoreTokens()) {
055                String t = tok.nextToken();
056                if (!t.equalsIgnoreCase("or") && checkCode(code, t)) 
057                    return true;
058            }
059        } else {
060            for (RegisteredPattern wildcard : WILDCARDS) {
061                if (wildcard.matches(pattern, code)) 
062                    return true;
063            }
064        }
065        
066        return false;
067    }
068
069}