<commit_before>package uk.nhs.careconnect.ccri.fhirserver.provider;

import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.rest.annotation.*;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.ValidationModeEnum;
import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;


import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;

import org.apache.http.impl.client.HttpClientBuilder;

import org.hl7.fhir.dstu3.model.*;

import org.hl7.fhir.instance.model.api.IBaseResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import uk.nhs.careconnect.ccri.fhirserver.OperationOutcomeFactory;

import uk.nhs.careconnect.ccri.fhirserver.ProviderResponseLibrary;
import uk.nhs.careconnect.ri.database.daointerface.ValueSetRepository;

import javax.servlet.http.HttpServletRequest;

import java.io.InputStreamReader;
import java.io.Reader;
import java.net.UnknownHostException;
import java.util.List;

@Component
public class ValueSetProvider implements ICCResourceProvider {


	@Autowired
	FhirContext ctx;

    @Autowired
    private ValueSetRepository valueSetDao;
    
    @Autowired
    private ResourcePermissionProvider resourcePermissionProvider;
    
    @Value("${ccri.valueSetHost}")
	private String valueSetHost;
    
    @Override
    public Class<ValueSet> getResourceType() {
        return ValueSet.class;
    }

    @Override
    public Long count() {
        return valueSetDao.count();
    }

    @Autowired
    private ResourceTestProvider resourceTestProvider;

    private static final Logger log = LoggerFactory.getLogger(ValueSetProvider.class);


    @Update()
    public MethodOutcome update(HttpServletRequest theRequest,@ResourceParam ValueSet valueSet) {

    	resourcePermissionProvider.checkPermission("update");
        MethodOutcome method = new MethodOutcome();
        method.setCreated(true);
        OperationOutcome opOutcome = new OperationOutcome();

        method.setOperationOutcome(opOutcome);


        try {
            ValueSet newValueSet = valueSetDao.create(ctx, valueSet);
            method.setId(newValueSet.getIdElement());
            method.setResource(newValueSet);
        } catch (Exception ex) {
            ProviderResponseLibrary.handleException(method,ex);
        }


        return method;
    }

    @Search
    public List<ValueSet> search(HttpServletRequest theRequest,
              @OptionalParam(name =ValueSet.SP_NAME) StringParam name,
             //  @OptionalParam(name =ValueSet.SP_PUBLISHER) StringParam publisher,
                                 @OptionalParam(name = ValueSet.SP_URL) UriParam url,
                                @OptionalParam(name = ValueSet.SP_IDENTIFIER) TokenParam identifier
    ) {
        return valueSetDao.search(ctx, name, null, url,identifier);
    }




    @Create
    public MethodOutcome create(HttpServletRequest theRequest, @ResourceParam ValueSet valueSet) {

    	resourcePermissionProvider.checkPermission("create");
        MethodOutcome method = new MethodOutcome();
        method.setCreated(true);
        OperationOutcome opOutcome = new OperationOutcome();

        method.setOperationOutcome(opOutcome);


        try {
            ValueSet newValueSet = valueSetDao.create(ctx, valueSet);
            method.setId(newValueSet.getIdElement());
            method.setResource(newValueSet);
        } catch (Exception ex) {
            ProviderResponseLibrary.handleException(method,ex);
        }

        return method;
    }

    @Read
    public ValueSet get
            (@IdParam IdType internalId) {
    	resourcePermissionProvider.checkPermission("read");
        ValueSet valueSet = valueSetDao.read(ctx, internalId);

        if ( valueSet == null) {
            throw OperationOutcomeFactory.buildOperationOutcomeException(
                    new ResourceNotFoundException("No ValueSet/" + internalId.getIdPart()),
                    OperationOutcome.IssueSeverity.ERROR, OperationOutcome.IssueType.NOTFOUND);
        }

        return valueSet;
    }
    
    @Validate
    public MethodOutcome testResource(@ResourceParam ValueSet resource,
                                  @Validate.Mode ValidationModeEnum theMode,
                                  @Validate.Profile String theProfile) {
        return resourceTestProvider.testResource(resource,theMode,theProfile);
    }

    @Operation(name = "$expand", idempotent = true, bundleType= BundleTypeEnum.COLLECTION)
    public ValueSet expand(
            @IdParam IdType internalId

    ) throws Exception {
        resourcePermissionProvider.checkPermission("read");
        ValueSet valueSet = valueSetDao.readAndExpand(ctx, internalId);

        if ( valueSet == null) {
            throw OperationOutcomeFactory.buildOperationOutcomeException(
                    new ResourceNotFoundException("No ValueSet/" + internalId.getIdPart()),
                    OperationOutcome.IssueSeverity.ERROR, OperationOutcome.IssueType.NOTFOUND);
        }

        return valueSet;

    }

    @Operation(name = "$refresh", idempotent = true, bundleType= BundleTypeEnum.COLLECTION)
    public MethodOutcome getValueCodes(
            @OperationParam(name="id") TokenParam valueSetId,
            @OperationParam(name="query") ReferenceParam valueSetQuery

    ) throws Exception {

    	System.out.println("getting value sets" + valueSetHost);
    	<commit_msg>Expanding SNOMED in filters<commit_after>package uk.nhs.careconnect.ccri.fhirserver.provider;

import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.rest.annotation.*;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.ValidationModeEnum;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.client.impl.GenericClient;
import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;


import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;

import org.apache.http.impl.client.HttpClientBuilder;

import org.hl7.fhir.dstu3.model.*;

import org.hl7.fhir.instance.model.api.IBaseResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import uk.nhs.careconnect.ccri.fhirserver.OperationOutcomeFactory;

import uk.nhs.careconnect.ccri.fhirserver.ProviderResponseLibrary;
import uk.nhs.careconnect.ri.database.daointerface.ValueSetRepository;

import javax.servlet.http.HttpServletRequest;

import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Parameter;
import java.net.UnknownHostException;
import java.util.List;

@Component
public class ValueSetProvider implements ICCResourceProvider {


	@Autowired
	FhirContext ctx;


	IGenericClient client;

    @Autowired
    private ValueSetRepository valueSetDao;
    
    @Autowired
    private ResourcePermissionProvider resourcePermissionProvider;
    
    @Value("${ccri.valueSetHost}")
	private String valueSetHost;
    
    @Override
    public Class<ValueSet> getResourceType() {
        return ValueSet.class;
    }

    @Override
    public Long count() {
        return valueSetDao.count();
    }

    @Autowired
    private ResourceTestProvider resourceTestProvider;

    private static final Logger log = LoggerFactory.getLogger(ValueSetProvider.class);


    @Update()
    public MethodOutcome update(HttpServletRequest theRequest,@ResourceParam ValueSet valueSet) {

    	resourcePermissionProvider.checkPermission("update");
        MethodOutcome method = new MethodOutcome();
        method.setCreated(true);
        OperationOutcome opOutcome = new OperationOutcome();

        method.setOperationOutcome(opOutcome);


        try {
            ValueSet newValueSet = valueSetDao.create(ctx, valueSet);
            method.setId(newValueSet.getIdElement());
            method.setResource(newValueSet);
        } catch (Exception ex) {
            ProviderResponseLibrary.handleException(method,ex);
        }


        return method;
    }

    @Search
    public List<ValueSet> search(HttpServletRequest theRequest,
              @OptionalParam(name =ValueSet.SP_NAME) StringParam name,
             //  @OptionalParam(name =ValueSet.SP_PUBLISHER) StringParam publisher,
                                 @OptionalParam(name = ValueSet.SP_URL) UriParam url,
                                @OptionalParam(name = ValueSet.SP_IDENTIFIER) TokenParam identifier
    ) {
        return valueSetDao.search(ctx, name, null, url,identifier);
    }




    @Create
    public MethodOutcome create(HttpServletRequest theRequest, @ResourceParam ValueSet valueSet) {

    	resourcePermissionProvider.checkPermission("create");
        MethodOutcome method = new MethodOutcome();
        method.setCreated(true);
        OperationOutcome opOutcome = new OperationOutcome();

        method.setOperationOutcome(opOutcome);


        try {
            ValueSet newValueSet = valueSetDao.create(ctx, valueSet);
            method.setId(newValueSet.getIdElement());
            method.setResource(newValueSet);
        } catch (Exception ex) {
            ProviderResponseLibrary.handleException(method,ex);
        }

        return method;
    }

    @Read
    public ValueSet get
            (@IdParam IdType internalId) {
    	resourcePermissionProvider.checkPermission("read");
        ValueSet valueSet = valueSetDao.read(ctx, internalId);

        if ( valueSet == null) {
            throw OperationOutcomeFactory.buildOperationOutcomeException(
                    new ResourceNotFoundException("No ValueSet/" + internalId.getIdPart()),
                    OperationOutcome.IssueSeverity.ERROR, OperationOutcome.IssueType.NOTFOUND);
        }

        return valueSet;
    }
    
    @Validate
    public MethodOutcome testResource(@ResourceParam ValueSet resource,
                                  @Validate.Mode ValidationModeEnum theMode,
                                  @Validate.Profile String theProfile) {
        return resourceTestProvider.testResource(resource,theMode,theProfile);
    }

    @Operation(name = "$expand", idempotent = true, bundleType= BundleTypeEnum.COLLECTION)
    public ValueSet expand(
            @IdParam IdType internalId

    ) throws Exception {
        resourcePermissionProvider.checkPermission("read");
        ValueSet valueSet = valueSetDao.readAndExpand(ctx, internalId);

        if (!valueSet.hasExpansion()&&valueSet.hasCompose()) {
            if (valueSet.getCompose().hasInclude()) {
               for (ValueSet.ConceptSetComponent include : valueSet.getCompose().getInclude()) {
                   if (include.hasSystem() && include.getSystem().equals("http://snomed.info/sct")) {
                       log.info("SNOMED");

                       // http://hl7.org/fhir/snomedct.html

                       if (client == null) {
                           client = ctx.newRestfulGenericClient("http://ontoserver.dataproducts.nhs.uk/fhir");
                       }
                       for (ValueSet.ConceptSetFilterComponent filter : include.getFilter()) {
                           if (filter.hasOp()) {
                               log.info("has Filter");
                               switch (filter.getOp()) {
                                   case IN:
                                       log.info("IN Filter detected");
                                   //    Parameters parameters = new Parameters();
                                   //    parameters.addParameter().setName("identifier").setValue(new StringType("http://snomed.info/sct/999000031000000106/version/20180321?fhir_vs=isa/"+filter.getValue()));
                                       ValueSet vsExpansion = (ValueSet) client
                                               .operation()
                                               .onType(ValueSet.class)
                                               .named("expand")
                                               .withSearchParameter(Parameters.class,"identifier", new UriParam("http://snomed.info/sct/999000031000000106/version/20180321?fhir_vs=refset/"+filter.getValue()))
                                               .returnResourceType(ValueSet.class)
                                               .useHttpGet()
                                               .execute();
                                       log.info("EXPANSION RETURNED");
                                       log.info(ctx.newJsonParser().setPrettyPrint(true).encodeResourceToString(vsExpansion));
                                       if (vsExpansion.hasExpansion()) {
                                           for (ValueSet.ValueSetExpansionContainsComponent contains : vsExpansion.getExpansion().getContains()) {
                                               valueSet.getExpansion().addContains(contains);
                                           }
                                       }

                                       break;
                               }
                           }
                       }
                   }
                }
            }
        }
        if ( valueSet == null) {
            throw OperationOutcomeFactory.buildOperationOutcomeException(
                    new ResourceNotFoundException("No ValueSet/" + internalId.getIdPart()),
                    OperationOutcome.IssueSeverity.ERROR, OperationOutcome.IssueType.NOTFOUND);
        }

        return valueSet;

    }



    @Operation(name = "$refresh", idempotent = true, bundleType= BundleTypeEnum.COLLECTION)
    public MethodOutcome getValueCodes(
            @OperationParam(name="id") TokenParam valueSetId,
            @OperationParam(name="query") ReferenceParam valueSetQuery

    ) throws Exception {

    	System.out.println("getting value sets" + valueSetHost);
    	
{'fraction_non_alphanumeric': 0.09023224043715847, 'fraction_numerical': 0.00430327868852459, 'mean_word_length': 2.4207943925233644, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 36, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6082734', 'n_tokens_mistral': 3871, 'n_tokens_neox': 3743, 'n_words': 642}