Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
677dc44
feat-flag!: Update SED fields based on HTI-5
kekey1 Jun 22, 2026
3e380c7
feat-flag: Support different file headings based on flag state
kekey1 Jun 23, 2026
cb6622e
Merge branch 'staging' into OCD-5318
kekey1 Jun 23, 2026
59267e3
fix: Use correct logic for task/participant upload parsing
kekey1 Jun 23, 2026
2abcd39
feat-flag: Do not check for required tasks/participants
kekey1 Jun 23, 2026
89392f2
feat-flag: Add error if both UCD fields are filled in
kekey1 Jun 23, 2026
e44b81c
feat-flag: Copy existing tasks/participants for sed
kekey1 Jun 23, 2026
06f0e9b
feat: Return either UCD name or details in "value" field
kekey1 Jun 23, 2026
51da1d8
refactor: Remove unused variable
kekey1 Jun 23, 2026
acf18cd
feat-flag: Stop including Full Usability Report in Questionable URL data
kekey1 Jun 24, 2026
e09cf99
feat-flag: Write UCD processes to SED download file
kekey1 Jun 24, 2026
cac800c
feat-flag: Remove SED Summary fields after flag is flipped
kekey1 Jun 25, 2026
95bf33c
Merge branch 'staging' into OCD-5318
kekey1 Jun 25, 2026
29dd3e4
feat-flag: Save UCD Processes, never test tools
kekey1 Jun 25, 2026
b80b2d4
feat-flag: Remove sed fields in an annotation-based way
kekey1 Jun 26, 2026
9cd8ac0
fix: Use systemwide JsonMapper to write out listing details
kekey1 Jul 6, 2026
4ebfa9c
feat: Also hide UCD fields after flag flip
kekey1 Jul 8, 2026
cc6e388
fix: Ensure activity isn't writing out hidden JSON fields
kekey1 Jul 8, 2026
f380243
feat: Save UCD processes from just "value"
kekey1 Jul 9, 2026
3a770ee
Merge branch 'staging' into OCD-5318
kekey1 Jul 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public class CHPLConfig implements WebMvcConfigurer, EnvironmentAware {
private Boolean tryItOutEnabled;

@Autowired
private DeprecatedResponseFieldAnnotationIntrospector deprecatedResponseFieldAnnotationIntrospector;
private IgnorableResponseFieldAnnotationIntrospector ignorableResponseFieldAnnotationIntrospector;

@Lazy
@Autowired
Expand Down Expand Up @@ -117,7 +117,7 @@ public void setEnvironment(Environment e) {
@Primary
public JsonMapper jsonMapper() {
JsonMapper mapper = JsonMapper.builder()
.annotationIntrospector(deprecatedResponseFieldAnnotationIntrospector)
.annotationIntrospector(ignorableResponseFieldAnnotationIntrospector)
.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package gov.healthit.chpl;

import org.ff4j.FF4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import gov.healthit.chpl.api.deprecatedUsage.DeprecatedResponseField;
import gov.healthit.chpl.sed.DeprecatedSedSummaryData;
import gov.healthit.chpl.sed.DeprecatedSedTestTaskData;
import gov.healthit.chpl.sed.DeprecatedUcdData;
import lombok.extern.log4j.Log4j2;
import tools.jackson.databind.cfg.MapperConfig;
import tools.jackson.databind.introspect.AnnotatedMember;
import tools.jackson.databind.introspect.JacksonAnnotationIntrospector;

@Log4j2
@Component
public class IgnorableResponseFieldAnnotationIntrospector extends JacksonAnnotationIntrospector {
private static final long serialVersionUID = 7316344670464634840L;

@Autowired
private Environment env;

@Autowired
private FF4j ff4j;

@Override
public boolean hasIgnoreMarker(MapperConfig<?> config, AnnotatedMember m) {
if (super.hasIgnoreMarker(config, m)) {
return true;
} else {
return isDeprecatedAndIgnorable(m) || isSedAndIgnorable(m);
}
}

private boolean isDeprecatedAndIgnorable(AnnotatedMember m) {
Boolean returnDeprecatedFields = Boolean.valueOf(env.getProperty("response.returnDeprecatedFields"));
boolean isDeprecated = _findAnnotation(m, DeprecatedResponseField.class) != null;
return !returnDeprecatedFields && isDeprecated;
}

private boolean isSedAndIgnorable(AnnotatedMember m) {
boolean isHti5Erd = ff4j.check(FeatureList.HTI_5_ERD);
boolean isSedSummary = _findAnnotation(m, DeprecatedSedSummaryData.class) != null;
boolean isSedTestTask = _findAnnotation(m, DeprecatedSedTestTaskData.class) != null;
boolean isSedUcdData = _findAnnotation(m, DeprecatedUcdData.class) != null;
return isHti5Erd && (isSedSummary || isSedTestTask || isSedUcdData);
}
}
1 change: 1 addition & 0 deletions chpl/chpl-resources/src/main/resources/errors.properties
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ listing.criteria.badUcdProcess=Could not process UCD Process '%s'.
listing.criteria.missingUcdProcess=Certification %s requires at least one UCD process.
listing.criteria.ucdProcessNotFoundAndRemoved=UCD Process '%s' referenced by criteria %s was not found and was or will be removed.
listing.ucdProcess.unattestedCriterionRemoved=The criterion %s is not attested to and has been removed from a UCD Process.
listing.ucdProcess.bothFieldsPresent=Either the UCD Process Name or UCD Process Details must be filled in, but not both for UCD Process %s.

#Test Task And Participant Errors
listing.criteria.testTasksNotApplicable=Test Tasks are not applicable for the criterion %s.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ private FeatureList() {

public static final String CMS_DISABLED = "cms-disabled";
public static final String DEMOGRAPHIC_CHANGE_REQUEST = "demographic-change-request";
public static final String HTI_5_ERD = "hti-5-erd";
public static final String INSIGHTS_DISPLAY = "insights-display";
public static final String SERVICE_BASE_URL_LIST_CHANGE_REQUEST = "sbul-change-request";
public static final String RWT_CHANGE_REQUEST = "rwt-change-request";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.ff4j.FF4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import gov.healthit.chpl.FeatureList;
import gov.healthit.chpl.certificationCriteria.CertificationCriteriaManager;
import gov.healthit.chpl.certificationCriteria.CertificationCriterion;
import gov.healthit.chpl.certificationCriteria.CertificationCriterionWithAttributes;
Expand Down Expand Up @@ -82,19 +84,23 @@ public class ListingCsvDataWriter {
private static final int SED_TESTING_DATE_COL = 40;
private static final int PARTICIPANT_START_COL = 41;
private static final int TASK_START_COL = 50;
private static final int CRITERIA_START_COL = 65;
private static final int CRITERIA_START_COL_PRE_HTI5 = 65;
private static final int CRITERIA_START_COL = 38;
private static final int ADDITIONAL_SOFTWARE_COL_COUNT = 5;
private static final int UCD_PROCESS_COL_COUNT = 2;
private static final int SED_TESTING_COL_COUNT = 2;

private CertificationCriteriaManager criteriaManager;
private StandardManager standardManager;
private DateFormat dateFormat;
private FF4j ff4j;

@Autowired
public ListingCsvDataWriter(CertificationCriteriaManager criteriaManager, StandardManager standardManager) {
public ListingCsvDataWriter(CertificationCriteriaManager criteriaManager, StandardManager standardManager,
FF4j ff4j) {
this.criteriaManager = criteriaManager;
this.standardManager = standardManager;
this.ff4j = ff4j;
this.dateFormat = new SimpleDateFormat(ListingUploadHandlerUtil.UPLOAD_DATE_FORMAT);
}

Expand All @@ -121,11 +127,13 @@ public List<List<String>> getCsvData(CertifiedProductSearchDetails listing, int
addAccessibilityStandards(csvDataMatrix, listing.getAccessibilityStandards());
csvDataMatrix[0][K1_URL_COL] = listing.getMandatoryDisclosures();
addCqms(csvDataMatrix, listing.getCqmResults());
csvDataMatrix[0][SED_REPORT_URL_COL] = listing.getSedReportFileLocation();
csvDataMatrix[0][SED_INTENDED_USERS_COL] = listing.getSedIntendedUserDescription();
csvDataMatrix[0][SED_TESTING_DATE_COL] = listing.getSedTestingEndDay() != null ? dateFormat.format(DateUtil.toDate(listing.getSedTestingEndDay())) : "";
addParticipants(csvDataMatrix, listing.getSed());
addTasks(csvDataMatrix, listing.getSed());
if (!ff4j.check(FeatureList.HTI_5_ERD)) {
csvDataMatrix[0][SED_REPORT_URL_COL] = listing.getSedReportFileLocation();
csvDataMatrix[0][SED_INTENDED_USERS_COL] = listing.getSedIntendedUserDescription();
csvDataMatrix[0][SED_TESTING_DATE_COL] = listing.getSedTestingEndDay() != null ? dateFormat.format(DateUtil.toDate(listing.getSedTestingEndDay())) : "";
addParticipants(csvDataMatrix, listing.getSed());
addTasks(csvDataMatrix, listing.getSed());
}
addCertificationResults(csvDataMatrix, getAllAvailableCriteriaAsCertResults(listing), listing.getSed());

List<List<String>> records = new ArrayList<List<String>>();
Expand Down Expand Up @@ -445,7 +453,7 @@ private void addTasks(String[][] csvDataMatrix, CertifiedProductSed sed) {
}

private void addCertificationResults(String[][] csvDataMatrix, List<CertificationResult> certResults, CertifiedProductSed sed) {
int currCol = CRITERIA_START_COL;
int currCol = !ff4j.check(FeatureList.HTI_5_ERD) ? CRITERIA_START_COL_PRE_HTI5 : CRITERIA_START_COL;
for (int i = 0; i < certResults.size(); i++) {
int currCertResultStartCol = currCol;
CertificationResult certResult = certResults.get(i);
Expand Down Expand Up @@ -652,19 +660,21 @@ private int addSed(String[][] csvDataMatrix, CertificationResult certResult, Cer
}
currCol += UCD_PROCESS_COL_COUNT;

List<TestTask> testTasks = getTestTasksForCriterion(certResult.getCriterion(), sed);
if (!CollectionUtils.isEmpty(testTasks)) {
for (int i = 0; i < testTasks.size(); i++) {
int sedTestingCol = currCol;
TestTask testTask = testTasks.get(i);
csvDataMatrix[i][sedTestingCol++] = testTask.getFriendlyId();
String participants = testTask.getTestParticipants().stream()
.map(participant -> participant.getFriendlyId())
.collect(Collectors.joining(";"));
csvDataMatrix[i][sedTestingCol++] = participants;
if (!ff4j.check(FeatureList.HTI_5_ERD)) {
List<TestTask> testTasks = getTestTasksForCriterion(certResult.getCriterion(), sed);
if (!CollectionUtils.isEmpty(testTasks)) {
for (int i = 0; i < testTasks.size(); i++) {
int sedTestingCol = currCol;
TestTask testTask = testTasks.get(i);
csvDataMatrix[i][sedTestingCol++] = testTask.getFriendlyId();
String participants = testTask.getTestParticipants().stream()
.map(participant -> participant.getFriendlyId())
.collect(Collectors.joining(";"));
csvDataMatrix[i][sedTestingCol++] = participants;
}
}
currCol += SED_TESTING_COL_COUNT;
}
currCol += SED_TESTING_COL_COUNT;
}
return currCol;
}
Expand Down
Loading
Loading