<commit_before>package org.opencds.cqf.ruler.plugin.utility;

import java.util.List;
import java.util.Optional;
import java.util.function.Function;

import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IPrimitiveType;

import ca.uhn.fhir.context.BaseRuntimeChildDefinition.IAccessor;
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeResourceDefinition;

/**
 * This interface provides utility methods for doing reflection on FHIR
 * resources. It's specifically focused on knowledge artifact resources since
 * there's not a common interface for those across different Resources (and FHIR
 * versions)
 */
public interface ReflectionUtilities {
    /**
     * Returns a FhirVersionEnum for a given ResourceType
     * 
     * @param <ResourceType>       an IBaseResource type
     * @param theResourceTypeClass the class of the resource to get the version for
     * @return the FhirVersionEnum corresponding to the theResourceTypeClass
     */
    public default <ResourceType extends IBase> FhirVersionEnum getFhirVersion(final 
            Class<? extends ResourceType> theResourceTypeClass) {
        String packageName = theResourceTypeClass.getPackage().getName();
        if (packageName.contains("r5")) {
            return FhirVersionEnum.R5;
        } else if (packageName.contains("r4")) {
            return FhirVersionEnum.R4;
        } else if (packageName.contains("dstu3")) {
            return FhirVersionEnum.DSTU3;
        } else if (packageName.contains("dstu2016may")) {
            return FhirVersionEnum.DSTU2_1;
        } else if (packageName.contains("org.hl7.fhir.dstu2")) {
            return FhirVersionEnum.DSTU2_HL7ORG;
        } else if (packageName.contains("ca.uhn.fhir.model.dstu2")) {
            return FhirVersionEnum.DSTU2;
        } else {
            throw new IllegalArgumentException(String.format(
                    "Unable to determine FHIR version for IBaseResource type: %s", theResourceTypeClass.getName()));
        }
    }

    /**
     * Gets the IAccessor for the given ResourceType and child
     * 
     * @param <ResourceType>       an IBaseResource type
     * @param theResourceTypeClass the class of a the IBaseResource type
     * @param theChildName         the name of the child property of the
     *                             ResourceType to generate an accessor for
     * @return an IAccessor for the given child and the ResourceType
     */
    public default <ResourceType extends IBase> IAccessor getAccessor(final Class<? extends ResourceType> theResourceTypeClass, String theChildName) {
        FhirContext fhirContext = FhirContext.forCached(this.getFhirVersion(theResourceTypeClass));
		  if (theResourceTypeClass.isInstance(IBaseResource.class)) {
				RuntimeResourceDefinition resourceDefinition = fhirContext.getResourceDefinition(IBaseResource.class.cast(theResourceTypeClass));
				return resourceDefinition.getChildByName(theChildName).getAccessor();
		  } else {
			  BaseRuntimeElementDefinition<?> elementDefinition = fhirContext.getElementDefinition(theResourceTypeClass);
			  return elementDefinition.getChildByName(theChildName).getAccessor();
		  }
    }

    /**
     * Generates a function to access a primitive property of the given
     * ResourceType.
     * 
     * @param <ResourceType>       an IBaseResource type
     * @param <ReturnType>         a return type for the Functions
     * @param theResourceTypeClass the class of a the IBaseResource type
     * @param theChildName         to create a function for
     * @return a function for accessing the "theChildName" property of the
     *         ResourceType
     */
    @SuppressWarnings("unchecked")
    public default <ResourceType extends IBase, ReturnType> Function<ResourceType, ReturnType> getPrimitiveFunction(final Class<? extends ResourceType> theResourceTypeClass, String theChildName) {
        IAccessor accessor = this.getAccessor(theResourceTypeClass, theChildName);
        return r -> {
            Optional<IBase> value = accessor.getFirstValueOrNull(r);
            if (!value.isPresent()) {
                return null;
            } else {
                return ((IPrimitiveType<ReturnType>) value.get()).getValue();
            }
        };
    }

	 /**
	 * Generates a function to access a primitive property of the given
	 * ResourceType.
	 * 
	 * @param <ResourceType>       an IBaseResource type
	 * @param <ReturnType>         a return type for the Functions
	 * @param theResourceTypeClass the class of a the IBaseResource type
	 * @param theChildName         to create a function for
	 * @return a function for accessing the "theChildName" property of the
	 *         ResourceType
	 */
	@SuppressWarnings("unchecked")
	public default <ResourceType extends IBase, ReturnType extends List<? extends IBase>> Function<ResourceType, ReturnType> getFunction(final Class<? extends ResourceType> theResourceTypeClass, String theChildName) {
		 IAccessor accessor = this.getAccessor(theResourceTypeClass, theChildName);
		 return r -> {
			  return (ReturnType)accessor.getValues(r);
		 };
	}


    /**
     * Generates a function to access the "version" property of the given
     * ResourceType.
     * 
     * @param <ResourceType>       an IBaseResource type
     * @param theResourceTypeClass the class of a the IBaseResource type
     * @return a function for accessing the "version" property of the ResourceType
     */
    public default <ResourceType extends IBase> Function<ResourceType, String> getVersionFunction(final Class<? extends ResourceType> theResourceTypeClass) {
        return this.getPrimitiveFunction(theResourceTypeClass, "version");
    }

    /**
     * Generates a function to access the "url" property of the given ResourceType.
     * 
     * @param <ResourceType>       an IBaseResource type
     * @param theResourceTypeClass the class of a the IBaseResource type
     * @return a function for accessing the "url" property of the ResourceType
     */
    public default <ResourceType extends IBase> Function<ResourceType, String> getUrlFunction(final Class<? extends ResourceType> theResourceTypeClass) {
        return this.getPrimitiveFunction(theResourceTypeClass, "url");
    }

    /**
     * Generates a function to access the "name" property of the given ResourceType.
     * 
     * @param <ResourceType>       an IBaseResource type
     * @param theResourceTypeClass the class of a the IBaseResource type
     * @return a function for accessing the "name" property of the ResourceType
     */
    public default <ResourceType extends IBase> Function<ResourceType, String> getNameFunction(final Class<? extends ResourceType> theResourceTypeClass) {
        return this.getPrimitiveFunction(theResourceTypeClass, "name");
    }
}
<commit_msg>Fix one issue with the reflection utilities<commit_after>package org.opencds.cqf.ruler.plugin.utility;

import java.util.List;
import java.util.Optional;
import java.util.function.Function;

import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IPrimitiveType;

import ca.uhn.fhir.context.BaseRuntimeChildDefinition.IAccessor;
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeResourceDefinition;

/**
 * This interface provides utility methods for doing reflection on FHIR
 * resources. It's specifically focused on knowledge artifact resources since
 * there's not a common interface for those across different Resources (and FHIR
 * versions)
 */
public interface ReflectionUtilities {
	/**
	 * Returns a FhirVersionEnum for a given ResourceType
	 * 
	 * @param <ResourceType>       an IBaseResource type
	 * @param theResourceTypeClass the class of the resource to get the version for
	 * @return the FhirVersionEnum corresponding to the theResourceTypeClass
	 */
	public default <ResourceType extends IBase> FhirVersionEnum getFhirVersion(
			final Class<? extends ResourceType> theResourceTypeClass) {
		String packageName = theResourceTypeClass.getPackage().getName();
		if (packageName.contains("r5")) {
			return FhirVersionEnum.R5;
		} else if (packageName.contains("r4")) {
			return FhirVersionEnum.R4;
		} else if (packageName.contains("dstu3")) {
			return FhirVersionEnum.DSTU3;
		} else if (packageName.contains("dstu2016may")) {
			return FhirVersionEnum.DSTU2_1;
		} else if (packageName.contains("org.hl7.fhir.dstu2")) {
			return FhirVersionEnum.DSTU2_HL7ORG;
		} else if (packageName.contains("ca.uhn.fhir.model.dstu2")) {
			return FhirVersionEnum.DSTU2;
		} else {
			throw new IllegalArgumentException(String.format(
					"Unable to determine FHIR version for IBaseResource type: %s", theResourceTypeClass.getName()));
		}
	}

	/**
	 * Gets the IAccessor for the given ResourceType and child
	 * 
	 * @param <ResourceType>       an IBaseResource type
	 * @param theResourceTypeClass the class of a the IBaseResource type
	 * @param theChildName         the name of the child property of the
	 *                             ResourceType to generate an accessor for
	 * @return an IAccessor for the given child and the ResourceType
	 */
	public default <ResourceType extends IBase> IAccessor getAccessor(
			final Class<? extends ResourceType> theResourceTypeClass, String theChildName) {
		FhirContext fhirContext = FhirContext.forCached(this.getFhirVersion(theResourceTypeClass));
		if (theResourceTypeClass.isInstance(IBaseResource.class)) {
			@SuppressWarnings("unchecked")
			RuntimeResourceDefinition resourceDefinition = fhirContext
					.getResourceDefinition((Class<? extends IBaseResource>) theResourceTypeClass);
			return resourceDefinition.getChildByName(theChildName).getAccessor();
		} else {
			BaseRuntimeElementDefinition<?> elementDefinition = fhirContext.getElementDefinition(theResourceTypeClass);
			return elementDefinition.getChildByName(theChildName).getAccessor();
		}
	}

	/**
	 * Generates a function to access a primitive property of the given
	 * ResourceType.
	 * 
	 * @param <ResourceType>       an IBaseResource type
	 * @param <ReturnType>         a return type for the Functions
	 * @param theResourceTypeClass the class of a the IBaseResource type
	 * @param theChildName         to create a function for
	 * @return a function for accessing the "theChildName" property of the
	 *         ResourceType
	 */
	@SuppressWarnings("unchecked")
	public default <ResourceType extends IBase, ReturnType> Function<ResourceType, ReturnType> getPrimitiveFunction(
			final Class<? extends ResourceType> theResourceTypeClass, String theChildName) {
		IAccessor accessor = this.getAccessor(theResourceTypeClass, theChildName);
		return r -> {
			Optional<IBase> value = accessor.getFirstValueOrNull(r);
			if (!value.isPresent()) {
				return null;
			} else {
				return ((IPrimitiveType<ReturnType>) value.get()).getValue();
			}
		};
	}

	/**
	 * Generates a function to access a primitive property of the given
	 * ResourceType.
	 * 
	 * @param <ResourceType>       an IBaseResource type
	 * @param <ReturnType>         a return type for the Functions
	 * @param theResourceTypeClass the class of a the IBaseResource type
	 * @param theChildName         to create a function for
	 * @return a function for accessing the "theChildName" property of the
	 *         ResourceType
	 */
	@SuppressWarnings("unchecked")
	public default <ResourceType extends IBase, ReturnType extends List<? extends IBase>> Function<ResourceType, ReturnType> getFunction(
			final Class<? extends ResourceType> theResourceTypeClass, String theChildName) {
		IAccessor accessor = this.getAccessor(theResourceTypeClass, theChildName);
		return r -> {
			return (ReturnType) accessor.getValues(r);
		};
	}

	/**
	 * Generates a function to access the "version" property of the given
	 * ResourceType.
	 * 
	 * @param <ResourceType>       an IBaseResource type
	 * @param theResourceTypeClass the class of a the IBaseResource type
	 * @return a function for accessing the "version" property of the ResourceType
	 */
	public default <ResourceType extends IBase> Function<ResourceType, String> getVersionFunction(
			final Class<? extends ResourceType> theResourceTypeClass) {
		return this.getPrimitiveFunction(theResourceTypeClass, "version");
	}

	/**
	 * Generates a function to access the "url" property of the given ResourceType.
	 * 
	 * @param <ResourceType>       an IBaseResource type
	 * @param theResourceTypeClass the class of a the IBaseResource type
	 * @return a function for accessing the "url" property of the ResourceType
	 */
	public default <ResourceType extends IBase> Function<ResourceType, String> getUrlFunction(
			final Class<? extends ResourceType> theResourceTypeClass) {
		return this.getPrimitiveFunction(theResourceTypeClass, "url");
	}

	/**
	 * Generates a function to access the "name" property of the given ResourceType.
	 * 
	 * @param <ResourceType>       an IBaseResource type
	 * @param theResourceTypeClass the class of a the IBaseResource type
	 * @return a function for accessing the "name" property of the ResourceType
	 */
	public default <ResourceType extends IBase> Function<ResourceType, String> getNameFunction(
			final Class<? extends ResourceType> theResourceTypeClass) {
		return this.getPrimitiveFunction(theResourceTypeClass, "name");
	}
}

{'fraction_non_alphanumeric': 0.0813474551338629, 'fraction_numerical': 0.003089143865842895, 'mean_word_length': 3.806291975963238, 'pattern_counts': {'":': 0, '<': 68, '<?xml version=': 0, '>': 72, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6024349', 'n_tokens_mistral': 3805, 'n_tokens_neox': 3598, 'n_words': 1111}