Skip to content

Commit c338d7e

Browse files
Add Minimal TylerCodesParser
Handles vet for CaseCategory, CaseType, and SubType. Starts to initialize and pass around a CodesParser as needed.
1 parent fe721f7 commit c338d7e

18 files changed

Lines changed: 601 additions & 152 deletions

proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/DocassembleToFilingInformationConverter.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.fasterxml.jackson.databind.module.SimpleModule;
66
import com.hubspot.algebra.Result;
77
import edu.suffolk.litlab.efsp.model.FilingInformation;
8+
import edu.suffolk.litlab.efsp.server.ecf4.CodesParser;
89
import edu.suffolk.litlab.efsp.tyler.TylerEnv;
910
import edu.suffolk.litlab.efsp.utils.FilingError;
1011
import edu.suffolk.litlab.efsp.utils.InfoCollector;
@@ -24,12 +25,12 @@ public DocassembleToFilingInformationConverter(TylerEnv tylerEnv) {
2425

2526
@Override
2627
public Result<FilingInformation, FilingError> traverseInterview(
27-
String interviewContents, InfoCollector collector) {
28+
String interviewContents, CodesParser parser, InfoCollector collector) {
2829
SimpleModule module = new SimpleModule();
2930
module.addDeserializer(
3031
FilingInformation.class,
3132
new FilingInformationDocassembleJacksonDeserializer(
32-
FilingInformation.class, collector, tylerEnv));
33+
FilingInformation.class, collector, parser, tylerEnv));
3334
ObjectMapper mapper = new ObjectMapper();
3435
mapper.registerModule(module);
3536
try {

proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/FilingInformationDocassembleJacksonDeserializer.java

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import edu.suffolk.litlab.efsp.model.LowerCourtInfo;
1414
import edu.suffolk.litlab.efsp.model.PartyId;
1515
import edu.suffolk.litlab.efsp.model.Person;
16+
import edu.suffolk.litlab.efsp.server.ecf4.CodesParser;
1617
import edu.suffolk.litlab.efsp.tyler.TylerEnv;
1718
import edu.suffolk.litlab.efsp.utils.FilingError;
1819
import edu.suffolk.litlab.efsp.utils.InfoCollector;
@@ -39,13 +40,15 @@ public class FilingInformationDocassembleJacksonDeserializer
3940

4041
private static final long serialVersionUID = 1L;
4142
private final InfoCollector classCollector;
43+
private final CodesParser parser;
4244

4345
/** If Tyler is setup on this server, this is the env we're submitting to. */
4446
private final TylerEnv tylerEnv;
4547

4648
public FilingInformationDocassembleJacksonDeserializer(
47-
Class<FilingInformation> t, InfoCollector collector, TylerEnv env) {
49+
Class<FilingInformation> t, InfoCollector collector, CodesParser parser, TylerEnv env) {
4850
super(t);
51+
this.parser = parser;
4952
this.classCollector = collector;
5053
this.tylerEnv = env;
5154
}
@@ -96,6 +99,8 @@ public FilingInformation fromNode(JsonNode node, InfoCollector collector) throws
9699
entities.setPreviousCaseId(extractNullableString(node.get("previous_case_id")));
97100
entities.setCaseDocketNumber(extractNullableString(node.get("docket_number")));
98101
boolean isFirstIndexedFiling = entities.getPreviousCaseId().isEmpty();
102+
boolean isInitialFiling =
103+
entities.getPreviousCaseId().isEmpty() && entities.getCaseDocketNumber().isEmpty();
99104

100105
List<Person> users = collectPeople(node, "users", collector);
101106
List<Person> otherParties = collectPeople(node, "other_parties", collector);
@@ -206,29 +211,65 @@ public FilingInformation fromNode(JsonNode node, InfoCollector collector) throws
206211
entities.setLowerCourtInfo(extractLowerCourt(node, collector));
207212

208213
JsonNode category = node.get("efile_case_category");
214+
var varBuilder =
215+
collector
216+
.varBuilder()
217+
.name("efile_case_category")
218+
.description("The top-level case category")
219+
.currentVal(category);
209220
if (category != null && !category.isNull() && category.isTextual()) {
210-
entities.setCaseCategoryCode(category.asText());
221+
var res = parser.vetCaseCat(category.asText());
222+
res.ifOk(
223+
code -> {
224+
entities.setCaseCategoryCode(code);
225+
});
226+
if (res.isErr()) {
227+
var variable = collector.addCodeError(res.expectErr("checked err above"), varBuilder);
228+
// Foundational error: Category is sorely needed
229+
throw FilingError.wrongValue(variable);
230+
}
211231
} else if (isFirstIndexedFiling) {
212-
InterviewVariable var = collector.requestVar("efile_case_category", "", "text");
232+
// TODO: show the options?
233+
InterviewVariable var = varBuilder.build();
213234
collector.addRequired(var);
214235
}
215236

216237
JsonNode type = node.get("efile_case_type");
238+
var varCaseBuilder =
239+
collector.varBuilder().name("efile_case_type").description("").currentVal(type);
217240
if (type != null && type.isTextual()) {
218-
entities.setCaseTypeCode(type.asText());
241+
var res = parser.vetCaseType(type.asText(), entities.getCaseCategoryCode(), isInitialFiling);
242+
res.ifOk(
243+
code -> {
244+
entities.setCaseTypeCode(code);
245+
});
246+
if (res.isErr()) {
247+
collector.addCodeError(res.expectErr(""), varCaseBuilder);
248+
}
219249
} else if (isFirstIndexedFiling) {
220250
InterviewVariable var = collector.requestVar("efile_case_type", "", "text");
221251
collector.addRequired(var);
222252
}
223253

224254
JsonNode subtype = node.get("efile_case_subtype");
225255
if (subtype != null && subtype.isTextual()) {
226-
entities.setCaseSubtypeCode(subtype.asText());
256+
var res = parser.vetSubType(subtype.asText(), entities.getCaseTypeCode());
257+
res.ifOk(
258+
code -> {
259+
entities.setCaseSubtypeCode(code);
260+
});
261+
if (res.isErr()) {
262+
var err = res.expectErr("");
263+
InterviewVariable var =
264+
collector.requestVar(
265+
"efile_case_subtype", "", "choice", err.options(), Optional.of(err.given()));
266+
collector.addWrong(var);
267+
}
227268
} else if (isFirstIndexedFiling) {
228269
InterviewVariable var =
229270
collector.requestVar("efile_case_subtype", "subtype (not always present)", "text");
230271
collector.addOptional(var);
231-
entities.setCaseSubtypeCode("");
272+
entities.setCaseSubtypeCode(Optional.empty());
232273
}
233274

234275
// Get the interview metadablock TODO(brycew-later): just one for now

proxyserver/src/main/java/edu/suffolk/litlab/efsp/model/FilingInformation.java

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package edu.suffolk.litlab.efsp.model;
22

33
import com.fasterxml.jackson.databind.JsonNode;
4+
import edu.suffolk.litlab.efsp.ecfcodes.tyler.CaseCategory;
5+
import edu.suffolk.litlab.efsp.ecfcodes.tyler.CaseType;
6+
import edu.suffolk.litlab.efsp.ecfcodes.tyler.NameAndCode;
47
import java.time.LocalDate;
58
import java.util.ArrayList;
69
import java.util.List;
@@ -52,10 +55,9 @@ public class FilingInformation {
5255
/** Existing docket number, NOT from EFM system. For subsequent filing into non-indexed cases. */
5356
private Optional<String> caseDocketNumber = Optional.empty();
5457

55-
// TODO(brycew-later): refactor so this is selected only in Tyler stuff
56-
private String caseCategoryCode;
57-
private String caseTypeCode;
58-
private String caseSubtypeCode;
58+
private CaseCategory caseCategoryCode;
59+
private CaseType caseTypeCode;
60+
private Optional<NameAndCode> caseSubtypeCode;
5961
private String paymentId;
6062
private List<FilingDoc> filingDocs = List.of();
6163
private Optional<LocalDate> returnDate = Optional.empty();
@@ -146,19 +148,19 @@ public List<PartyId> getPartyRepByAttorney(String attorneyId) {
146148
return parties;
147149
}
148150

149-
public String getCaseCategoryCode() {
151+
public CaseCategory getCaseCategoryCode() {
150152
return caseCategoryCode;
151153
}
152154

153-
public String getCaseTypeCode() {
155+
public CaseType getCaseTypeCode() {
154156
return caseTypeCode;
155157
}
156158

157159
public List<CaseServiceContact> getServiceContacts() {
158160
return serviceContacts;
159161
}
160162

161-
public String getCaseSubtypeCode() {
163+
public Optional<NameAndCode> getCaseSubtypeCode() {
162164
return caseSubtypeCode;
163165
}
164166

@@ -218,7 +220,7 @@ public void setServiceContacts(List<CaseServiceContact> serviceContacts) {
218220
this.serviceContacts = serviceContacts;
219221
}
220222

221-
public void setCaseCategoryCode(String caseCategoryCode) {
223+
public void setCaseCategoryCode(CaseCategory caseCategoryCode) {
222224
this.caseCategoryCode = caseCategoryCode;
223225
}
224226

@@ -230,11 +232,11 @@ public void setCaseDocketNumber(String num) {
230232
this.caseDocketNumber = Optional.ofNullable(num);
231233
}
232234

233-
public void setCaseTypeCode(String caseTypeCode) {
235+
public void setCaseTypeCode(CaseType caseTypeCode) {
234236
this.caseTypeCode = caseTypeCode;
235237
}
236238

237-
public void setCaseSubtypeCode(String caseSubtypeId) {
239+
public void setCaseSubtypeCode(Optional<NameAndCode> caseSubtypeId) {
238240
this.caseSubtypeCode = caseSubtypeId;
239241
}
240242

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package edu.suffolk.litlab.efsp.server.ecf4;
2+
3+
import com.hubspot.algebra.Result;
4+
import edu.suffolk.litlab.efsp.ecfcodes.tyler.CaseCategory;
5+
import edu.suffolk.litlab.efsp.ecfcodes.tyler.CaseType;
6+
import edu.suffolk.litlab.efsp.ecfcodes.tyler.NameAndCode;
7+
import edu.suffolk.litlab.efsp.utils.FilingError;
8+
import java.util.List;
9+
import java.util.Optional;
10+
11+
public interface CodesParser {
12+
// Types specifically for errors.
13+
public sealed interface CodeError {}
14+
15+
public record NoMatchingCode(String given, List<String> options) implements CodeError {}
16+
17+
public record RequiredCodeNotPresent(List<String> options) implements CodeError {}
18+
19+
public record BadCode(FilingError err) implements CodeError {}
20+
21+
public Result<CaseCategory, CodeError> vetCaseCat(String caseCategoryCode);
22+
23+
public Result<CaseType, CodeError> vetCaseType(
24+
String caseTypeCode, CaseCategory caseCategory, boolean isInitialFiling);
25+
26+
public Result<Optional<NameAndCode>, NoMatchingCode> vetSubType(
27+
String subtypeCode, CaseType caseType);
28+
}

proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCaseTypeFactory.java

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -408,26 +408,10 @@ public List<FilingAssociationType> lateStageFilingAssociationAdd(
408408
ecfAug.setCaseTypeText(Ecf4Helper.convertText(comboCodes.type.code));
409409
}
410410

411-
DataFieldRow subTypeConfig = serializer.allDataFields.getFieldRow("CaseInformationCaseSubType");
412-
if (subTypeConfig.isvisible) {
413-
List<NameAndCode> subTypes = cd.getCaseSubtypesFor(courtLocation.code, comboCodes.type.code);
414-
Optional<NameAndCode> maybeSubtype =
415-
subTypes.stream()
416-
.filter(type -> type.getCode().equals(info.getCaseSubtypeCode()))
417-
.findFirst();
411+
var maybeSubtype = info.getCaseSubtypeCode();
418412

419-
if (maybeSubtype.isPresent()) {
420-
ecfAug.setCaseSubTypeText(Ecf4Helper.convertText(maybeSubtype.get().getCode()));
421-
} else if (subTypeConfig.isrequired) {
422-
InterviewVariable subTypeVar =
423-
collector.requestVar(
424-
"efile_case_subtype",
425-
"Sub type of the case",
426-
"choices",
427-
subTypes.stream().map(nac -> nac.getName()).collect(Collectors.toList()),
428-
Optional.of(info.getCaseSubtypeCode()));
429-
collector.addWrong(subTypeVar);
430-
}
413+
if (maybeSubtype.isPresent()) {
414+
ecfAug.setCaseSubTypeText(Ecf4Helper.convertText(maybeSubtype.get().getCode()));
431415
}
432416

433417
List<PartyType> partyTypes = cd.getPartyTypeFor(courtLocation.code, comboCodes.type.code);

proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCourtSpecificSerializer.java

Lines changed: 4 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -109,18 +109,13 @@ public EcfCourtSpecificSerializer(CodeDatabase cd, CourtLocationInfo court) {
109109
* Given the case info from a case that's already in the court's system on a subsequent filing.
110110
*/
111111
public ComboCaseCodes serializeCaseCodesIndexed(
112-
String caseCategoryCode,
113-
String caseTypeCode,
112+
CaseCategory caseCategory,
113+
CaseType type,
114114
List<String> filingCodeStrs,
115115
Map<String, Person> existingParties,
116116
Map<String, Person> newParties,
117117
InfoCollector collector)
118118
throws FilingError {
119-
CaseCategory caseCategory =
120-
vetCaseCat(cd.getCaseCategoryWithCode(this.court.code, caseCategoryCode), collector);
121-
List<CaseType> caseTypes = cd.getCaseTypesFor(court.code, caseCategory.code, Optional.empty());
122-
Optional<CaseType> maybeType = cd.getCaseTypeWith(court.code, caseTypeCode);
123-
CaseType type = vetCaseType(maybeType, caseTypes, caseCategory, collector, false);
124119
List<FilingCode> filingRealCodes =
125120
vetFilingTypes(filingCodeStrs, caseCategory, type, collector, false);
126121
Map<String, Pair<PartyType, Boolean>> partyTypes =
@@ -131,14 +126,8 @@ public ComboCaseCodes serializeCaseCodesIndexed(
131126
/** Either an initial filing, or a non-indexed case. */
132127
public ComboCaseCodes serializeCaseCodes(
133128
FilingInformation info, InfoCollector collector, boolean isInitialFiling) throws FilingError {
134-
Optional<CaseCategory> maybeCaseCat =
135-
cd.getCaseCategoryWithCode(this.court.code, info.getCaseCategoryCode());
136-
CaseCategory caseCategory = vetCaseCat(maybeCaseCat, collector);
137-
138-
List<CaseType> caseTypes = cd.getCaseTypesFor(court.code, caseCategory.code, Optional.empty());
139-
Optional<CaseType> maybeType =
140-
caseTypes.stream().filter(type -> type.code.equals(info.getCaseTypeCode())).findFirst();
141-
CaseType type = vetCaseType(maybeType, caseTypes, caseCategory, collector, isInitialFiling);
129+
CaseCategory caseCategory = info.getCaseCategoryCode();
130+
CaseType type = info.getCaseTypeCode();
142131

143132
if (!type.initial && info.getCaseDocketNumber().isEmpty()) {
144133
FilingError err =
@@ -173,70 +162,6 @@ public ComboCaseCodes serializeCaseCodes(
173162
return new ComboCaseCodes(caseCategory, type, filingCodes, partyTypes);
174163
}
175164

176-
private CaseCategory vetCaseCat(Optional<CaseCategory> caseCat, InfoCollector collector)
177-
throws FilingError {
178-
if (caseCat.isEmpty()) {
179-
List<CaseCategory> categories = cd.getCaseCategoriesFor(court.code);
180-
// TODO(brycew-later): handle that these variables could be different from different
181-
// deserializers
182-
InterviewVariable var =
183-
collector.requestVar(
184-
"efile_case_category",
185-
"",
186-
"choice",
187-
categories.stream().map(cat -> cat.code).collect(Collectors.toList()),
188-
caseCat.map(CaseCategory::getCode));
189-
collector.addWrong(var);
190-
// Foundational error: Category is sorely needed
191-
throw FilingError.wrongValue(var);
192-
}
193-
return caseCat.get();
194-
}
195-
196-
private CaseType vetCaseType(
197-
Optional<CaseType> maybeType,
198-
List<CaseType> caseTypes,
199-
CaseCategory caseCategory,
200-
InfoCollector collector,
201-
boolean isInitialFiling)
202-
throws FilingError {
203-
if (caseTypes.isEmpty()) {
204-
FilingError err =
205-
FilingError.serverError(
206-
"There are no caseTypes for " + court.code + " and " + caseCategory.code);
207-
collector.error(err);
208-
}
209-
if (maybeType.isEmpty()) {
210-
InterviewVariable var =
211-
collector.requestVar(
212-
"efile_case_type",
213-
"",
214-
"choice",
215-
caseTypes.stream().map(type -> type.name).collect(Collectors.toList()),
216-
maybeType.map(CaseType::toString));
217-
collector.addWrong(var);
218-
throw FilingError.wrongValue(var);
219-
}
220-
CaseType type = maybeType.get();
221-
// Check if the court doesn't handle this type (initial vs subsequent) of filing
222-
if (isInitialFiling && (!type.initial || !court.initial)) {
223-
FilingError err =
224-
FilingError.malformedInterview(
225-
"An Initial"
226-
+ " filing can't be filed at "
227-
+ court.name
228-
+ " or be of filing type "
229-
+ type.name);
230-
collector.error(err);
231-
} else if (!isInitialFiling && (!court.subsequent)) {
232-
FilingError err =
233-
FilingError.malformedInterview("A Subsequent filing can't be filed at " + court.name);
234-
collector.error(err);
235-
}
236-
237-
return maybeType.get();
238-
}
239-
240165
private List<FilingCode> vetFilingTypes(
241166
List<String> maybeCodeStrs,
242167
CaseCategory caseCategory,

0 commit comments

Comments
 (0)