Skip to content

Commit 1e4f196

Browse files
authored
Merge pull request #1092 from CMSgov/feature/QPPSF-8020_APP_CT
QPPSF-8020 - Y5 Conversion Tool APP
2 parents 938b93d + bdfb448 commit 1e4f196

File tree

8 files changed

+156
-2
lines changed

8 files changed

+156
-2
lines changed

converter/src/main/java/gov/cms/qpp/conversion/decode/ClinicalDocumentDecoder.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ public class ClinicalDocumentDecoder extends QrdaDecoder {
4646
public static final String ENTITY_VIRTUAL_GROUP = "virtualGroup";
4747
public static final String ENTITY_ID = "entityId";
4848
public static final String CPCPLUS = "CPCPLUS";
49+
public static final String APP = "APP";
50+
public static final String APP_PROGRAM_NAME = "app1";
51+
private static final String APP_GROUP = "MIPS_APP1_GROUP";
52+
private static final String APP_INDIVIDUAL = "MIPS_APP1_INDIV";
53+
public static final String APP_APM = "MIPS_APP1_APMENTITY";
4954

5055
public ClinicalDocumentDecoder(Context context) {
5156
super(context);
@@ -215,10 +220,18 @@ private Pair<String, String> getProgramNameEntityPair(String name) {
215220
pair = new ImmutablePair<>(MIPS_PROGRAM_NAME, ENTITY_INDIVIDUAL);
216221
break;
217222

223+
case APP_INDIVIDUAL:
224+
pair = new ImmutablePair<>(APP_PROGRAM_NAME, ENTITY_INDIVIDUAL);
225+
break;
226+
218227
case MIPS_GROUP:
219228
pair = new ImmutablePair<>(MIPS_PROGRAM_NAME, ENTITY_GROUP);
220229
break;
221230

231+
case APP_GROUP:
232+
pair = new ImmutablePair<>(APP_PROGRAM_NAME, ENTITY_GROUP);
233+
break;
234+
222235
case CPCPLUS:
223236
pair = new ImmutablePair<>(CPCPLUS_PROGRAM_NAME, ENTITY_APM);
224237
break;
@@ -231,6 +244,10 @@ private Pair<String, String> getProgramNameEntityPair(String name) {
231244
pair = new ImmutablePair<>(MIPS_PROGRAM_NAME, ENTITY_APM);
232245
break;
233246

247+
case APP_APM:
248+
pair = new ImmutablePair<>(APP_PROGRAM_NAME, ENTITY_APM);
249+
break;
250+
234251
case PCF:
235252
pair = new ImmutablePair<>(PCF_PROGRAM_NAME, ENTITY_APM);
236253
break;

converter/src/main/java/gov/cms/qpp/conversion/encode/ClinicalDocumentEncoder.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ private JsonWrapper encodeMeasurementSets(Map<TemplateId, Node> childMapByTempla
120120
&& ClinicalDocumentDecoder.MIPS_APM.equalsIgnoreCase(
121121
currentNode.getValue(ClinicalDocumentDecoder.RAW_PROGRAM_NAME))) {
122122
childWrapper.put(ClinicalDocumentDecoder.PROGRAM_NAME, ClinicalDocumentDecoder.MIPS.toLowerCase(Locale.getDefault()));
123+
} else if (TemplateId.MEASURE_SECTION_V4.getRoot().equalsIgnoreCase(childType.getRoot())
124+
&& ClinicalDocumentDecoder.APP_APM.equalsIgnoreCase(
125+
currentNode.getValue(ClinicalDocumentDecoder.RAW_PROGRAM_NAME))) {
126+
childWrapper.put(ClinicalDocumentDecoder.PROGRAM_NAME, ClinicalDocumentDecoder.APP.toLowerCase(Locale.getDefault()));
123127
}
124128

125129
measurementSetsWrapper.put(childWrapper);

converter/src/main/java/gov/cms/qpp/conversion/model/Program.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public enum Program {
1616
MIPS("MIPS_GROUP", "MIPS_INDIV", "MIPS_VIRTUALGROUP", "MIPS", "MIPSAPM"),
1717
CPC("CPCPLUS"),
1818
PCF("PCF"),
19+
APP("MIPS_APP1_INDIV", "MIPS_APP1_GROUP", "MIPS_APP1_APMENTITY"),
1920
ALL;
2021

2122
private final Set<String> aliases;
@@ -59,6 +60,16 @@ public static boolean isMips(Node node) {
5960
return extractProgram(node) == Program.MIPS;
6061
}
6162

63+
/**
64+
* Checks if a node is using the APP program
65+
*
66+
* @param node
67+
* @return
68+
*/
69+
public static boolean isApp(Node node) {
70+
return extractProgram(node) == Program.APP;
71+
}
72+
6273
/**
6374
* Extracts a program type from a node
6475
*

converter/src/main/java/gov/cms/qpp/conversion/validate/ClinicalDocumentValidator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ protected void performValidation(final Node node) {
5353

5454
forceCheckErrors(node).valueIn(ProblemCode.CLINICAL_DOCUMENT_INCORRECT_PROGRAM_NAME.format(programName, VALID_PROGRAM_NAMES),
5555
ClinicalDocumentDecoder.PROGRAM_NAME, ClinicalDocumentDecoder.MIPS_PROGRAM_NAME,
56-
ClinicalDocumentDecoder.CPCPLUS_PROGRAM_NAME, ClinicalDocumentDecoder.PCF);
56+
ClinicalDocumentDecoder.CPCPLUS_PROGRAM_NAME, ClinicalDocumentDecoder.PCF, ClinicalDocumentDecoder.APP_PROGRAM_NAME);
5757

5858
if (ClinicalDocumentDecoder.ENTITY_VIRTUAL_GROUP.equals(entityType)) {
5959
forceCheckErrors(node).value(ProblemCode.VIRTUAL_GROUP_ID_REQUIRED, ClinicalDocumentDecoder.ENTITY_ID);

converter/src/test/java/gov/cms/qpp/conversion/decode/ClinicalDocumentDecoderTest.java

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,28 @@ void decodeClinicalDocumentInternalDecode() {
159159
.isEqualTo("123456789");
160160
}
161161

162+
@Test
163+
void decodeAppClinicalDocumentInternalDecode() {
164+
Element clinicalDocument = makeClinicalDocument("APP1");
165+
Node testParentNode = new Node();
166+
ClinicalDocumentDecoder objectUnderTest = new ClinicalDocumentDecoder(new Context());
167+
objectUnderTest.setNamespace(clinicalDocument.getNamespace());
168+
objectUnderTest.decode(clinicalDocument, testParentNode);
169+
170+
assertWithMessage("Clinical Document doesn't contain program name")
171+
.that(testParentNode.getValue(ClinicalDocumentDecoder.PROGRAM_NAME))
172+
.isEqualTo(ClinicalDocumentDecoder.APP_PROGRAM_NAME);
173+
assertWithMessage("Clinical Document doesn't contain entity type")
174+
.that(testParentNode.getValue(ClinicalDocumentDecoder.ENTITY_TYPE))
175+
.isEqualTo(ClinicalDocumentDecoder.ENTITY_INDIVIDUAL);
176+
assertWithMessage("Clinical Document doesn't contain national provider")
177+
.that(testParentNode.getValue(ClinicalDocumentDecoder.NATIONAL_PROVIDER_IDENTIFIER))
178+
.isEqualTo("2567891421");
179+
assertWithMessage("Clinical Document doesn't contain taxpayer id number")
180+
.that(testParentNode.getValue(ClinicalDocumentDecoder.TAX_PAYER_IDENTIFICATION_NUMBER))
181+
.isEqualTo("123456789");
182+
}
183+
162184
@Test
163185
void decodeClinicalDocumentInternalDecodeMIPSIndividual() {
164186
Element clinicalDocument = makeClinicalDocument("MIPS_INDIV");
@@ -181,6 +203,28 @@ void decodeClinicalDocumentInternalDecodeMIPSIndividual() {
181203
.isEqualTo("123456789");
182204
}
183205

206+
@Test
207+
void decodeClinicalDocumentInternalDecodeMIPSAPPIndividual() {
208+
Element clinicalDocument = makeClinicalDocument("MIPS_APP1_INDIV");
209+
Node testParentNode = new Node();
210+
ClinicalDocumentDecoder objectUnderTest = new ClinicalDocumentDecoder(new Context());
211+
objectUnderTest.setNamespace(clinicalDocument.getNamespace());
212+
objectUnderTest.decode(clinicalDocument, testParentNode);
213+
214+
assertWithMessage("Clinical Document doesn't contain program name")
215+
.that(testParentNode.getValue(ClinicalDocumentDecoder.PROGRAM_NAME))
216+
.isEqualTo(ClinicalDocumentDecoder.APP_PROGRAM_NAME);
217+
assertWithMessage("Clinical Document doesn't contain entity type")
218+
.that(testParentNode.getValue(ClinicalDocumentDecoder.ENTITY_TYPE))
219+
.isEqualTo(ClinicalDocumentDecoder.ENTITY_INDIVIDUAL);
220+
assertWithMessage("Clinical Document doesn't contain national provider")
221+
.that(testParentNode.getValue(ClinicalDocumentDecoder.NATIONAL_PROVIDER_IDENTIFIER))
222+
.isEqualTo("2567891421");
223+
assertWithMessage("Clinical Document doesn't contain taxpayer id number")
224+
.that(testParentNode.getValue(ClinicalDocumentDecoder.TAX_PAYER_IDENTIFICATION_NUMBER))
225+
.isEqualTo("123456789");
226+
}
227+
184228
@Test
185229
void decodeClinicalDocumentInternalDecodeMIPSGroup() {
186230
Element clinicalDocument = makeClinicalDocument("MIPS_GROUP");
@@ -203,6 +247,28 @@ void decodeClinicalDocumentInternalDecodeMIPSGroup() {
203247
.isEqualTo("123456789");
204248
}
205249

250+
@Test
251+
void decodeClinicalDocumentInternalDecodeMIPSAPPGroup() {
252+
Element clinicalDocument = makeClinicalDocument("MIPS_APP1_GROUP");
253+
Node testParentNode = new Node();
254+
ClinicalDocumentDecoder objectUnderTest = new ClinicalDocumentDecoder(new Context());
255+
objectUnderTest.setNamespace(clinicalDocument.getNamespace());
256+
objectUnderTest.decode(clinicalDocument, testParentNode);
257+
258+
assertWithMessage("Clinical Document doesn't contain program name")
259+
.that(testParentNode.getValue(ClinicalDocumentDecoder.PROGRAM_NAME))
260+
.isEqualTo(ClinicalDocumentDecoder.APP_PROGRAM_NAME);
261+
assertWithMessage("Clinical Document doesn't contain entity type")
262+
.that(testParentNode.getValue(ClinicalDocumentDecoder.ENTITY_TYPE))
263+
.isEqualTo(ClinicalDocumentDecoder.ENTITY_GROUP);
264+
assertWithMessage("Clinical Document doesn't contain national provider")
265+
.that(testParentNode.getValue(ClinicalDocumentDecoder.NATIONAL_PROVIDER_IDENTIFIER))
266+
.isNull();
267+
assertWithMessage("Clinical Document doesn't contain taxpayer id number")
268+
.that(testParentNode.getValue(ClinicalDocumentDecoder.TAX_PAYER_IDENTIFICATION_NUMBER))
269+
.isEqualTo("123456789");
270+
}
271+
206272
@Test
207273
void decodeClinicalDocumentInternalDecodeUnknown() {
208274
Element clinicalDocument = makeClinicalDocument("Unknown");
@@ -376,6 +442,22 @@ void decodeMipsApmTest() {
376442
.isEqualTo("AR000000");
377443
}
378444

445+
@Test
446+
void decodeMipsAppApmTest() {
447+
Element clinicalDocument = makeClinicalDocument(ClinicalDocumentDecoder.APP_APM);
448+
clinicalDocument.addContent(prepareParticipant(clinicalDocument.getNamespace()));
449+
Node testParentNode = new Node();
450+
451+
ClinicalDocumentDecoder objectUnderTest = new ClinicalDocumentDecoder(new Context());
452+
objectUnderTest.setNamespace(clinicalDocument.getNamespace());
453+
objectUnderTest.decode(clinicalDocument, testParentNode);
454+
455+
assertThat(testParentNode.getValue(ClinicalDocumentDecoder.ENTITY_TYPE))
456+
.isEqualTo(ClinicalDocumentDecoder.ENTITY_APM);
457+
assertThat(testParentNode.getValue(ClinicalDocumentDecoder.ENTITY_ID))
458+
.isEqualTo("AR000000");
459+
}
460+
379461
@Test
380462
void decodeClinicalDocumentInternalDecodeCPCPlus() {
381463
Element clinicalDocument = makeClinicalDocument(ClinicalDocumentDecoder.CPCPLUS);

converter/src/test/java/gov/cms/qpp/conversion/encode/ClinicalDocumentEncoderTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,24 @@ void testMeasurementSetIncludesSource() throws EncodeException {
270270
}
271271
}
272272

273+
@Test
274+
void testAppApmIncludesEntityID() throws EncodeException {
275+
JsonWrapper testJsonWrapper = new JsonWrapper();
276+
clinicalDocumentNode.putValue(ClinicalDocumentDecoder.ENTITY_TYPE, "apm");
277+
clinicalDocumentNode.putValue(ClinicalDocumentDecoder.PROGRAM_NAME, "app1");
278+
279+
ClinicalDocumentEncoder clinicalDocumentEncoder = new ClinicalDocumentEncoder(new Context());
280+
clinicalDocumentEncoder.internalEncode(testJsonWrapper, clinicalDocumentNode);
281+
282+
Map<?, ?> clinicalDocMap = ((Map<?, ?>) testJsonWrapper.toObject());
283+
284+
assertThat(clinicalDocMap.get(ClinicalDocumentDecoder.NATIONAL_PROVIDER_IDENTIFIER))
285+
.isNull();
286+
287+
assertThat(clinicalDocMap.get(ClinicalDocumentDecoder.ENTITY_ID))
288+
.isNotNull();
289+
}
290+
273291

274292
private JsonWrapper getMeasurementSets(JsonWrapper clinicalDocument) {
275293
return clinicalDocument.get("measurementSets");

converter/src/test/java/gov/cms/qpp/conversion/model/ProgramTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ void instanceRetrievalMips() {
2323
);
2424
}
2525

26+
@Test
27+
void instanceRetrievalMipsApp() {
28+
Stream.of("MIPS_APP1_GROUP", "MIPS_APP1_INDIV").forEach(mip ->
29+
assertWithMessage("Program other than %s was returned", Program.APP)
30+
.that(Program.getInstance(mip)).isSameInstanceAs(Program.APP)
31+
);
32+
}
33+
2634
@Test
2735
void instanceRetrievalCpcPlus() {
2836
assertWithMessage("Program other than %s was returned", Program.CPC)
@@ -115,6 +123,20 @@ void testIsCpcPlusForCpcplusMixedCaseIsTrue() {
115123
assertThat(Program.isCpc(node)).isTrue();
116124
}
117125

126+
@Test
127+
void testIsAppIndividualIsTrue() {
128+
Node node = new Node();
129+
node.putValue(ClinicalDocumentDecoder.RAW_PROGRAM_NAME, "MIPS_APP1_INDIV");
130+
assertThat(Program.isApp(node)).isTrue();
131+
}
132+
133+
@Test
134+
void testIsMipsNonAppIndividualFalse() {
135+
Node node = new Node();
136+
node.putValue(ClinicalDocumentDecoder.RAW_PROGRAM_NAME, "MIPS_INDIV");
137+
assertThat(Program.isApp(node)).isFalse();
138+
}
139+
118140
@Test
119141
void testExtractProgramForMipsInd() {
120142
Node node = new Node();

converter/src/test/resources/cpc_plus/failure/fixture.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@
175175
"errorCode": 25,
176176
"subs": [
177177
"cpci",
178-
"[a-zA-Z, _]*"
178+
"[a-zA-Z, _,1-9]*"
179179
],
180180
"occurrences": 1
181181
}

0 commit comments

Comments
 (0)