Skip to content

Commit

Permalink
Merge branch 'hapifhir:master' into fix/remove-entity-embeddable-conf…
Browse files Browse the repository at this point in the history
…lict
  • Loading branch information
iyt-trifork authored Dec 27, 2024
2 parents bdf4201 + 4feb489 commit 6517182
Show file tree
Hide file tree
Showing 198 changed files with 19,423 additions and 672 deletions.
2 changes: 1 addition & 1 deletion hapi-deployable-pom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>7.7.14-SNAPSHOT</version>
<version>7.7.16-SNAPSHOT</version>

<relativePath>../pom.xml</relativePath>
</parent>
Expand Down
2 changes: 1 addition & 1 deletion hapi-fhir-android/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.14-SNAPSHOT</version>
<version>7.7.16-SNAPSHOT</version>

<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>
Expand Down
2 changes: 1 addition & 1 deletion hapi-fhir-base/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.14-SNAPSHOT</version>
<version>7.7.16-SNAPSHOT</version>

<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public interface INarrativeTemplate {

Set<String> getAppliesToProfiles();

Set<String> getAppliesToCode();

Set<String> getAppliesToResourceTypes();

Set<Class<? extends IBase>> getAppliesToClasses();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ List<INarrativeTemplate> getTemplateByResourceName(
@Nonnull FhirContext theFhirContext,
@Nonnull EnumSet<TemplateTypeEnum> theStyles,
@Nonnull String theResourceName,
@Nonnull Collection<String> theProfiles);
@Nonnull Collection<String> theProfiles,
@Nonnull Collection<String> theCodes);

List<INarrativeTemplate> getTemplateByName(
@Nonnull FhirContext theFhirContext, @Nonnull EnumSet<TemplateTypeEnum> theStyles, @Nonnull String theName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public class NarrativeTemplate implements INarrativeTemplate {
private final Set<String> myAppliesToDataTypes = new HashSet<>();
private final Set<Class<? extends IBase>> myAppliesToClasses = new HashSet<>();
private final Set<String> myAppliesToFragmentNames = new HashSet<>();
private final Set<String> myAppliesToCode = new HashSet<>();
private String myTemplateFileName;
private TemplateTypeEnum myTemplateType = TemplateTypeEnum.THYMELEAF;
private String myContextPath;
Expand Down Expand Up @@ -81,10 +82,19 @@ public Set<String> getAppliesToProfiles() {
return Collections.unmodifiableSet(myAppliesToProfiles);
}

@Override
public Set<String> getAppliesToCode() {
return Collections.unmodifiableSet(myAppliesToCode);
}

void addAppliesToProfile(String theAppliesToProfile) {
myAppliesToProfiles.add(theAppliesToProfile);
}

void addAppliesToCode(String theAppliesToCode) {
myAppliesToCode.add(theAppliesToCode);
}

@Override
public Set<String> getAppliesToResourceTypes() {
return Collections.unmodifiableSet(myAppliesToResourceTypes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,24 +107,25 @@ public List<INarrativeTemplate> getTemplateByResourceName(
@Nonnull FhirContext theFhirContext,
@Nonnull EnumSet<TemplateTypeEnum> theStyles,
@Nonnull String theResourceName,
@Nonnull Collection<String> theProfiles) {
return getFromMap(theStyles, theResourceName.toUpperCase(), myResourceTypeToTemplate, theProfiles);
@Nonnull Collection<String> theProfiles,
@Nonnull Collection<String> theCodes) {
return getFromMap(theStyles, theResourceName.toUpperCase(), myResourceTypeToTemplate, theProfiles, theCodes);
}

@Override
public List<INarrativeTemplate> getTemplateByName(
@Nonnull FhirContext theFhirContext,
@Nonnull EnumSet<TemplateTypeEnum> theStyles,
@Nonnull String theName) {
return getFromMap(theStyles, theName, myNameToTemplate, Collections.emptyList());
return getFromMap(theStyles, theName, myNameToTemplate);
}

@Override
public List<INarrativeTemplate> getTemplateByFragmentName(
@Nonnull FhirContext theFhirContext,
@Nonnull EnumSet<TemplateTypeEnum> theStyles,
@Nonnull String theFragmentName) {
return getFromMap(theStyles, theFragmentName, myFragmentNameToTemplate, Collections.emptyList());
return getFromMap(theStyles, theFragmentName, myFragmentNameToTemplate);
}

@SuppressWarnings("PatternVariableCanBeUsed")
Expand All @@ -138,22 +139,30 @@ public List<INarrativeTemplate> getTemplateByElement(
if (theElement instanceof IBaseResource) {
IBaseResource resource = (IBaseResource) theElement;
String resourceName = theFhirContext.getResourceDefinition(resource).getName();

List<String> profiles = resource.getMeta().getProfile().stream()
.filter(Objects::nonNull)
.map(IPrimitiveType::getValueAsString)
.filter(StringUtils::isNotBlank)
.collect(Collectors.toList());
retVal = getTemplateByResourceName(theFhirContext, theStyles, resourceName, profiles);

List<String> codes = resource.getMeta().getTag().stream()
.filter(Objects::nonNull)
.filter(f -> StringUtils.isNotBlank(f.getSystem()) && StringUtils.isNotBlank(f.getCode()))
.map(t -> t.getSystem() + "|" + t.getCode())
.collect(Collectors.toList());

retVal = getTemplateByResourceName(theFhirContext, theStyles, resourceName, profiles, codes);
}

if (retVal.isEmpty()) {
retVal = getFromMap(theStyles, theElement.getClass().getName(), myClassToTemplate, Collections.emptyList());
retVal = getFromMap(theStyles, theElement.getClass().getName(), myClassToTemplate);
}

if (retVal.isEmpty()) {
String datatypeName =
theFhirContext.getElementDefinition(theElement.getClass()).getName();
retVal = getFromMap(theStyles, datatypeName.toUpperCase(), myDatatypeToTemplate, Collections.emptyList());
retVal = getFromMap(theStyles, datatypeName.toUpperCase(), myDatatypeToTemplate);
}
return retVal;
}
Expand Down Expand Up @@ -222,6 +231,11 @@ private static Collection<NarrativeTemplate> loadProperties(String theManifestTe
if (isNotBlank(profile)) {
nextTemplate.addAppliesToProfile(profile);
}
} else if (nextKey.endsWith(".tag")) {
String tag = file.getProperty(nextKey);
if (isNotBlank(tag)) {
nextTemplate.addAppliesToCode(tag);
}
} else if (nextKey.endsWith(".resourceType")) {
String resourceType = file.getProperty(nextKey);
parseValuesAndAddToMap(resourceType, nextTemplate::addAppliesToResourceType);
Expand Down Expand Up @@ -282,15 +296,22 @@ static String loadResource(String theName) {
}
}

private static <T> List<INarrativeTemplate> getFromMap(
EnumSet<TemplateTypeEnum> theStyles, T theKey, ListMultimap<T, NarrativeTemplate> theMap) {
return getFromMap(theStyles, theKey, theMap, Collections.emptyList(), Collections.emptyList());
}

private static <T> List<INarrativeTemplate> getFromMap(
EnumSet<TemplateTypeEnum> theStyles,
T theKey,
ListMultimap<T, NarrativeTemplate> theMap,
Collection<String> theProfiles) {
Collection<String> theProfiles,
Collection<String> theCodes) {
return theMap.get(theKey).stream()
.filter(t -> theStyles.contains(t.getTemplateType()))
.filter(t -> theProfiles.isEmpty()
|| t.getAppliesToProfiles().stream().anyMatch(theProfiles::contains))
.filter(t -> theCodes.isEmpty() || t.getAppliesToCode().stream().anyMatch(theCodes::contains))
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,22 @@
*/
package ca.uhn.fhir.system;

import org.apache.commons.lang3.time.DateUtils;
import java.util.concurrent.TimeUnit;

public final class HapiSystemProperties {
static final String SUPPRESS_HAPI_FHIR_VERSION_LOG = "suppress_hapi_fhir_version_log";
static final String DISABLE_STATUS_BASED_REINDEX = "disable_status_based_reindex";
/**
* This is provided for testing only! Use with caution as this property may change.
*/
static final String TEST_SYSTEM_PROP_VALIDATION_RESOURCE_CACHES_MS =
"TEST_SYSTEM_PROP_VALIDATION_RESOURCE_CACHES_MS";
static final String VALIDATION_RESOURCE_CACHE_TIMEOUT_MILLIS = "VALIDATION_RESOURCE_CACHE_EXPIRY_MS";

static final String UNIT_TEST_CAPTURE_STACK = "unit_test_capture_stack";
static final String STACKFILTER_PATTERN_PROP = "log.stackfilter.pattern";
static final String HAPI_CLIENT_KEEPRESPONSES = "hapi.client.keepresponses";
static final String TEST_MODE = "test";
static final String UNIT_TEST_MODE = "unit_test_mode";
static final long DEFAULT_TEST_SYSTEM_PROP_VALIDATION_RESOURCE_CACHES_MS = 10 * DateUtils.MILLIS_PER_SECOND;
static final long DEFAULT_VALIDATION_RESOURCE_CACHE_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(10);
static final String PREVENT_INVALIDATING_CONDITIONAL_MATCH_CRITERIA =
"hapi.storage.prevent_invalidating_conditional_match_criteria";

Expand Down Expand Up @@ -75,20 +74,20 @@ public static void setStackFilterPattern(String thePattern) {
/**
* Set the validation resource cache expireAfterWrite timeout in milliseconds
*
* @param theMillis
* @param theMillis the timeout value to set (in milliseconds)
*/
public static void setTestValidationResourceCachesMs(long theMillis) {
System.setProperty(TEST_SYSTEM_PROP_VALIDATION_RESOURCE_CACHES_MS, "" + theMillis);
public static void setValidationResourceCacheTimeoutMillis(long theMillis) {
System.setProperty(VALIDATION_RESOURCE_CACHE_TIMEOUT_MILLIS, "" + theMillis);
}

/**
* Get the validation resource cache expireAfterWrite timeout in milliseconds. If it has not been set, the default
* value is 10 seconds.
*/
public static long getTestValidationResourceCachesMs() {
String property = System.getProperty(TEST_SYSTEM_PROP_VALIDATION_RESOURCE_CACHES_MS);
public static long getValidationResourceCacheTimeoutMillis() {
String property = System.getProperty(VALIDATION_RESOURCE_CACHE_TIMEOUT_MILLIS);
if (property == null) {
return DEFAULT_TEST_SYSTEM_PROP_VALIDATION_RESOURCE_CACHES_MS;
return DEFAULT_VALIDATION_RESOURCE_CACHE_TIMEOUT_MILLIS;
}
return Long.parseLong(property);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,30 +265,48 @@ public static IBase addIssueWithMessageId(
}

public static void addDetailsToIssue(FhirContext theFhirContext, IBase theIssue, String theSystem, String theCode) {
addDetailsToIssue(theFhirContext, theIssue, theSystem, theCode, null);
}

public static void addDetailsToIssue(
FhirContext theFhirContext, IBase theIssue, String theSystem, String theCode, String theText) {
BaseRuntimeElementCompositeDefinition<?> issueElement =
(BaseRuntimeElementCompositeDefinition<?>) theFhirContext.getElementDefinition(theIssue.getClass());
BaseRuntimeChildDefinition detailsChildDef = issueElement.getChildByName("details");

BaseRuntimeElementCompositeDefinition<?> codingDef =
(BaseRuntimeElementCompositeDefinition<?>) theFhirContext.getElementDefinition("Coding");
ICompositeType coding = (ICompositeType) codingDef.newInstance();

// System
IPrimitiveType<?> system =
(IPrimitiveType<?>) theFhirContext.getElementDefinition("uri").newInstance();
system.setValueAsString(theSystem);
codingDef.getChildByName("system").getMutator().addValue(coding, system);

// Code
IPrimitiveType<?> code =
(IPrimitiveType<?>) theFhirContext.getElementDefinition("code").newInstance();
code.setValueAsString(theCode);
codingDef.getChildByName("code").getMutator().addValue(coding, code);
BaseRuntimeElementCompositeDefinition<?> ccDef =
(BaseRuntimeElementCompositeDefinition<?>) theFhirContext.getElementDefinition("CodeableConcept");

ICompositeType codeableConcept = (ICompositeType) ccDef.newInstance();
ccDef.getChildByName("coding").getMutator().addValue(codeableConcept, coding);

if (isNotBlank(theSystem) || isNotBlank(theCode)) {
BaseRuntimeElementCompositeDefinition<?> codingDef =
(BaseRuntimeElementCompositeDefinition<?>) theFhirContext.getElementDefinition("Coding");
ICompositeType coding = (ICompositeType) codingDef.newInstance();

// System
if (isNotBlank(theSystem)) {
IPrimitiveType<?> system = (IPrimitiveType<?>)
theFhirContext.getElementDefinition("uri").newInstance();
system.setValueAsString(theSystem);
codingDef.getChildByName("system").getMutator().addValue(coding, system);
}

// Code
if (isNotBlank(theCode)) {
IPrimitiveType<?> code = (IPrimitiveType<?>)
theFhirContext.getElementDefinition("code").newInstance();
code.setValueAsString(theCode);
codingDef.getChildByName("code").getMutator().addValue(coding, code);
}

ccDef.getChildByName("coding").getMutator().addValue(codeableConcept, coding);
}

if (isNotBlank(theText)) {
IPrimitiveType<?> textElem = (IPrimitiveType<?>)
ccDef.getChildByName("text").getChildByName("text").newInstance(theText);
ccDef.getChildByName("text").getMutator().addValue(codeableConcept, textElem);
}

detailsChildDef.getMutator().addValue(theIssue, codeableConcept);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*-
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2024 Smile CDR, Inc.
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package ca.uhn.fhir.util;

import jakarta.annotation.Nonnull;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Stream;

/**
* This class collects items from a stream to a given limit and know whether there are
* still more items beyond that limit.
*
* @param <T> the type of object being streamed
*/
public class StopLimitAccumulator<T> {
private final boolean isTruncated;
private final List<T> myList;

private StopLimitAccumulator(List<T> theList, boolean theIsTruncated) {
myList = Collections.unmodifiableList(theList);
isTruncated = theIsTruncated;
}

public static <T> StopLimitAccumulator<T> fromStreamAndLimit(@Nonnull Stream<T> theItemStream, long theLimit) {
assert theLimit > 0;
AtomicBoolean isBeyondLimit = new AtomicBoolean(false);
List<T> accumulator = new ArrayList<>();

theItemStream
.limit(theLimit + 1) // Fetch one extra item to see if there are any more items past our limit
.forEach(item -> {
if (accumulator.size() < theLimit) {
accumulator.add(item);
} else {
isBeyondLimit.set(true);
}
});
return new StopLimitAccumulator<>(accumulator, isBeyondLimit.get());
}

public boolean isTruncated() {
return isTruncated;
}

public List<T> getItemList() {
return myList;
}
}
Loading

0 comments on commit 6517182

Please sign in to comment.