001package org.hl7.fhir.validation.ipa;
002
003import java.io.ByteArrayInputStream;
004import java.util.ArrayList;
005import java.util.List;
006import java.util.Map;
007
008import org.hl7.fhir.r5.elementmodel.Element;
009import org.hl7.fhir.r5.elementmodel.JsonParser;
010import org.hl7.fhir.utilities.SimpleHTTPClient;
011import org.hl7.fhir.utilities.SimpleHTTPClient.HTTPResult;
012import org.hl7.fhir.utilities.validation.ValidationMessage;
013import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
014import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
015import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
016import org.hl7.fhir.validation.instance.InstanceValidator;
017
018/**
019 * You give this validator three parameters:
020 *   URL of server
021 *   access token for the server (most be already logged in)
022 *   patient ID - the patient ID that was authorised by the log in
023 *   
024 * @author grahamegrieve
025 *
026 */
027public class IPAValidator {
028
029  public class ValidationNode {
030
031    public ValidationNode(String string) {
032      // TODO Auto-generated constructor stub
033    }
034
035    public List<ValidationMessage> getIssues() {
036      // TODO Auto-generated method stub
037      return null;
038    }
039
040    public String getName() {
041      // TODO Auto-generated method stub
042      return null;
043    }
044
045  }
046
047  private String address;
048  private String token;
049  private String urn;
050  private InstanceValidator validator;
051  
052  public IPAValidator(String address, String token, String urn, InstanceValidator validator) {
053    super();
054    this.address = address;
055    this.token = token;
056    this.urn = urn;
057    this.validator = validator;
058  }
059  
060  public String getAddress() {
061    return address;
062  }
063  
064  public void setAddress(String address) {
065    this.address = address;
066  }
067  
068  public String getToken() {
069    return token;
070  }
071  
072  public void setToken(String token) {
073    this.token = token;
074  }
075  
076  public String getUrn() {
077    return urn;
078  }
079  
080  public void setUrn(String urn) {
081    this.urn = urn;
082  }
083  
084  public InstanceValidator getValidator() {
085    return validator;
086  }
087  
088  public void setValidator(InstanceValidator validator) {
089    this.validator = validator;
090  }
091
092  public void validate() {
093    List<Element> patients = searchPatients();
094    if (patients.size() > 0) {
095      
096    // validate all resources and links
097    // validate search parameters
098    // check self links
099    
100//    AllergyIntolerance  patient patient+clinical-status
101//    Condition patient patient+category, patient+clinical-status, patient+code, patient+onset-date, patient+category+clinical_status
102//    DocumentReference _id, patient, patient+category, patient+type  patient+category+date, patient+status, patient+type+period
103//    Immunization  patient patient+date, patient+status
104//    MedicationRequest patient patient+intent, patient+intent+authoredon, patient+intent+status
105//    MedicationStatement subject subject+status
106//    Observation patient+category, patient+code, patient+category+date patient+category+status, patient+code+date
107//    Patient _id, identifier birthdate, family, gender, given, name, family+gender, birthdate+family, birthdate+name, gender+name
108    
109    }
110    
111    
112    
113  }
114
115  private List<Element> searchPatients() {
116    ValidationNode vn = new ValidationNode("Patient Search");
117    log("Searching Patients");
118    Element bundle = makeRequest(vn, "/Patient");
119    List<Element> list = new ArrayList<>();
120    if (bundle != null) {
121      checkSelfLink(vn, bundle, null);
122      List<Element> entries = bundle.getChildren("entry");
123      int i = 0;
124      for (Element entry : entries) {
125        Element resource = entry.getNamedChild("resource");
126        if (resource != null && resource.fhirType().equals("Patient")) {
127          validator.validate(this, vn.getIssues(), "Bundle.entry["+i+"].resource", resource, "http://hl7.org/fhir/uv/ipa/StructureDefinition/ipa-patient");        
128          list.add(resource);
129        }
130      }
131    }
132    if (list.size() > 1) {
133      vn.getIssues().add(new ValidationMessage(Source.IPAValidator, IssueType.EXCEPTION, "patient.search", 
134          "Multiple Patients found; check that this is an expected outcome",
135          IssueSeverity.WARNING));              
136    } else if (list.size() == 0) {
137      vn.getIssues().add(new ValidationMessage(Source.IPAValidator, IssueType.EXCEPTION, "patient.search", 
138          "No Patients found, unable to continue",
139          IssueSeverity.ERROR));              
140    }
141    return list;
142  }
143
144  private void checkSelfLink(ValidationNode vn, Element bundle, Map<String, String> params) {
145    // we check that there's a self link 
146    Element sl = null;
147    for (Element e : bundle.getChildren("link")) {
148      if ("self".equals(e.getNamedChildValue("relation"))) {
149        sl = e.getNamedChild("url");
150      }
151    }
152    if (sl == null) {
153      vn.getIssues().add(new ValidationMessage(Source.IPAValidator, IssueType.EXCEPTION, vn.getName(), 
154          "Self link not found in search result",
155          IssueSeverity.ERROR));                    
156    } else if (params != null) {
157      // we check that all the provided params are in the self link
158    }
159  }
160
161  private Element makeRequest(ValidationNode vn, String url)  {
162    try {
163      SimpleHTTPClient http = new SimpleHTTPClient();
164      HTTPResult result = http.get(url, "application/fhir+json");
165      if (result.getCode() >= 300) {
166        vn.getIssues().add(new ValidationMessage(Source.IPAValidator, IssueType.EXCEPTION, "http.request", 
167            "HTTP Return code is "+result.getCode()+" "+result.getMessage(),
168            IssueSeverity.FATAL));        
169        return null;
170      } else if (result.getContent() == null || result.getContent().length == 0) {
171        vn.getIssues().add(new ValidationMessage(Source.IPAValidator, IssueType.EXCEPTION, "http.request", 
172            "No Content Returned",
173            IssueSeverity.FATAL));        
174        return null;
175      } else {
176        return new JsonParser(validator.getContext()).parse(new ByteArrayInputStream(result.getContent())).get(0).getElement();
177      }
178    } catch (Exception e) {
179      vn.getIssues().add(new ValidationMessage(Source.IPAValidator, IssueType.EXCEPTION, "http.request", e.getMessage(),
180          IssueSeverity.FATAL));
181      return null;
182    }
183    
184  }
185
186  private void log(String msg) {
187    System.out.println(msg);
188  }
189}