From 0d60b82b1ea8787e9c9fc280ee48dd1d6d9df722 Mon Sep 17 00:00:00 2001 From: Bryce Willey Date: Thu, 4 Jun 2026 10:00:16 -0400 Subject: [PATCH 1/4] Vet FilerType --- ...rmationDocassembleJacksonDeserializer.java | 9 +++++ .../litlab/efsp/model/FilingInformation.java | 11 ++++++ .../litlab/efsp/server/ecf4/CodesParser.java | 3 ++ .../efsp/server/ecf4/EcfCaseTypeFactory.java | 36 +++---------------- .../server/ecf4/tyler/TylerCodesParser.java | 29 +++++++++++++++ 5 files changed, 57 insertions(+), 31 deletions(-) diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/FilingInformationDocassembleJacksonDeserializer.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/FilingInformationDocassembleJacksonDeserializer.java index 97b428f35..1626caae6 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/FilingInformationDocassembleJacksonDeserializer.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/FilingInformationDocassembleJacksonDeserializer.java @@ -400,6 +400,15 @@ public FilingInformation fromNode(JsonNode node, InfoCollector collector) throws } entities.setReturnDate(extractReturnDate(node.get("return_date"), collector)); + + var filerTypeRes = parser.vetFilerType(getStringMember(node, "filer_type")); + if (filerTypeRes.isErr()) { + var filerTypeBuilder = collector.varBuilder().name("filer_type"); + collector.addCodeError(filerTypeRes.expectErr(""), filerTypeBuilder); + } else { + entities.setFilerType(filerTypeRes.expect("")); + } + entities.setMiscInfo(node); return entities; diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/model/FilingInformation.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/model/FilingInformation.java index 716e46a9b..9cada2eff 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/model/FilingInformation.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/model/FilingInformation.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.databind.JsonNode; import edu.suffolk.litlab.efsp.ecfcodes.tyler.CaseCategory; import edu.suffolk.litlab.efsp.ecfcodes.tyler.CaseType; +import edu.suffolk.litlab.efsp.ecfcodes.tyler.FilerType; import edu.suffolk.litlab.efsp.ecfcodes.tyler.NameAndCode; import java.time.LocalDate; import java.util.ArrayList; @@ -69,6 +70,8 @@ public class FilingInformation { private Person leadContact; + private Optional filerType; + private JsonNode miscInfo; /** @@ -194,6 +197,10 @@ public Optional getReturnDate() { return returnDate; } + public Optional getFilerType() { + return filerType; + } + public JsonNode getMiscInfo() { return miscInfo; } @@ -274,6 +281,10 @@ public void setReturnDate(Optional returnDate) { this.returnDate = returnDate; } + public void setFilerType(Optional filerType) { + this.filerType = filerType; + } + public void setMiscInfo(JsonNode node) { this.miscInfo = node; } diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/CodesParser.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/CodesParser.java index 0d44e188f..05799c5b7 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/CodesParser.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/CodesParser.java @@ -6,6 +6,7 @@ import edu.suffolk.litlab.efsp.ecfcodes.tyler.CaseType; import edu.suffolk.litlab.efsp.ecfcodes.tyler.DocumentTypeTableRow; import edu.suffolk.litlab.efsp.ecfcodes.tyler.FileType; +import edu.suffolk.litlab.efsp.ecfcodes.tyler.FilerType; import edu.suffolk.litlab.efsp.ecfcodes.tyler.FilingCode; import edu.suffolk.litlab.efsp.ecfcodes.tyler.FilingComponent; import edu.suffolk.litlab.efsp.ecfcodes.tyler.NameAndCode; @@ -105,6 +106,8 @@ public Result, List> vetOptionalServices( public Result vetFilingComponent( String filingComponent, ArrayList components); + public Result, CodeError> vetFilerType(Optional maybeFilerType); + public Result, CodeError> vetDocType( String docTypeStr, FilingCode filing); diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCaseTypeFactory.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCaseTypeFactory.java index d6faf8a8e..f55ea7414 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCaseTypeFactory.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCaseTypeFactory.java @@ -26,7 +26,6 @@ import edu.suffolk.litlab.efsp.ecfcodes.tyler.ComboCaseCodes; import edu.suffolk.litlab.efsp.ecfcodes.tyler.CourtLocationInfo; import edu.suffolk.litlab.efsp.ecfcodes.tyler.DataFieldRow; -import edu.suffolk.litlab.efsp.ecfcodes.tyler.FilerType; import edu.suffolk.litlab.efsp.ecfcodes.tyler.NameAndCode; import edu.suffolk.litlab.efsp.model.CaseServiceContact; import edu.suffolk.litlab.efsp.model.ContactInformation; @@ -599,36 +598,11 @@ public List lateStageFilingAssociationAdd( } // Filing - DataFieldRow filertype = serializer.allDataFields.getFieldRow("FilingFilerType"); - if (filertype.isvisible) { - List allTypes = cd.getFilerTypes(courtLocation.code); - String filerTypeName = "filer_type"; - JsonNode filerTypeNode = miscInfo.get(filerTypeName); - InterviewVariable var = - collector.requestVar( - filerTypeName, - "Metadata about the filer of this case", - "choices", - allTypes.stream().map(t -> t.code).collect(Collectors.toList()), - Optional.ofNullable(filerTypeNode).map(JsonNode::toString)); - if (filerTypeNode != null && filerTypeNode.isTextual()) { - String filerType = filerTypeNode.asText(); - Optional typeInfo = - allTypes.stream().filter(t -> t.code.equalsIgnoreCase(filerType)).findFirst(); - if (typeInfo.isPresent()) { - ecfAug.setFilerTypeText(Ecf4Helper.convertText(typeInfo.get().code)); - } else { - collector.addWrong(var); - } - } else { - Optional defaultType = allTypes.stream().filter(t -> t.isDefault).findFirst(); - if (defaultType.isPresent()) { - ecfAug.setFilerTypeText(Ecf4Helper.convertText(defaultType.get().code)); - } else if (filertype.isrequired) { - collector.addRequired(var); - } - } - } + info.getFilerType() + .ifPresent( + filerType -> { + ecfAug.setFilerTypeText(Ecf4Helper.convertText(filerType.code)); + }); if (courtLocation.allowreturndate && info.getReturnDate().isPresent()) { ecfAug.setReturnDate(Ecf4Helper.convertDate(info.getReturnDate().get())); diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/tyler/TylerCodesParser.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/tyler/TylerCodesParser.java index 408ca3d9d..537b13e43 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/tyler/TylerCodesParser.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/tyler/TylerCodesParser.java @@ -13,6 +13,7 @@ import edu.suffolk.litlab.efsp.ecfcodes.tyler.DataFields; import edu.suffolk.litlab.efsp.ecfcodes.tyler.DocumentTypeTableRow; import edu.suffolk.litlab.efsp.ecfcodes.tyler.FileType; +import edu.suffolk.litlab.efsp.ecfcodes.tyler.FilerType; import edu.suffolk.litlab.efsp.ecfcodes.tyler.FilingCode; import edu.suffolk.litlab.efsp.ecfcodes.tyler.FilingComponent; import edu.suffolk.litlab.efsp.ecfcodes.tyler.NameAndCode; @@ -517,6 +518,34 @@ public Result, CodeError> vetDocType( return Result.ok(Optional.empty()); } + public Result, CodeError> vetFilerType(Optional maybeFilerType) { + DataFieldRow filertype = allDataFields.getFieldRow("FilingFilerType"); + if (filertype.isvisible) { + List allTypes = cd.getFilerTypes(this.court.code); + // allTypes.stream().map(t -> t.code).toList()); + if (maybeFilerType.isPresent()) { + String filerType = maybeFilerType.get(); + Optional typeInfo = + allTypes.stream().filter(t -> t.code.equalsIgnoreCase(filerType)).findFirst(); + if (typeInfo.isEmpty()) { + return Result.err( + new NoMatchingCode(filerType, allTypes.stream().map(t -> t.code).toList())); + } + return Result.ok(typeInfo); + } else { + // Choose a default, if there's one present. + Optional defaultType = allTypes.stream().filter(t -> t.isDefault).findFirst(); + if (defaultType.isPresent()) { + return Result.ok(defaultType); + } else if (filertype.isrequired) { + return Result.err( + new RequiredCodeNotPresent(allTypes.stream().map(t -> t.code).toList())); + } + } + } + return Result.ok(Optional.empty()); + } + // Note: older versions of this code passed back a list of proc/rem codes. Doesn't make a ton of // sense, // and Tyler's docs only refer to the code in the singular. So only returning one here. From eea25e0f8d8ee08c15ed2341e9719384d2b82119 Mon Sep 17 00:00:00 2001 From: Bryce Willey Date: Thu, 4 Jun 2026 10:12:24 -0400 Subject: [PATCH 2/4] Vet Filing Associations --- .../suffolk/litlab/efsp/server/ecf4/CodesParser.java | 2 ++ .../litlab/efsp/server/ecf4/EcfCaseTypeFactory.java | 10 +++------- .../efsp/server/ecf4/tyler/TylerCodesParser.java | 11 ++++++++++- .../litlab/efsp/server/setup/tyler/Ecf4Filer.java | 9 +++++---- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/CodesParser.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/CodesParser.java index 05799c5b7..ad0bc9582 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/CodesParser.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/CodesParser.java @@ -154,4 +154,6 @@ public Optional getDocumentDescription( public Result vetFileName(String fileName); public Result vetFilingDocSize(List docs); + + public boolean useFilingAssociations(); } diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCaseTypeFactory.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCaseTypeFactory.java index f55ea7414..49ed16b1f 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCaseTypeFactory.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCaseTypeFactory.java @@ -214,18 +214,15 @@ public static CaseQueryCriteriaType getCriteria() { * the ID. But we don't have the filing document objects when making the case. */ public List lateStageFilingAssociationAdd( - EcfCourtSpecificSerializer serializer, Map filingIdToObj, Map> filingAssociations, Map partyIdToRefObj) { - DataFieldRow filingcaseparties = serializer.allDataFields.getFieldRow("FilingEventCaseParties"); var toReturn = new ArrayList(); var structOf = new ecf4.latest.gov.niem.niem.structures._2.ObjectFactory(); - if (filingcaseparties.isrequired) { - for (Map.Entry filingObj : filingIdToObj.entrySet()) { - ecf4.latest.gov.niem.niem.structures._2.ReferenceType filingRt = - structOf.createReferenceType(); + for (Map.Entry filingObj : filingIdToObj.entrySet()) { + ecf4.latest.gov.niem.niem.structures._2.ReferenceType filingRt = + structOf.createReferenceType(); filingRt.setRef(filingObj.getValue()); var filingAssociation = filingAssociations.get(filingObj.getKey()); for (PartyId partyId : filingAssociation) { @@ -241,7 +238,6 @@ public List lateStageFilingAssociationAdd( log.warn("Parties that do exist: {}", List.of(partyIdToRefObj.keySet().toArray())); } } - } } return toReturn; } diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/tyler/TylerCodesParser.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/tyler/TylerCodesParser.java index 537b13e43..12586c278 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/tyler/TylerCodesParser.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/tyler/TylerCodesParser.java @@ -627,7 +627,6 @@ public Result, CodeError> vetDamageAmount( } //////// Still TODO - // Filer Types // Filing Associations // Anything else not currently checked @@ -967,4 +966,14 @@ public Result vetFilingDocSize(List docs) } return Result.nullOk(); } + + /** + * Get if we need to add an association between filings and case parties. Is simply a boolean + * because there's no filing error that needs to be swallowed. + * + * @return + */ + public boolean useFilingAssociations() { + return allDataFields.getFieldRow("FilingEventCaseParties").isrequired; + } } diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/setup/tyler/Ecf4Filer.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/setup/tyler/Ecf4Filer.java index 7a5f88fb7..be63d04b9 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/setup/tyler/Ecf4Filer.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/setup/tyler/Ecf4Filer.java @@ -500,10 +500,11 @@ private CoreMessageAndNames prepareFiling( info.getFilings().stream() .collect( Collectors.toMap(f -> f.getIdString(), f -> f.getFilingPartyIds())); - for (var association : - ecfCaseFactory.lateStageFilingAssociationAdd( - serializer, filingIdToObj, filingAssociations, pair.getRight())) { - aug.getFilingAssociation().add(association); + if (parser.useFilingAssociations()) { + for (var association : + ecfCaseFactory.lateStageFilingAssociationAdd(filingIdToObj, filingAssociations, pair.getRight())) { + aug.getFilingAssociation().add(association); + } } }); log.info( From 72aca2e3bcc9ef30a7ea575f2cdddbfa861554e4 Mon Sep 17 00:00:00 2001 From: Bryce Willey Date: Thu, 4 Jun 2026 11:59:31 -0400 Subject: [PATCH 3/4] Cleaning up other things to vet --- ...AddressDocassembleJacksonDeserializer.java | 11 +- ...lingDocDocassembleJacksonDeserializer.java | 14 +- ...rmationDocassembleJacksonDeserializer.java | 3 + .../PersonDocassembleJacksonDeserializer.java | 2 +- .../suffolk/litlab/efsp/model/FilingDoc.java | 3 +- .../litlab/efsp/server/ecf4/CodesParser.java | 8 +- .../efsp/server/ecf4/EcfCaseTypeFactory.java | 11 +- .../ecf4/EcfCourtSpecificSerializer.java | 151 ++++-------------- .../server/ecf4/tyler/TylerCodesParser.java | 38 ++++- .../services/CourtSchedulingService.java | 3 +- .../efsp/server/setup/tyler/Ecf4Filer.java | 25 +-- ...DocDocassembleJacksonDeserializerTest.java | 40 ++--- .../litlab/efsp/server/AddressTest.java | 7 +- .../ecf4/EcfCourtSpecificSerializerTest.java | 21 ++- 14 files changed, 133 insertions(+), 204 deletions(-) diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/AddressDocassembleJacksonDeserializer.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/AddressDocassembleJacksonDeserializer.java index fcf28cd0f..f60ba6455 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/AddressDocassembleJacksonDeserializer.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/AddressDocassembleJacksonDeserializer.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.databind.JsonNode; import edu.suffolk.litlab.efsp.model.Address; +import edu.suffolk.litlab.efsp.server.ecf4.CodesParser; import edu.suffolk.litlab.efsp.utils.FilingError; import edu.suffolk.litlab.efsp.utils.InfoCollector; import edu.suffolk.litlab.efsp.utils.InterviewVariable; @@ -21,7 +22,7 @@ protected AddressDocassembleJacksonDeserializer() {} * * @throws FilingError if @param node isn't a JSON object describing an address */ - public static Optional
fromNode(JsonNode node, InfoCollector collector) + public static Optional
fromNode(JsonNode node, CodesParser parser, InfoCollector collector) throws FilingError { if (!node.isObject()) { FilingError err = @@ -65,6 +66,7 @@ public static Optional
fromNode(JsonNode node, InfoCollector collector) String zip = (node.has("zip")) ? node.get("zip").asText("") : ""; String country = (node.has("country")) ? node.get("country").asText("US").toUpperCase() : "US"; if (country.length() > 2) { + // TODO: consider handling ISO-3166-alpha 3 codes? log.error("Country {} isn't a valid country (should be 2 letters", country); InterviewVariable countryOptions = collector.requestVar( @@ -73,6 +75,13 @@ public static Optional
fromNode(JsonNode node, InfoCollector collector) collector.error(err); throw err; } + var stateRes = parser.vetStateCode(state, country); + if (stateRes.isErr()) { + var stateBuilder = collector.varBuilder().name("state"); + collector.addCodeError(stateRes.expectErr(""), stateBuilder); + } else { + state = stateRes.expect(""); + } Address addr = new Address(address, unit, city, state, zip, country); return Optional.of(addr); } diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/FilingDocDocassembleJacksonDeserializer.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/FilingDocDocassembleJacksonDeserializer.java index a10c0c766..ada80985d 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/FilingDocDocassembleJacksonDeserializer.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/FilingDocDocassembleJacksonDeserializer.java @@ -25,6 +25,7 @@ import edu.suffolk.litlab.efsp.server.ecf4.CodesParser.TextVarError; import edu.suffolk.litlab.efsp.utils.FilingError; import edu.suffolk.litlab.efsp.utils.InfoCollector; +import edu.suffolk.litlab.efsp.utils.InterviewVariable; import edu.suffolk.litlab.efsp.utils.JsonHelpers; import fj.data.NonEmptyList; import fj.data.Option; @@ -57,6 +58,7 @@ public static Optional fromNode( int sequenceNum, List filingOptions, boolean isInitialFiling, + boolean hasServiceContacts, CodesParser parser, InfoCollector collector) throws FilingError { @@ -161,7 +163,7 @@ public static Optional fromNode( yield Optional.empty(); } }; - var actionRes = parser.vetFilingAction(maybeAction, isInitialFiling); + var actionRes = parser.vetFilingAction(maybeAction, isInitialFiling, hasServiceContacts); if (actionRes.isErr()) { collector.addWrong( collector @@ -187,6 +189,16 @@ public static Optional fromNode( return PartyId.Already(fp); }) .collect(Collectors.toList()); + var partiesRes = parser.vetFilingParties(fullParties); + if (partiesRes.isErr()) { + InterviewVariable partyVar = + collector.requestVar( + "filing_parties", "The Parties that are filing this document", "text"); + collector.addRequired(partyVar); + } else { + fullParties = partiesRes.expect(""); + } + var components = new ArrayList(parser.retrieveFilingComponents(filingType)); fj.data.List attachments = fj.data.List.nil(); if (node.has("tyler_merge_attachments") diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/FilingInformationDocassembleJacksonDeserializer.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/FilingInformationDocassembleJacksonDeserializer.java index 1626caae6..78924f655 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/FilingInformationDocassembleJacksonDeserializer.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/FilingInformationDocassembleJacksonDeserializer.java @@ -319,6 +319,7 @@ public FilingInformation fromNode(JsonNode node, InfoCollector collector) throws varToPartyId, filingOptions, isInitialFiling, + entities.getServiceContacts().size() > 0, parser, collector)); if (entities.getFilings().isEmpty()) { @@ -526,6 +527,7 @@ private static List extractFilingDocs( Map varToPartyId, List filingOptions, boolean isInitialFiling, + boolean hasServiceContacts, CodesParser parser, InfoCollector collector) throws FilingError { @@ -556,6 +558,7 @@ private static List extractFilingDocs( filingDocs.size(), filingOptions, isInitialFiling, + hasServiceContacts, parser, collector); collector.popAttributeStack(); diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/PersonDocassembleJacksonDeserializer.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/PersonDocassembleJacksonDeserializer.java index a8c4cbf1e..7e8bee989 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/PersonDocassembleJacksonDeserializer.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/PersonDocassembleJacksonDeserializer.java @@ -64,7 +64,7 @@ public static Result fromNode( if (node.has("address") && node.get("address").isObject()) { collector.pushAttributeStack("address"); try { - addr = AddressDocassembleJacksonDeserializer.fromNode(node.get("address"), collector); + addr = AddressDocassembleJacksonDeserializer.fromNode(node.get("address"), parser, collector); collector.popAttributeStack(); } catch (FilingError err) { if (!err.getType().equals(FilingError.Type.MissingRequired)) { diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/model/FilingDoc.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/model/FilingDoc.java index 816892dc3..14a779e6b 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/model/FilingDoc.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/model/FilingDoc.java @@ -10,8 +10,7 @@ import java.util.UUID; import org.apache.commons.lang3.builder.ToStringBuilder; -// TODO(brycew-later): this class is a mess. Refactor, considering the same pattern that's in -// FilingInformation: add a JsonNode / generic container for EFM specific settings +// TODO(brycew-later): this class is a mess. Refactor public class FilingDoc { private final Optional userProvidedDescription; // Tyler has crazy dumb rules regarding the title of a doc; it's set here diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/CodesParser.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/CodesParser.java index ad0bc9582..5817da2dc 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/CodesParser.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/CodesParser.java @@ -50,6 +50,8 @@ public sealed interface AttorneyError {} public record NoMultipleAttorneys() implements AttorneyError {} public record RequiredAttorneys() implements AttorneyError {} + public record RequiredFilingParty() {} + public record DueDateRequired() {} public record InvalidFilingAction(String reason) {} @@ -83,6 +85,8 @@ public Result vetFilingType( public Result, CodeError> vetLangCode(Optional lang); + public Result vetStateCode(String state, String countryString); + public Result, CrossReferenceError> getCrossRefIds( Map crossRefs, CaseType caseType); @@ -92,6 +96,8 @@ public Result, CodeError> vetPartyTypes( CaseType type, boolean isFirstIndexedFiling); + public Result, RequiredFilingParty> vetFilingParties(List filingParties); + public Result, CodeError> vetMotionCode( Optional motionCode, FilingCode filing); @@ -146,7 +152,7 @@ public Result, DueDateRequired> vetDueDate( Optional dueDate, FilingCode filing); public Result, InvalidFilingAction> vetFilingAction( - Optional filingAction, boolean isInitialFiling); + Optional filingAction, boolean isInitialFiling, boolean hasServiceContacts); public Optional getDocumentDescription( String description, String firstFileName, FilingCode filing); diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCaseTypeFactory.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCaseTypeFactory.java index 49ed16b1f..57bfd1349 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCaseTypeFactory.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCaseTypeFactory.java @@ -25,7 +25,6 @@ import edu.suffolk.litlab.efsp.ecfcodes.tyler.CodeDatabase; import edu.suffolk.litlab.efsp.ecfcodes.tyler.ComboCaseCodes; import edu.suffolk.litlab.efsp.ecfcodes.tyler.CourtLocationInfo; -import edu.suffolk.litlab.efsp.ecfcodes.tyler.DataFieldRow; import edu.suffolk.litlab.efsp.ecfcodes.tyler.NameAndCode; import edu.suffolk.litlab.efsp.model.CaseServiceContact; import edu.suffolk.litlab.efsp.model.ContactInformation; @@ -56,7 +55,6 @@ public class EcfCaseTypeFactory { private static Logger log = LoggerFactory.getLogger(EcfCaseTypeFactory.class); - private final CodeDatabase cd; private final ecf4.latest.tyler.ecf.extensions.common.ObjectFactory tylerObjFac; private final ecf4.latest.oasis.names.tc.legalxml_courtfiling.schema.xsd.commontypes_4 .ObjectFactory @@ -66,7 +64,6 @@ public class EcfCaseTypeFactory { private final Jurisdiction jurisdiction; public EcfCaseTypeFactory(CodeDatabase cd, Jurisdiction jurisdiction) { - this.cd = cd; this.tylerObjFac = new ecf4.latest.tyler.ecf.extensions.common.ObjectFactory(); this.ecfCommonObjFac = new ecf4.latest.oasis.names.tc.legalxml_courtfiling.schema.xsd.commontypes_4 @@ -411,10 +408,8 @@ public List lateStageFilingAssociationAdd( Map partyIdToRefObj = new HashMap<>(); int i = 0; for (Person plaintiff : info.getNewPlaintiffs()) { - collector.pushAttributeStack("plaintiffs[" + i + ']'); var pInfo = comboCodes.partyInfo().get(plaintiff.getPartyId()); - CaseParticipantType cp = serializer.serializeEcfCaseParticipant(plaintiff, pInfo, collector); - collector.popAttributeStack(); + CaseParticipantType cp = serializer.serializeEcfCaseParticipant(plaintiff, pInfo); ecfAug.getCaseParticipant().add(ecfCommonObjFac.createCaseParticipant(cp)); partyIdToRefObj.put(plaintiff.getIdString(), cp.getEntityRepresentation().getValue()); presentPartyTypes.add(pInfo.type().code); @@ -422,10 +417,8 @@ public List lateStageFilingAssociationAdd( i = 0; for (Person defendant : info.getNewDefendants()) { - collector.pushAttributeStack("defendants[" + i + ']'); var pInfo = comboCodes.partyInfo().get(defendant.getPartyId()); - CaseParticipantType cp = serializer.serializeEcfCaseParticipant(defendant, pInfo, collector); - collector.popAttributeStack(); + CaseParticipantType cp = serializer.serializeEcfCaseParticipant(defendant, pInfo); ecfAug.getCaseParticipant().add(ecfCommonObjFac.createCaseParticipant(cp)); partyIdToRefObj.put(defendant.getIdString(), cp.getEntityRepresentation().getValue()); presentPartyTypes.add(pInfo.type().code); diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCourtSpecificSerializer.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCourtSpecificSerializer.java index 2bbe4e1be..e3d318d70 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCourtSpecificSerializer.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCourtSpecificSerializer.java @@ -36,11 +36,7 @@ import ecf4.latest.tyler.ecf.extensions.common.FilingTypeType; import edu.suffolk.litlab.efsp.ecfcodes.tyler.CaseCategory; import edu.suffolk.litlab.efsp.ecfcodes.tyler.CaseType; -import edu.suffolk.litlab.efsp.ecfcodes.tyler.CodeDatabase; import edu.suffolk.litlab.efsp.ecfcodes.tyler.ComboCaseCodes; -import edu.suffolk.litlab.efsp.ecfcodes.tyler.CourtLocationInfo; -import edu.suffolk.litlab.efsp.ecfcodes.tyler.DataFieldRow; -import edu.suffolk.litlab.efsp.ecfcodes.tyler.DataFields; import edu.suffolk.litlab.efsp.ecfcodes.tyler.FilingCode; import edu.suffolk.litlab.efsp.ecfcodes.tyler.FilingComponent; import edu.suffolk.litlab.efsp.model.Address; @@ -56,13 +52,11 @@ import edu.suffolk.litlab.efsp.model.Person; import edu.suffolk.litlab.efsp.utils.FilingError; import edu.suffolk.litlab.efsp.utils.InfoCollector; -import edu.suffolk.litlab.efsp.utils.InterviewVariable; import jakarta.xml.bind.JAXBElement; import java.io.IOException; import java.math.BigDecimal; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.function.Function; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -70,9 +64,6 @@ public class EcfCourtSpecificSerializer { private static Logger log = LoggerFactory.getLogger(EcfCourtSpecificSerializer.class); - private final CodeDatabase cd; - private final CourtLocationInfo court; - public final DataFields allDataFields; private static final ecf4.latest.gov.niem.niem.niem_core._2.ObjectFactory niemObjFac = new ecf4.latest.gov.niem.niem.niem_core._2.ObjectFactory(); private static final ecf4.latest.gov.niem.niem.niem_core._2.ObjectFactory coreObjFac = @@ -87,11 +78,7 @@ public class EcfCourtSpecificSerializer { new ecf4.latest.oasis.names.tc.legalxml_courtfiling.schema.xsd.commontypes_4 .ObjectFactory(); - public EcfCourtSpecificSerializer(CodeDatabase cd, CourtLocationInfo court) { - this.cd = cd; - this.court = court; - this.allDataFields = cd.getDataFields(court.code); - } + public EcfCourtSpecificSerializer() {} /** Either an initial filing, or a non-indexed case. */ public ComboCaseCodes serializeCaseCodes( @@ -122,24 +109,13 @@ public ComboCaseCodes serializeCaseCodes( * @throws FilingError */ public CaseParticipantType serializeEcfCaseParticipant( - Person per, PartyInfo info, InfoCollector collector) throws FilingError { + Person per, PartyInfo info) throws FilingError { final CaseParticipantType cpt = ecfOf.createCaseParticipantType(); - ContactInformationType cit = serializeEcfContactInformation(per.getContactInfo(), collector); + ContactInformationType cit = serializeEcfContactInformation(per.getContactInfo()); if (per.isOrg()) { OrganizationAugmentationType aug = ecfOf.createOrganizationAugmentationType(); aug.getContactInformation().add(cit); OrganizationType ot = ecfOf.createOrganizationType(); - DataFieldRow orgNameRow = allDataFields.getFieldRow("PartyBusinessName"); - if (!orgNameRow.matchRegex(per.getName().getFullName())) { - InterviewVariable var = - collector.requestVar( - "name", "Name needs to match the regex: " + orgNameRow.regularexpression, "text"); - collector.addWrong(var); - } else if (per.getName().getFullName().length() > 400) { - InterviewVariable var = - collector.requestVar("name", "Name needs to be shorter that 400 characters", "text"); - collector.addWrong(var); - } ot.setOrganizationName(Ecf4Helper.convertText(per.getName().getFullName())); ot.setId(per.getIdString()); ot.getRest().add(ecfOf.createOrganizationAugmentation(aug)); @@ -161,7 +137,7 @@ public CaseParticipantType serializeEcfCaseParticipant( pt.setPersonCapability(extObjFac.createPersonCapability(ct)); } - pt.setPersonName(serializeNameType(per.getName(), collector)); + pt.setPersonName(serializeNameType(per.getName())); pt.setPersonAugmentation(aug); per.getGender() @@ -183,20 +159,15 @@ public CaseParticipantType serializeEcfCaseParticipant( pt.setPersonSex(niemObjFac.createPersonSexCode(sct)); }); - if (per.getLanguage().isPresent()) { - List langs = cd.getLanguageNames(this.court.code); - if (!langs.isEmpty()) { - // TODO(brycew): need to have an ISO 639_2 (language codes) converter, from general - // language name - /// https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes - LanguageCodeType lct = iso639Fac.createLanguageCodeType(); - PersonLanguageType plt = niemObjFac.createPersonLanguageType(); - plt.getLanguage().add(niemObjFac.createLanguageCode(lct)); - pt.setPersonPrimaryLanguage(plt); - } - // TODO(brycew): currently taking the safer option: if no languages are specified, don't - // add one - } + per.getLanguage().ifPresent(lang -> { + LanguageCodeType lct = iso639Fac.createLanguageCodeType(); + PersonLanguageType plt = niemObjFac.createPersonLanguageType(); + // TODO: need to test this with Tyler still: + // lct.setValue(lang); + plt.getLanguage(); + plt.getLanguage().add(niemObjFac.createLanguageCode(lct)); + pt.setPersonPrimaryLanguage(plt); + }); per.getBirthdate() .ifPresent( @@ -214,11 +185,11 @@ public CaseParticipantType serializeEcfCaseParticipant( } public ContactInformationType serializeEcfContactInformation( - ContactInformation contactInfo, InfoCollector collector) throws FilingError { + ContactInformation contactInfo) throws FilingError { ContactInformationType cit = niemObjFac.createContactInformationType(); if (contactInfo.getAddress().isPresent()) { Address addr = contactInfo.getAddress().get(); - JAXBElement contactMeans = serializeNiemContactMeans(addr, collector); + JAXBElement contactMeans = serializeNiemContactMeans(addr); cit.getContactMeans().add(contactMeans); } @@ -258,8 +229,7 @@ public static tyler.efm.latest.services.schema.common.AddressType serializeTyler * Returns the "ContactMeans" XML object from this address. Can be used in the ContactInformation * element. */ - public JAXBElement serializeNiemContactMeans( - Address address, InfoCollector collector) throws FilingError { + public JAXBElement serializeNiemContactMeans(Address address) { StreetType st = niemObjFac.createStreetType(); st.setStreetFullText( Ecf4Helper.convertText(address.getStreet() + " " + address.getApartment())); @@ -270,24 +240,7 @@ public JAXBElement serializeNiemContactMeans( sat.setLocationCityName(pntt); CountryCodeType cct = Ecf4Helper.strToCountryCode(address.getCountry()); sat.setLocationCountry(niemObjFac.createLocationCountryFIPS104Code(cct)); - if (!fillStateCode(address.getState(), cct, sat)) { - String countryString = cct.getValue(); - List stateCodes = cd.getStateCodes(this.court.code, countryString); - InterviewVariable var = - collector.requestVar( - "state", - "State in a country", - "choices", - stateCodes, - Optional.of(address.getState())); - if (stateCodes.isEmpty()) { - FilingError err = - FilingError.malformedInterview( - "There are no allowed states for " + countryString + " in " + cd.getDomain()); - collector.error(err); - } - collector.addWrong(var); - } + fillStateCode(address.getState(), cct, sat); sat.setLocationPostalCode(Ecf4Helper.convertString(address.getZip())); var addressType = niemObjFac.createAddressType(); addressType.setAddressRepresentation(niemObjFac.createStructuredAddress(sat)); @@ -299,8 +252,7 @@ public JAXBElement serializeNiemContactMeans( * * @throws FilingError */ - public ecf4.latest.gov.niem.niem.niem_core._2.PersonNameType serializeNameType( - Name name, InfoCollector collector) throws FilingError { + public ecf4.latest.gov.niem.niem.niem_core._2.PersonNameType serializeNameType(Name name) { Function wrapName = (n) -> { PersonNameTextType t = niemObjFac.createPersonNameTextType(); @@ -325,9 +277,8 @@ public JAXBElement filingDocToXml( CaseCategory caseCategory, CaseType motionType, FilingCode filing, - JsonNode miscInfo, - InfoCollector collector) - throws IOException, FilingError { + JsonNode miscInfo) + throws IOException { DocumentType docType = tylerObjFac.createDocumentType(); doc.descriptionFromSpec() .ifPresent( @@ -367,13 +318,6 @@ public JAXBElement filingDocToXml( filingPartyId.getIdentificationString(), (filingPartyId.isNewInCurrentFiling()) ? "REFERENCE" : "IDENTIFICATION")); } - // TODO(brycew): needs to handle when we can avoid using filing party ids - if (doc.getFilingPartyIds().isEmpty()) { - InterviewVariable partyVar = - collector.requestVar( - "filing_parties", "The Parties that are filing this document", "text"); - collector.addRequired(partyVar); - } docType.setDocumentMetadata(metadata); String cc = doc.getCourtesyCopies().stream().reduce("", (base, str) -> base + "," + str); @@ -390,32 +334,15 @@ public JAXBElement filingDocToXml( motion -> { docType.setMotionTypeCode(Ecf4Helper.convertText(motion.getCode())); }); - boolean serviceOnInitial = - switch (this.court.allowserviceoninitial) { - case TRUE -> true; - case FALSE -> false; - case DEFAULT -> allDataFields.getFieldRow("FilingServiceCheckBoxInitial").isvisible; - }; + // From Reference Guide: if no FilingAction is provided, the original default behavior applies: // * ReviewFiling API w/o service contacts: EFile // * ReviewFiling API w/ service contacts: EfileAndServe // * ServeFiling API: Serve - if (doc.getFilingAction().isPresent()) { - FilingTypeType act = filingActionToXml(doc.getFilingAction().get()); - if (isInitialFiling - && !serviceOnInitial - && (act.equals(FilingTypeType.E_FILE_AND_SERVE) || act.equals(FilingTypeType.SERVE))) { - InterviewVariable var = - collector.requestVar( - "filing_action", - "Cannot do service on initial filing", - "text", - List.of(), - doc.getFilingAction().map(FilingAction::toString)); - collector.addWrong(var); - } + doc.getFilingAction().ifPresent(action -> { + FilingTypeType act = filingActionToXml(action); docType.setFilingAction(act); - } + }); for (OptionalService serv : doc.getOptionalServices()) { DocumentOptionalServiceType xmlServ = tylerObjFac.createDocumentOptionalServiceType(); @@ -433,11 +360,9 @@ public JAXBElement filingDocToXml( DocumentRenditionMetadataType renditionMetadata = ecfOf.createDocumentRenditionMetadataType(); int idx = 0; for (var attachment : doc.getFilingAttachments()) { - collector.pushAttributeStack(".elements[" + idx + "]"); renditionMetadata .getDocumentAttachment() - .add(attachmentToXml(attachment, filing, miscInfo, collector, idx)); - collector.popAttributeStack(); + .add(attachmentToXml(attachment, filing, miscInfo, idx)); idx += 1; } @@ -454,26 +379,19 @@ public JAXBElement filingDocToXml( } private FilingTypeType filingActionToXml(FilingAction action) { - switch (action) { - case E_FILE: - return FilingTypeType.E_FILE; - case E_FILE_AND_SERVE: - return FilingTypeType.E_FILE_AND_SERVE; - case SERVE: - return FilingTypeType.SERVE; - default: - // I don't like enum defaults... - return FilingTypeType.E_FILE; - } + return switch (action) { + case E_FILE -> FilingTypeType.E_FILE; + case E_FILE_AND_SERVE -> FilingTypeType.E_FILE_AND_SERVE; + case SERVE -> FilingTypeType.SERVE; + }; } private DocumentAttachmentType attachmentToXml( FilingAttachment fa, FilingCode filing, JsonNode miscInfo, - InfoCollector collector, int seqNum) - throws IOException, FilingError { + throws IOException { // TODO(brycew-later): what should this actually be? Very unclear DocumentAttachmentType attachment = ecfOf.createDocumentAttachmentType(); attachment.setBinaryDescriptionText(Ecf4Helper.convertText(fa.getDocumentDescription())); @@ -511,13 +429,6 @@ private DocumentAttachmentType attachmentToXml( /** True if it worked. */ private boolean fillStateCode(String state, CountryCodeType country, StructuredAddressType sat) { - String countryString = country.getValue().toString(); - List stateCodes = cd.getStateCodes(this.court.code, countryString); - - if (!stateCodes.contains(state)) { - return false; - } - if (country.getValue().equalsIgnoreCase("US")) { try { USStateCodeSimpleType stateSimple = USStateCodeSimpleType.fromValue(state); diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/tyler/TylerCodesParser.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/tyler/TylerCodesParser.java index 12586c278..5c2ba0edb 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/tyler/TylerCodesParser.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/tyler/TylerCodesParser.java @@ -228,6 +228,9 @@ public Result, CodeError> vetLangCode(Optional lang) { return Result.ok(Optional.empty()); } + // TODO(brycew): need to have an ISO 639_2 (language codes) converter, from general + // language name + // https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes var matchedLang = langs.stream().filter(l -> l.getName().equalsIgnoreCase(lang.get())).findFirst(); if (matchedLang.isEmpty()) { @@ -238,6 +241,20 @@ public Result, CodeError> vetLangCode(Optional lang) { return Result.ok(matchedLang.map(l -> l.getCode())); } + public Result vetStateCode(String state, String countryString) { + List stateCodes = cd.getStateCodes(this.court.code, countryString); + if (stateCodes.isEmpty()) { + FilingError err = + FilingError.malformedInterview( + "There are no allowed states for " + countryString + " in " + cd.getDomain()); + return Result.err(new BadCode(err)); + } + if (!stateCodes.contains(state)) { + return Result.err(new NoMatchingCode(state, stateCodes)); + } + return Result.ok(state); + } + public Result, CrossReferenceError> getCrossRefIds( Map crossRefs, CaseType caseType) { List refs = cd.getCrossReference(court.code, caseType.code); @@ -382,6 +399,14 @@ public Result, CodeError> vetPartyTypes( return Result.ok(partyInfos); } + public Result, RequiredFilingParty> vetFilingParties(List filingParties) { + // TODO(brycew): needs to handle when we can avoid using filing party ids + if (filingParties.isEmpty()) { + return Result.err(new RequiredFilingParty()); + } + return Result.ok(filingParties); + } + // TODO: do good tests here public Result, CodeError> vetMotionCode( Optional motionCode, FilingCode filing) { @@ -881,11 +906,7 @@ public Result, DueDateRequired> vetDueDate( } public Result, InvalidFilingAction> vetFilingAction( - Optional filingAction, boolean isInitialFiling) { - // From Reference Guide: if no FilingAction is provided, the original default behavior applies: - // * ReviewFiling API w/o service contacts: EFile - // * ReviewFiling API w/ service contacts: EfileAndServe - // * ServeFiling API: Serve + Optional filingAction, boolean isInitialFiling, boolean hasServiceContacts) { if (filingAction.isPresent()) { FilingAction act = filingAction.get(); boolean serviceOnInitial = @@ -894,11 +915,16 @@ public Result, InvalidFilingAction> vetFilingAction( case FALSE -> false; case DEFAULT -> allDataFields.getFieldRow("FilingServiceCheckBoxInitial").isvisible; }; + boolean tryingToDoService = (act.equals(FilingAction.E_FILE_AND_SERVE) || act.equals(FilingAction.SERVE) || hasServiceContacts); if (isInitialFiling && !serviceOnInitial - && (act.equals(FilingAction.E_FILE_AND_SERVE) || act.equals(FilingAction.SERVE))) { + && tryingToDoService) { return Result.err(new InvalidFilingAction("Cannot do service on initial filing")); } + DataFieldRow checkBoxSub = allDataFields.getFieldRow("FilingServiceCheckBoxSubsequent"); + if (!isInitialFiling && !checkBoxSub.isvisible && tryingToDoService) { + return Result.err(new InvalidFilingAction("Court " + this.court.name + " cannot do service on subsequent filings")); + } } return Result.ok(filingAction); } diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/services/CourtSchedulingService.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/services/CourtSchedulingService.java index a80abf9a1..8c9a55f0a 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/services/CourtSchedulingService.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/services/CourtSchedulingService.java @@ -307,8 +307,7 @@ public Response getReturnDate( .build(); } try { - EcfCourtSpecificSerializer serializer = - new EcfCourtSpecificSerializer(cd, locationInfo.get()); + EcfCourtSpecificSerializer serializer = new EcfCourtSpecificSerializer(); boolean isInitialFiling = info.getPreviousCaseId().isEmpty() && info.getCaseDocketNumber().isEmpty(); boolean isFirstIndexedFiling = info.getPreviousCaseId().isEmpty(); diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/setup/tyler/Ecf4Filer.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/setup/tyler/Ecf4Filer.java index be63d04b9..4eaa07d15 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/setup/tyler/Ecf4Filer.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/setup/tyler/Ecf4Filer.java @@ -49,7 +49,6 @@ import edu.suffolk.litlab.efsp.ecfcodes.tyler.CodeDatabase; import edu.suffolk.litlab.efsp.ecfcodes.tyler.ComboCaseCodes; import edu.suffolk.litlab.efsp.ecfcodes.tyler.CourtLocationInfo; -import edu.suffolk.litlab.efsp.ecfcodes.tyler.DataFieldRow; import edu.suffolk.litlab.efsp.ecfcodes.tyler.Disclaimer; import edu.suffolk.litlab.efsp.ecfcodes.tyler.FilingCode; import edu.suffolk.litlab.efsp.ecfcodes.tyler.ServiceCodeType; @@ -240,7 +239,7 @@ private CoreMessageAndNames prepareFiling( collector.error(err); } - EcfCourtSpecificSerializer serializer = new EcfCourtSpecificSerializer(cd, locationInfo); + EcfCourtSpecificSerializer serializer = new EcfCourtSpecificSerializer(); var maybeParser = getParser(cd, locationInfo.code, apiToken); if (maybeParser.isEmpty()) { collector.error( @@ -408,28 +407,6 @@ private CoreMessageAndNames prepareFiling( cfm.getDocumentIdentification().add(id); } - boolean serviceOnInitial = - switch (locationInfo.allowserviceoninitial) { - case TRUE -> true; - case FALSE -> false; - case DEFAULT -> - cd.getDataField(locationInfo.code, "FilingServiceCheckBoxInitial").isvisible; - }; - if (isInitialFiling && !serviceOnInitial && info.getServiceContacts().size() > 0) { - FilingError err = - FilingError.malformedInterview( - "Court " + locationInfo.name + " doesn't allow service on initial filings"); - collector.error(err); - } - DataFieldRow checkBoxSub = - cd.getDataField(locationInfo.code, "FilingServiceCheckBoxSubsequent"); - if (!isInitialFiling && !checkBoxSub.isvisible && info.getServiceContacts().size() > 0) { - FilingError err = - FilingError.malformedInterview( - "Court " + locationInfo.name + " doesn't allow service on subsequent filings"); - collector.error(err); - } - cfm.setSendingMDELocationID(Ecf4Helper.convertId(ServiceHelpers.SERVICE_URL)); cfm.setSendingMDEProfileCode(ServiceHelpers.MDE_PROFILE_CODE); cfm.setCase(assembledCase); diff --git a/proxyserver/src/test/java/edu/suffolk/litlab/efsp/docassemble/FilingDocDocassembleJacksonDeserializerTest.java b/proxyserver/src/test/java/edu/suffolk/litlab/efsp/docassemble/FilingDocDocassembleJacksonDeserializerTest.java index d67baeeee..e7d323104 100644 --- a/proxyserver/src/test/java/edu/suffolk/litlab/efsp/docassemble/FilingDocDocassembleJacksonDeserializerTest.java +++ b/proxyserver/src/test/java/edu/suffolk/litlab/efsp/docassemble/FilingDocDocassembleJacksonDeserializerTest.java @@ -100,12 +100,12 @@ public void testWeirdJsonShouldBeEmpty() ObjectMapper m = new ObjectMapper(); assertThatThrownBy( () -> - fromNode(m.readTree("null"), varToPartyId, 0, filingCodes, true, parser, collector)) + fromNode(m.readTree("null"), varToPartyId, 0, filingCodes, true, false, parser, collector)) .isInstanceOf(FilingError.class); assertThatThrownBy( - () -> fromNode(m.readTree("[]"), varToPartyId, 0, filingCodes, true, parser, collector)) + () -> fromNode(m.readTree("[]"), varToPartyId, 0, filingCodes, true, false, parser, collector)) .isInstanceOf(FilingError.class); - var doc = fromNode(m.readTree("{}"), varToPartyId, 0, filingCodes, true, parser, collector); + var doc = fromNode(m.readTree("{}"), varToPartyId, 0, filingCodes, true, false, parser, collector); assertThat(doc).isEmpty(); } @@ -115,7 +115,7 @@ public void noAttachmentsShouldLoadDocument() throws FilingError, IOException { JsonNode node = readFile("old_style_doc.json"); var doc = FilingDocDocassembleJacksonDeserializer.fromNode( - node, varToPartyId, 0, filingCodes, true, parser, collector); + node, varToPartyId, 0, filingCodes, true, false, parser, collector); assertThat(doc).isPresent(); var attachments = doc.get().getFilingAttachments(); assertThat(attachments.length()).isEqualTo(1); @@ -128,7 +128,7 @@ public void oneAttachmentShouldLoadDocument() throws FilingError, IOException { JsonNode node = readFile("one_attachment.json"); var maybeDoc = FilingDocDocassembleJacksonDeserializer.fromNode( - node, varToPartyId, 0, filingCodes, true, parser, collector); + node, varToPartyId, 0, filingCodes, true, false, parser, collector); assertThat(maybeDoc).isPresent(); var doc = maybeDoc.get(); assertThat(doc.getFilingCode()).isEqualTo(filingCodes.get(0)); @@ -150,7 +150,7 @@ public void oneAttachmentAsSecondSequenceShouldLoadDocument() throws FilingError JsonNode node = readFile("one_attachment.json"); var doc = FilingDocDocassembleJacksonDeserializer.fromNode( - node, varToPartyId, 2, filingCodes, true, parser, collector); + node, varToPartyId, 2, filingCodes, true, false, parser, collector); assertThat(doc).isPresent(); assertThat(doc.get().sequenceNum()).isEqualTo(2); var attachments = doc.get().getFilingAttachments(); @@ -167,7 +167,7 @@ public void partyIdNotPresent() throws IOException, FilingError { JsonNode node = readFile("one_attachment.json"); var doc = FilingDocDocassembleJacksonDeserializer.fromNode( - node, Map.of(), 0, filingCodes, true, parser, collector); + node, Map.of(), 0, filingCodes, true, false, parser, collector); assertThat(doc).isPresent(); var parties = doc.get().getFilingPartyIds(); assertThat(parties.size()).isEqualTo(1); @@ -179,7 +179,7 @@ public void oneEnabledOneDisabledShouldLoadOneAttachment() throws FilingError, I JsonNode node = readFile("one_enabled_one_disabled.json"); var doc = FilingDocDocassembleJacksonDeserializer.fromNode( - node, varToPartyId, 0, filingCodes, true, parser, collector); + node, varToPartyId, 0, filingCodes, true, false, parser, collector); assertThat(doc).isPresent(); var attachments = doc.get().getFilingAttachments(); assertThat(attachments.length()).isEqualTo(1); @@ -192,7 +192,7 @@ public void noEnabledShouldFilingError() throws IOException, FilingError { JsonNode node = readFile("fail_no_enabled_attachment.json"); var doc = FilingDocDocassembleJacksonDeserializer.fromNode( - node, varToPartyId, 0, filingCodes, true, parser, collector); + node, varToPartyId, 0, filingCodes, true, false, parser, collector); assertThat(doc).as("Document shouldn't have parsed").isEmpty(); } @@ -201,7 +201,7 @@ public void shouldFallbackToParentDocIfNoEnabled() throws FilingError, IOExcepti JsonNode node = readFile("fallback_to_upper_doc.json"); var doc = FilingDocDocassembleJacksonDeserializer.fromNode( - node, varToPartyId, 0, filingCodes, true, parser, collector); + node, varToPartyId, 0, filingCodes, true, false, parser, collector); assertThat(doc).isPresent(); var attachments = doc.get().getFilingAttachments(); assertThat(attachments.length()).isEqualTo(1); @@ -215,7 +215,7 @@ public void noDocTypesShouldFail() throws IOException, FilingError { JsonNode node = readFile("fail_missing_doc_types.json"); try { FilingDocDocassembleJacksonDeserializer.fromNode( - node, varToPartyId, 0, filingCodes, true, parser, collector); + node, varToPartyId, 0, filingCodes, true, false, parser, collector); fail("Should have thrown a filing error, didn't"); } catch (FilingError err) { assertThat(err.getType()).isEqualTo(FilingError.Type.WrongValue); @@ -227,7 +227,7 @@ public void twoAttachmentsShouldLoadTwoAttachments() throws FilingError, IOExcep JsonNode node = readFile("two_attachments.json"); var doc = FilingDocDocassembleJacksonDeserializer.fromNode( - node, varToPartyId, 0, filingCodes, true, parser, collector); + node, varToPartyId, 0, filingCodes, true, false, parser, collector); assertThat(doc).isPresent(); var attachments = doc.get().getFilingAttachments(); assertThat(attachments.length()).isEqualTo(2); @@ -244,7 +244,7 @@ public void hasOptionalServicesShouldParse() throws FilingError, IOException { JsonNode node = readFile("has_optional_services.json"); var doc = FilingDocDocassembleJacksonDeserializer.fromNode( - node, varToPartyId, 0, filingCodes, true, parser, collector); + node, varToPartyId, 0, filingCodes, true, false, parser, collector); assertThat(doc).isPresent(); var optionalServices = doc.get().getOptionalServices(); assertThat(optionalServices).hasSize(1); @@ -257,7 +257,7 @@ public void filingActionShouldAlwaysParse() throws IOException, FilingError { JsonNode node = readTemplate("template_filing_action.json", emptyData); var doc = FilingDocDocassembleJacksonDeserializer.fromNode( - node, varToPartyId, 0, filingCodes, true, parser, collector); + node, varToPartyId, 0, filingCodes, true, false, parser, collector); assertThat(doc).isPresent(); assertThat(doc.get().getFilingAction()).isEmpty(); } @@ -271,7 +271,7 @@ public void filingActionShouldAlwaysParse() throws IOException, FilingError { JsonNode node = readTemplate("template_filing_action.json", data); var doc = FilingDocDocassembleJacksonDeserializer.fromNode( - node, varToPartyId, 0, filingCodes, false, parser, collector); + node, varToPartyId, 0, filingCodes, false, false, parser, collector); assertThat(doc).isPresent(); assertThat(doc.get().getFilingAction()).isPresent(); } @@ -282,7 +282,7 @@ public void testTylerMergeAttachments() throws IOException, FilingError { JsonNode node = readFile("tyler_merge_attachments.json"); var doc = FilingDocDocassembleJacksonDeserializer.fromNode( - node, varToPartyId, 0, filingCodes, true, parser, collector); + node, varToPartyId, 0, filingCodes, true, false, parser, collector); assertThat(doc).isPresent(); var attachments = doc.get().getFilingAttachments(); assertThat(attachments.length()).isEqualTo(1); @@ -309,7 +309,7 @@ record InputSaved(String dateInput, String savedDate) {} JsonNode node = readTemplate(INPUT_FILE, testData.dateInput); var doc = FilingDocDocassembleJacksonDeserializer.fromNode( - node, varToPartyId, 0, filingCodes, true, parser, collector); + node, varToPartyId, 0, filingCodes, true, false, parser, collector); assertThat(doc).isPresent(); assertThat(doc.get().getDueDate()).isPresent(); assertThat(doc.get().getDueDate().get()).isEqualTo(testData.savedDate); @@ -326,7 +326,7 @@ public void nonTextDueDateShouldBeEmpty() throws IOException, FilingError { JsonNode node = readTemplate(INPUT_FILE, emptyData); var doc = FilingDocDocassembleJacksonDeserializer.fromNode( - node, varToPartyId, 0, filingCodes, true, parser, collector); + node, varToPartyId, 0, filingCodes, true, false, parser, collector); assertThat(doc).isPresent(); assertThat(doc.get().getDueDate()).isEmpty(); } @@ -347,7 +347,7 @@ public void invalidDueDateShouldThrow() throws IOException, FilingError { assertThatThrownBy( () -> FilingDocDocassembleJacksonDeserializer.fromNode( - node, varToPartyId, 0, filingCodes, true, parser, collector)) + node, varToPartyId, 0, filingCodes, true, false, parser, collector)) .withFailMessage("Failed on %s", badData) .isInstanceOf(DateTimeParseException.class); } @@ -371,7 +371,7 @@ public void testMalformedDataUrlShouldThrow() throws IOException { assertThatThrownBy( () -> FilingDocDocassembleJacksonDeserializer.fromNode( - node, varToPartyId, 0, filingCodes, true, parser, collector)) + node, varToPartyId, 0, filingCodes, true, false, parser, collector)) .withFailMessage("Using %s", badData) .isInstanceOf(FilingError.class); } diff --git a/proxyserver/src/test/java/edu/suffolk/litlab/efsp/server/AddressTest.java b/proxyserver/src/test/java/edu/suffolk/litlab/efsp/server/AddressTest.java index f6cb3083b..67d5b38c3 100644 --- a/proxyserver/src/test/java/edu/suffolk/litlab/efsp/server/AddressTest.java +++ b/proxyserver/src/test/java/edu/suffolk/litlab/efsp/server/AddressTest.java @@ -28,21 +28,18 @@ public class AddressTest { Address addr; - EcfCourtSpecificSerializer serializer; + EcfCourtSpecificSerializer serializer = new EcfCourtSpecificSerializer(); @BeforeEach public void setUp() { addr = new Address("100 Circle Road", "Apt 2", "Plano", "TX", "75093", "US"); CodeDatabase cd = mock(CodeDatabase.class); when(cd.getStateCodes("adams", "US")).thenReturn(List.of("TX", "MA")); - CourtLocationInfo loc = new CourtLocationInfo("adams"); - serializer = new EcfCourtSpecificSerializer(cd, loc); } @Test public void addressShouldMakeXml() throws JAXBException, FilingError { - FailFastCollector collector = new FailFastCollector(); - JAXBElement addrElem = serializer.serializeNiemContactMeans(addr, collector); + JAXBElement addrElem = serializer.serializeNiemContactMeans(addr); // Should be able to grab the xml str without an exception Ecf4Helper.objectToXmlStr(addrElem.getValue(), AddressType.class); diff --git a/proxyserver/src/test/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCourtSpecificSerializerTest.java b/proxyserver/src/test/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCourtSpecificSerializerTest.java index 802af5d21..7de5448fd 100644 --- a/proxyserver/src/test/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCourtSpecificSerializerTest.java +++ b/proxyserver/src/test/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCourtSpecificSerializerTest.java @@ -50,6 +50,8 @@ public class EcfCourtSpecificSerializerTest { CodeDatabase cd; InfoCollector collector; private static final String caseType = "78334"; + EcfCourtSpecificSerializer courtSer = new EcfCourtSpecificSerializer(); + @BeforeEach public void setUp() { @@ -106,8 +108,6 @@ public void setUp() { @Test public void shouldBeEmptyPersonIfIsUser() throws FilingError, JAXBException { ContactInformation info = new ContactInformation("bob@example.com"); - CourtLocationInfo loc = new CourtLocationInfo("not_real"); - EcfCourtSpecificSerializer courtSer = new EcfCourtSpecificSerializer(cd, loc); PartyType partyType = PartyType.TestObj("1234", "Special", "not_real"); Person user = @@ -122,7 +122,7 @@ public void shouldBeEmptyPersonIfIsUser() throws FilingError, JAXBException { Optional.of("1234"), Optional.empty()); PartyInfo partyInfo = new PartyInfo(partyType, user.getPartyId(), user.isOrg()); - CaseParticipantType cpt = courtSer.serializeEcfCaseParticipant(user, partyInfo, collector); + CaseParticipantType cpt = courtSer.serializeEcfCaseParticipant(user, partyInfo); assertEquals("1234", cpt.getCaseParticipantRoleCode().getValue()); assertTrue( cpt.getEntityRepresentation().getValue() @@ -150,7 +150,7 @@ public void shouldBeEmptyPersonIfIsUser() throws FilingError, JAXBException { Optional.of("1234"), Optional.empty()); PartyInfo orgInfo = new PartyInfo(partyType, org.getPartyId(), org.isOrg()); - CaseParticipantType cptOrg = courtSer.serializeEcfCaseParticipant(org, orgInfo, collector); + CaseParticipantType cptOrg = courtSer.serializeEcfCaseParticipant(org, orgInfo); assertEquals("1234", cptOrg.getCaseParticipantRoleCode().getValue()); assertTrue(cptOrg.getEntityRepresentation().getValue() instanceof OrganizationType); OrganizationType orgPt = ((OrganizationType) cptOrg.getEntityRepresentation().getValue()); @@ -169,7 +169,7 @@ public void shouldBeEmptyPersonIfIsUser() throws FilingError, JAXBException { Optional.of("1234"), Optional.empty()); PartyInfo perInfo = new PartyInfo(partyType, per.getPartyId(), per.isOrg()); - CaseParticipantType cptPer = courtSer.serializeEcfCaseParticipant(per, perInfo, collector); + CaseParticipantType cptPer = courtSer.serializeEcfCaseParticipant(per, perInfo); System.out.println(Ecf4Helper.objectToXmlStr(cpt, CaseParticipantType.class)); assertEquals(cptPer.getCaseParticipantRoleCode().getValue(), "1234"); assertTrue(cptPer.getEntityRepresentation().getValue() instanceof PersonType); @@ -191,9 +191,7 @@ public void shouldAllowAtLeastOnePhone() throws FilingError { List.of("1234567890", "(123) 456-7890"), Optional.empty(), Optional.of("bob@example.com")); - CourtLocationInfo loc = new CourtLocationInfo("not_real"); - EcfCourtSpecificSerializer courtSer = new EcfCourtSpecificSerializer(cd, loc); - var contactInfoType = courtSer.serializeEcfContactInformation(info, collector); + var contactInfoType = courtSer.serializeEcfContactInformation(info); assertThat(contactInfoType.getContactMeans()).hasSize(3); assertThat(collector.getWrong()).hasSize(0); } @@ -228,14 +226,13 @@ public void shouldParseDoc() throws IOException, FilingError { var parser = new TylerCodesParser(cd, null, loc, true); var doc = FilingDocDocassembleJacksonDeserializer.fromNode( - node, varToPartyId, 2, List.of(filing), true, parser, collector); + node, varToPartyId, 2, List.of(filing), true, false, parser, collector); - EcfCourtSpecificSerializer cookSer = new EcfCourtSpecificSerializer(cd, loc); ObjectMapper mapper = new ObjectMapper(); JsonNode miscNode = mapper.createObjectNode(); var xmlDoc = - cookSer.filingDocToXml( - doc.get(), true, caseCategory, caseType, filing, miscNode, collector); + courtSer.filingDocToXml( + doc.get(), true, caseCategory, caseType, filing, miscNode); assertThat(xmlDoc.getValue().getDocumentSequenceID().getValue()).isEqualTo("2"); assertThat(xmlDoc.getValue().getDocumentDescriptionText().getValue()) .isEqualTo("The Motion to Stay Eviction for Bob Ma"); From a2327055f2b4f85391070d6990c99650a5b26506 Mon Sep 17 00:00:00 2001 From: Bryce Willey Date: Thu, 4 Jun 2026 16:05:04 -0400 Subject: [PATCH 4/4] Removing all MiscInfo, last of the CodesParser cleanups. --- .../suffolk/litlab/efsp/db/UserDatabase.java | 34 ++---- ...AddressDocassembleJacksonDeserializer.java | 4 +- ...lingDocDocassembleJacksonDeserializer.java | 16 ++- ...rmationDocassembleJacksonDeserializer.java | 42 ++++++- .../PersonDocassembleJacksonDeserializer.java | 3 +- .../litlab/efsp/model/EmailTemplates.java | 16 +++ .../litlab/efsp/model/FilingAttachment.java | 59 ++------- .../suffolk/litlab/efsp/model/FilingDoc.java | 2 +- .../litlab/efsp/model/FilingInformation.java | 56 +++++++-- .../litlab/efsp/server/ecf4/CodesParser.java | 9 +- .../efsp/server/ecf4/CoreMessageAndNames.java | 19 --- .../efsp/server/ecf4/EcfCaseTypeFactory.java | 112 ++++++------------ .../ecf4/EcfCourtSpecificSerializer.java | 78 ++++++------ .../server/ecf4/Ecfv5CaseTypeFactory.java | 13 +- .../server/ecf4/tyler/TylerCodesParser.java | 47 ++++++-- .../services/CourtSchedulingService.java | 6 +- .../server/services/FilingReviewService.java | 22 +--- .../efsp/server/setup/tyler/Ecf4Filer.java | 20 ++-- .../efsp/server/utils/OrgMessageSender.java | 10 +- .../litlab/efsp/db/UserDatabaseTest.java | 8 +- ...embleToFilingInformationConverterTest.java | 4 + ...DocDocassembleJacksonDeserializerTest.java | 62 ++++++---- ...sonDocassembleJacksonDeserializerTest.java | 6 + .../litlab/efsp/server/AddressTest.java | 2 - .../server/ecf4/EcfCaseTypeFactoryTest.java | 2 +- .../ecf4/EcfCourtSpecificSerializerTest.java | 7 +- .../housing_tro_2_plaintiff_business_def.json | 1 + 27 files changed, 336 insertions(+), 324 deletions(-) create mode 100644 proxyserver/src/main/java/edu/suffolk/litlab/efsp/model/EmailTemplates.java delete mode 100644 proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/CoreMessageAndNames.java diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/db/UserDatabase.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/db/UserDatabase.java index 7efd5341e..09aa8c1a6 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/db/UserDatabase.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/db/UserDatabase.java @@ -2,6 +2,7 @@ import edu.suffolk.litlab.efsp.db.model.Transaction; import edu.suffolk.litlab.efsp.ecfcodes.tyler.CodeTableConstants; +import edu.suffolk.litlab.efsp.model.EmailTemplates; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -84,12 +85,7 @@ public void addToTable( String caseType, String courtId, Timestamp submitted, - String acceptedTmpl, - String acceptedSubject, - String rejectedTmpl, - String rejectedSubject, - String neutralTmpl, - String neutralSubject, + EmailTemplates emailTemplates, String caseTitle, String envelopeId) throws SQLException { @@ -105,12 +101,7 @@ public void addToTable( caseType, courtId, submitted, - acceptedTmpl, - acceptedSubject, - rejectedTmpl, - rejectedSubject, - neutralTmpl, - neutralSubject, + emailTemplates, caseTitle, envelopeId); } @@ -128,12 +119,7 @@ public void addToTable( String caseType, String courtId, Timestamp submitted, - String acceptedTmpl, - String acceptedSubject, - String rejectedTmpl, - String rejectedSubject, - String neutralTmpl, - String neutralSubject, + EmailTemplates tmpls, String caseTitle, String envelopeId) throws SQLException { @@ -173,12 +159,12 @@ INSERT INTO submitted_filings ( insertSt.setString(8, caseType); insertSt.setString(9, courtId); insertSt.setTimestamp(10, submitted); - insertSt.setString(11, acceptedTmpl); - insertSt.setString(12, acceptedSubject); - insertSt.setString(13, rejectedTmpl); - insertSt.setString(14, rejectedSubject); - insertSt.setString(15, neutralTmpl); - insertSt.setString(16, neutralSubject); + insertSt.setString(11, tmpls.acceptedTemplate()); + insertSt.setString(12, tmpls.acceptedSubject()); + insertSt.setString(13, tmpls.rejectedTemplate()); + insertSt.setString(14, tmpls.rejectedSubject()); + insertSt.setString(15, tmpls.neutralTemplate()); + insertSt.setString(16, tmpls.neutralSubject()); insertSt.setString(17, caseTitle); insertSt.setString(18, envelopeId); insertSt.executeUpdate(); diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/AddressDocassembleJacksonDeserializer.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/AddressDocassembleJacksonDeserializer.java index f60ba6455..321d288a7 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/AddressDocassembleJacksonDeserializer.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/AddressDocassembleJacksonDeserializer.java @@ -22,8 +22,8 @@ protected AddressDocassembleJacksonDeserializer() {} * * @throws FilingError if @param node isn't a JSON object describing an address */ - public static Optional
fromNode(JsonNode node, CodesParser parser, InfoCollector collector) - throws FilingError { + public static Optional
fromNode( + JsonNode node, CodesParser parser, InfoCollector collector) throws FilingError { if (!node.isObject()) { FilingError err = FilingError.malformedInterview( diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/FilingDocDocassembleJacksonDeserializer.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/FilingDocDocassembleJacksonDeserializer.java index ada80985d..9c6ff7e52 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/FilingDocDocassembleJacksonDeserializer.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/FilingDocDocassembleJacksonDeserializer.java @@ -246,7 +246,7 @@ public static Optional fromNode( var descriptionFromSpec = parser.getDocumentDescription( - userDescription, goodAttachments.some().head().getFileName(), filingType); + userDescription, goodAttachments.some().head().fileName(), filingType); return Optional.of( new FilingDoc( filingType, @@ -345,6 +345,15 @@ private static Optional getAttachment( + dataUrl + ")")); } + + // TODO(brycew): depends on some DA code, should read in the PDF if possible here. Might be + // risky though. + // https://stackoverflow.com/questions/6026971/page-count-of-pdf-with-java + Optional pageCount = Optional.empty(); + if (node.has("page_count")) { + int count = node.get("page_count").asInt(1); + pageCount = Optional.of(count); + } // Difficult to hardcode more SSRF solutions, since deployment can be varied. Can't block local // network / // localhost, since things could be on the same server / network. TODO: inject an allow-list @@ -363,11 +372,12 @@ private static Optional getAttachment( return Optional.of( new FilingAttachment( + filingComponent, + documentDescription, fileName, (inStream != null) ? inStream.readAllBytes() : new byte[0], documentType, - filingComponent, - documentDescription)); + pageCount)); } catch (MalformedURLException ex) { FilingError err = serverError( diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/FilingInformationDocassembleJacksonDeserializer.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/FilingInformationDocassembleJacksonDeserializer.java index 78924f655..844d17985 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/FilingInformationDocassembleJacksonDeserializer.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/FilingInformationDocassembleJacksonDeserializer.java @@ -1,5 +1,7 @@ package edu.suffolk.litlab.efsp.docassemble; +import static edu.suffolk.litlab.efsp.utils.JsonHelpers.getNumberMember; +import static edu.suffolk.litlab.efsp.utils.JsonHelpers.getStringDefault; import static edu.suffolk.litlab.efsp.utils.JsonHelpers.getStringMember; import com.fasterxml.jackson.core.JsonParser; @@ -11,6 +13,7 @@ import com.hubspot.algebra.Result; import edu.suffolk.litlab.efsp.ecfcodes.tyler.FilingCode; import edu.suffolk.litlab.efsp.model.CaseServiceContact; +import edu.suffolk.litlab.efsp.model.EmailTemplates; import edu.suffolk.litlab.efsp.model.FilingDoc; import edu.suffolk.litlab.efsp.model.FilingInformation; import edu.suffolk.litlab.efsp.model.LowerCourtInfo; @@ -410,7 +413,44 @@ public FilingInformation fromNode(JsonNode node, InfoCollector collector) throws entities.setFilerType(filerTypeRes.expect("")); } - entities.setMiscInfo(node); + var maybeAmt = getNumberMember(node, "amount_in_controversy"); + var filingCodes = entities.getFilings().stream().map(d -> d.getFilingCode()).toList(); + var amtRes = parser.vetAmountInControversy(maybeAmt, filingCodes); + if (amtRes.isErr()) { + collector.error( + FilingError.malformedInterview("ad danum amount, Amount in controversy required")); + } else { + entities.setAmountInControversy(amtRes.expect("")); + } + + var maybeMax = getNumberMember(node, "max_fee_amount"); + entities.setMaxFeeAmount(parser.vetMaxAmount(maybeMax)); + + boolean contestedCase = false; + JsonNode jsonContested = node.get("is_contested_case"); + if (jsonContested != null && jsonContested.isBoolean()) { + contestedCase = jsonContested.asBoolean(); + } + entities.setIsContestedCase(contestedCase); + + boolean outOfState = false; + if (node.has("out_of_state")) { + outOfState = node.get("out_of_state").asBoolean(false); + } + entities.setOutOfState(outOfState); + + var emailTemplates = + new EmailTemplates( + getStringDefault(node, "email_confirmation_contents", ""), + getStringDefault(node, "email_confirmation_subject", ""), + getStringDefault(node, "acceptance_contents", ""), + getStringDefault(node, "acceptance_subject", ""), + getStringDefault(node, "rejected_contents", ""), + getStringDefault(node, "rejected_subject", ""), + getStringDefault(node, "neutral_contents", ""), + getStringDefault(node, "neutral_subject", "")); + + entities.setEmailTemplates(emailTemplates); return entities; } diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/PersonDocassembleJacksonDeserializer.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/PersonDocassembleJacksonDeserializer.java index 7e8bee989..2d07c0e95 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/PersonDocassembleJacksonDeserializer.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/docassemble/PersonDocassembleJacksonDeserializer.java @@ -64,7 +64,8 @@ public static Result fromNode( if (node.has("address") && node.get("address").isObject()) { collector.pushAttributeStack("address"); try { - addr = AddressDocassembleJacksonDeserializer.fromNode(node.get("address"), parser, collector); + addr = + AddressDocassembleJacksonDeserializer.fromNode(node.get("address"), parser, collector); collector.popAttributeStack(); } catch (FilingError err) { if (!err.getType().equals(FilingError.Type.MissingRequired)) { diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/model/EmailTemplates.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/model/EmailTemplates.java new file mode 100644 index 000000000..c6489a1b5 --- /dev/null +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/model/EmailTemplates.java @@ -0,0 +1,16 @@ +package edu.suffolk.litlab.efsp.model; + +public record EmailTemplates( + String confirmationTemplate, + String confirmationSubject, + String acceptedTemplate, + String acceptedSubject, + String rejectedTemplate, + String rejectedSubject, + String neutralTemplate, + String neutralSubject) { + + public EmailTemplates() { + this("", "", "", "", "", "", "", ""); + } +} diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/model/FilingAttachment.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/model/FilingAttachment.java index 49ffde3c1..2888dfc7b 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/model/FilingAttachment.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/model/FilingAttachment.java @@ -5,50 +5,15 @@ import java.util.Optional; /** An individual PDF, all a part of the same "document". The equivalent of an ALDocument. */ -public class FilingAttachment { - private final FilingComponent filingComponentCode; - // For the setBinaryDescriptionText - private final String documentDescription; - private final String fileName; - private final byte[] fileContents; - // This is, "determined via configuration within the EFM for each EFSP"? - // So, we can just say yes? - // Provides Document Type code / BinaryFormatStandardName - private final Optional documentTypeFormatStandardName; - - // page count? - - public FilingAttachment( - String fileName, - byte[] fileStream, - Optional documentTypeFormatStandardName, - FilingComponent filingComponentCode, - String documentDescription) { - this.filingComponentCode = filingComponentCode; - this.fileName = fileName; - this.documentTypeFormatStandardName = documentTypeFormatStandardName; - this.documentDescription = documentDescription; - this.fileContents = fileStream; - } - - public byte[] getFileContents() { - return fileContents; - } - - public String getFileName() { - return fileName; - } - - public FilingComponent getFilingComponent() { - return filingComponentCode; - } - - public Optional getDocumentTypeFormatStandardName() { - return documentTypeFormatStandardName; - } - - /** The description of this document. Goes into BinaryDescriptionText for Tyler. */ - public String getDocumentDescription() { - return documentDescription; - } -} +public record FilingAttachment( + FilingComponent filingComponentCode, + /** The description of this document. Goes into BinaryDescriptionText for Tyler. */ + String documentDescription, + String fileName, + byte[] fileContents, + // This is, "determined via configuration within the EFM for each EFSP"? + // So, we can just say yes? + // Provides Document Type code / BinaryFormatStandardName + Optional documentTypeFormatStandardName, + // If present, we've pre-counted the pages, if not, will have to count them later. + Optional pageCount) {} diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/model/FilingDoc.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/model/FilingDoc.java index 14a779e6b..24928f747 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/model/FilingDoc.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/model/FilingDoc.java @@ -106,7 +106,7 @@ public FilingDoc( public int allAttachmentsLength() { int length = 0; for (var attachment : filingAttachments) { - length += attachment.getFileContents().length; + length += attachment.fileContents().length; } return length; } diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/model/FilingInformation.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/model/FilingInformation.java index 9cada2eff..d8da93a9a 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/model/FilingInformation.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/model/FilingInformation.java @@ -1,10 +1,10 @@ package edu.suffolk.litlab.efsp.model; -import com.fasterxml.jackson.databind.JsonNode; import edu.suffolk.litlab.efsp.ecfcodes.tyler.CaseCategory; import edu.suffolk.litlab.efsp.ecfcodes.tyler.CaseType; import edu.suffolk.litlab.efsp.ecfcodes.tyler.FilerType; import edu.suffolk.litlab.efsp.ecfcodes.tyler.NameAndCode; +import java.math.BigDecimal; import java.time.LocalDate; import java.util.ArrayList; import java.util.List; @@ -72,7 +72,11 @@ public class FilingInformation { private Optional filerType; - private JsonNode miscInfo; + private Optional amountInControversy = Optional.empty(); + private Optional maxFeeAmount = Optional.empty(); + private boolean contestedCase = false; + private boolean outOfState = false; + private EmailTemplates emailTemplates = new EmailTemplates(); /** * Gets all of the peole who are listed by filer ids in the filing docs. This corresponds to the @@ -201,14 +205,30 @@ public Optional getFilerType() { return filerType; } - public JsonNode getMiscInfo() { - return miscInfo; - } - public Optional getLowerCourtInfo() { return lowerCourtInfo; } + public Optional getAmountInControversy() { + return amountInControversy; + } + + public Optional getMaxFeeAmount() { + return maxFeeAmount; + } + + public boolean isContestedCase() { + return contestedCase; + } + + public boolean getOutOfState() { + return outOfState; + } + + public EmailTemplates getEmailTemplates() { + return emailTemplates; + } + public void setCourtLocation(String courtLocationId) { this.courtLocationId = courtLocationId; } @@ -285,10 +305,6 @@ public void setFilerType(Optional filerType) { this.filerType = filerType; } - public void setMiscInfo(JsonNode node) { - this.miscInfo = node; - } - public void setLowerCourtInfo(LowerCourtInfo info) { this.lowerCourtInfo = Optional.ofNullable(info); } @@ -296,4 +312,24 @@ public void setLowerCourtInfo(LowerCourtInfo info) { public void setLowerCourtInfo(Optional info) { this.lowerCourtInfo = info; } + + public void setAmountInControversy(Optional amtInControversy) { + this.amountInControversy = amtInControversy; + } + + public void setMaxFeeAmount(Optional maxFeeAmount) { + this.maxFeeAmount = maxFeeAmount; + } + + public void setIsContestedCase(boolean isContestedCase) { + this.contestedCase = isContestedCase; + } + + public void setOutOfState(boolean outOfState) { + this.outOfState = outOfState; + } + + public void setEmailTemplates(EmailTemplates emailTemplates) { + this.emailTemplates = emailTemplates; + } } diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/CodesParser.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/CodesParser.java index 5817da2dc..efff4513a 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/CodesParser.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/CodesParser.java @@ -50,7 +50,7 @@ public sealed interface AttorneyError {} public record NoMultipleAttorneys() implements AttorneyError {} public record RequiredAttorneys() implements AttorneyError {} - public record RequiredFilingParty() {} + public record ThingRequired() {} public record DueDateRequired() {} @@ -96,7 +96,7 @@ public Result, CodeError> vetPartyTypes( CaseType type, boolean isFirstIndexedFiling); - public Result, RequiredFilingParty> vetFilingParties(List filingParties); + public Result, ThingRequired> vetFilingParties(List filingParties); public Result, CodeError> vetMotionCode( Optional motionCode, FilingCode filing); @@ -161,5 +161,10 @@ public Optional getDocumentDescription( public Result vetFilingDocSize(List docs); + public Result, ThingRequired> vetAmountInControversy( + Optional amt, List filings); + + public Optional vetMaxAmount(Optional maxAmount); + public boolean useFilingAssociations(); } diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/CoreMessageAndNames.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/CoreMessageAndNames.java deleted file mode 100644 index 43e318c7e..000000000 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/CoreMessageAndNames.java +++ /dev/null @@ -1,19 +0,0 @@ -package edu.suffolk.litlab.efsp.server.ecf4; - -import ecf4.latest.oasis.names.tc.legalxml_courtfiling.schema.xsd.corefilingmessage_4.CoreFilingMessageType; -import jakarta.annotation.Nullable; - -public class CoreMessageAndNames { - public final CoreFilingMessageType cfm; - public final @Nullable String existingCaseTitle; - public final String caseCategoryName; - public final String courtName; - - public CoreMessageAndNames( - CoreFilingMessageType cfm, String caseTitle, String caseCategoryName, String courtName) { - this.cfm = cfm; - this.existingCaseTitle = caseTitle; - this.caseCategoryName = caseCategoryName; - this.courtName = courtName; - } -} diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCaseTypeFactory.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCaseTypeFactory.java index 57bfd1349..4bce8b1e8 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCaseTypeFactory.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCaseTypeFactory.java @@ -1,6 +1,5 @@ package edu.suffolk.litlab.efsp.server.ecf4; -import com.fasterxml.jackson.databind.JsonNode; import ecf4.latest.gov.niem.niem.iso_4217._2.CurrencyCodeSimpleType; import ecf4.latest.gov.niem.niem.niem_core._2.AmountType; import ecf4.latest.gov.niem.niem.niem_core._2.CaseType; @@ -220,21 +219,21 @@ public List lateStageFilingAssociationAdd( for (Map.Entry filingObj : filingIdToObj.entrySet()) { ecf4.latest.gov.niem.niem.structures._2.ReferenceType filingRt = structOf.createReferenceType(); - filingRt.setRef(filingObj.getValue()); - var filingAssociation = filingAssociations.get(filingObj.getKey()); - for (PartyId partyId : filingAssociation) { - if (partyIdToRefObj.containsKey(partyId.getIdString())) { - ReferenceType partyRef = structObjFac.createReferenceType(); - partyRef.setRef(partyIdToRefObj.get(partyId.getIdString())); - FilingAssociationType association = tylerObjFac.createFilingAssociationType(); - association.setPartyReference(partyRef); - association.setFilingReference(filingRt); - toReturn.add(association); - } else { - log.warn("When adding filing associations, Party {} isn't an object?", partyId); - log.warn("Parties that do exist: {}", List.of(partyIdToRefObj.keySet().toArray())); - } + filingRt.setRef(filingObj.getValue()); + var filingAssociation = filingAssociations.get(filingObj.getKey()); + for (PartyId partyId : filingAssociation) { + if (partyIdToRefObj.containsKey(partyId.getIdString())) { + ReferenceType partyRef = structObjFac.createReferenceType(); + partyRef.setRef(partyIdToRefObj.get(partyId.getIdString())); + FilingAssociationType association = tylerObjFac.createFilingAssociationType(); + association.setPartyReference(partyRef); + association.setFilingReference(filingRt); + toReturn.add(association); + } else { + log.warn("When adding filing associations, Party {} isn't an object?", partyId); + log.warn("Parties that do exist: {}", List.of(partyIdToRefObj.keySet().toArray())); } + } } return toReturn; } @@ -249,7 +248,6 @@ public List lateStageFilingAssociationAdd( * @param isInitialFiling * @param isFirstIndexedFiling * @param queryType - * @param miscInfo * @param serializer * @param collector * @param serviceContactToXmlObjs @@ -270,7 +268,6 @@ public List lateStageFilingAssociationAdd( // HACK(brycew): hacky: needed because "fees" querys and "service" put the payment stuff // in the tyler Aug QueryType queryType, - JsonNode miscInfo, // TODO(brycew-later): if we get XML Answer files, this isn't generic EcfCourtSpecificSerializer serializer, InfoCollector collector, Map serviceContactToXmlObjs) @@ -285,40 +282,29 @@ public List lateStageFilingAssociationAdd( isInitialFiling, isFirstIndexedFiling, queryType, - miscInfo, serializer, - collector, serviceContactToXmlObjs); JAXBElement tylerAug = pair.getLeft(); JAXBElement myCase; if (comboCodes.cat().ecfcasetype.equals("CivilCase")) { - Optional amountInControversy = Optional.empty(); - boolean anyAmountInControversy = - comboCodes.filings().stream() - .anyMatch(f -> f.amountincontroversy.equalsIgnoreCase("Required")); - if (anyAmountInControversy) { - JsonNode jsonAmt = info.getMiscInfo().get("amount_in_controversy"); - if (jsonAmt != null && jsonAmt.isNumber()) { - amountInControversy = Optional.of(jsonAmt.decimalValue()); - } else { - collector.addRequired( - collector.requestVar("amount_in_controversy", "ad danum amount", "currency")); - } - } myCase = makeCivilCaseType( caseAug, tylerAug, info.getCaseDocketNumber(), info.getPreviousCaseId(), - amountInControversy); + info.getAmountInControversy()); } else if (comboCodes.cat().ecfcasetype.equals("DomesticCase")) { myCase = makeDomesticCaseType( - caseAug, tylerAug, info.getCaseDocketNumber(), info.getPreviousCaseId(), miscInfo); + caseAug, + tylerAug, + info.getCaseDocketNumber(), + info.getPreviousCaseId(), + info.isContestedCase()); } else if (comboCodes.cat().ecfcasetype.equals("AppellateCase")) { - myCase = makeAppellateCaseType(caseAug, tylerAug, info, miscInfo, collector); + myCase = makeAppellateCaseType(caseAug, tylerAug, info, collector); } else if (comboCodes.cat().ecfcasetype.equals("BankruptcyCase") || comboCodes.cat().ecfcasetype.equals("CitationCase") || comboCodes.cat().ecfcasetype.equals("JuvenileCase") @@ -384,9 +370,7 @@ public List lateStageFilingAssociationAdd( boolean isInitialFiling, boolean isFirstIndexedFiling, QueryType queryType, - JsonNode miscInfo, EcfCourtSpecificSerializer serializer, - InfoCollector collector, Map serviceContactXmlObjs) throws SQLException, FilingError { var ecfAug = tylerObjFac.createCaseAugmentationType(); @@ -406,7 +390,6 @@ public List lateStageFilingAssociationAdd( Set presentPartyTypes = new HashSet<>(); Map partyIdToRefObj = new HashMap<>(); - int i = 0; for (Person plaintiff : info.getNewPlaintiffs()) { var pInfo = comboCodes.partyInfo().get(plaintiff.getPartyId()); CaseParticipantType cp = serializer.serializeEcfCaseParticipant(plaintiff, pInfo); @@ -415,7 +398,6 @@ public List lateStageFilingAssociationAdd( presentPartyTypes.add(pInfo.type().code); } - i = 0; for (Person defendant : info.getNewDefendants()) { var pInfo = comboCodes.partyInfo().get(defendant.getPartyId()); CaseParticipantType cp = serializer.serializeEcfCaseParticipant(defendant, pInfo); @@ -459,12 +441,6 @@ public List lateStageFilingAssociationAdd( for (PartyId partyId : iterator) { log.info("Referenced PartyId ({})", partyId); if (partyId.isAlreadyInCase()) { - if (partyId.getIdentificationString().contains(" ")) { - FilingError err = - FilingError.serverError( - "Party ID " + partyId.getIdentificationString() + " should be a GUID but isn't"); - collector.error(err); - } CaseParticipantType cpt = ecfCommonObjFac.createCaseParticipantType(); IdentificationType id = of.createIdentificationType(); id.setIdentificationCategory( @@ -608,21 +584,15 @@ public List lateStageFilingAssociationAdd( PaymentFactory.makeProviderChargeType(info.getPaymentId(), this.jurisdiction)); } - if (miscInfo.has("max_fee_amount") && courtLocation.allowmaxfeeamount) { - AmountType amountType = new AmountType(); - amountType.setCurrencyCode(CurrencyCodeSimpleType.USD); - if (miscInfo.get("max_fee_amount").isNumber()) { - BigDecimal amnt = miscInfo.get("max_fee_amount").decimalValue(); - amountType.setValue(amnt); - ecfAug.setMaxFeeAmount(amountType); - } else { - FilingError err = - FilingError.malformedInterview("max_fee_amount needs to be a decimal (float) value"); - collector.error(err); - } - } + info.getMaxFeeAmount() + .ifPresent( + amnt -> { + AmountType amountType = new AmountType(); + amountType.setCurrencyCode(CurrencyCodeSimpleType.USD); + amountType.setValue(amnt); + ecfAug.setMaxFeeAmount(amountType); + }); - // log.info("Full ecfAug: {}", ecfAug); return Pair.of(tylerObjFac.createCaseAugmentation(ecfAug), partyIdToRefObj); } @@ -670,17 +640,17 @@ private static JAXBElement makeCivilCaseType( JAXBElement causeOfAction = ecfCommonObjFac.createCauseOfActionCode(new TextType()); c.getRest().add(causeOfAction); - if (amountInControversy.isPresent()) { - AmountType amount = new AmountType(); - amount.setValue(amountInControversy.get()); - amount.setCurrencyCode(CurrencyCodeSimpleType.USD); - c.getRest().add(ecfCivilObjFac.createAmountInControversy(amount)); - } + amountInControversy.ifPresent( + amt -> { + AmountType amount = new AmountType(); + amount.setValue(amt); + amount.setCurrencyCode(CurrencyCodeSimpleType.USD); + c.getRest().add(ecfCivilObjFac.createAmountInControversy(amount)); + }); c.getRest().add(ecfCivilObjFac.createClassActionIndicator(Ecf4Helper.convertBool(false))); c.getRest().add(ecfCivilObjFac.createJurisdictionalGroundsCode(Ecf4Helper.convertText(""))); c.getRest().add(ecfCivilObjFac.createJuryDemandIndicator(Ecf4Helper.convertBool(false))); - JAXBElement relief = ecfCivilObjFac.createReliefTypeCode(new TextType()); - c.getRest().add(relief); + c.getRest().add(ecfCivilObjFac.createReliefTypeCode(new TextType())); return ecfCivilObjFac.createCivilCase(c); } @@ -692,7 +662,6 @@ private static JAXBElement makeAppellateCaseType( JAXBElement caseAug, JAXBElement tylerAug, FilingInformation info, - JsonNode node, InfoCollector collector) throws FilingError { var ecfAppellateObjFac = @@ -770,7 +739,7 @@ private static JAXBElement makeDomesticCaseType( JAXBElement tylerAug, Optional caseDocketId, Optional caseTrackingId, - JsonNode node) { + boolean contestedCase) { var ecfDomesticObjFac = new ecf4.latest.oasis.names.tc.legalxml_courtfiling.schema.xsd.domesticcase_4 .ObjectFactory(); @@ -790,11 +759,6 @@ private static JAXBElement makeDomesticCaseType( d.getRest().add(tylerAug); JAXBElement causeOfAction = ecfCommonObjFac.createCauseOfActionCode(new TextType()); d.getRest().add(causeOfAction); - boolean contestedCase = false; - JsonNode jsonContested = node.get("is_contested_case"); - if (jsonContested != null && jsonContested.isBoolean()) { - contestedCase = jsonContested.asBoolean(); - } d.getRest() .add(ecfDomesticObjFac.createCaseContestedIndicator(Ecf4Helper.convertBool(contestedCase))); d.getRest().add(ecfDomesticObjFac.createDomesticCasePerson(new PersonType())); diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCourtSpecificSerializer.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCourtSpecificSerializer.java index e3d318d70..5fa3b8cb8 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCourtSpecificSerializer.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCourtSpecificSerializer.java @@ -1,6 +1,5 @@ package edu.suffolk.litlab.efsp.server.ecf4; -import com.fasterxml.jackson.databind.JsonNode; import ecf4.latest.gov.niem.niem.fbi._2.SEXCodeSimpleType; import ecf4.latest.gov.niem.niem.fbi._2.SEXCodeType; import ecf4.latest.gov.niem.niem.fips_10_4._2.CountryCodeType; @@ -108,8 +107,7 @@ public ComboCaseCodes serializeCaseCodes( * * @throws FilingError */ - public CaseParticipantType serializeEcfCaseParticipant( - Person per, PartyInfo info) throws FilingError { + public CaseParticipantType serializeEcfCaseParticipant(Person per, PartyInfo info) { final CaseParticipantType cpt = ecfOf.createCaseParticipantType(); ContactInformationType cit = serializeEcfContactInformation(per.getContactInfo()); if (per.isOrg()) { @@ -159,15 +157,17 @@ public CaseParticipantType serializeEcfCaseParticipant( pt.setPersonSex(niemObjFac.createPersonSexCode(sct)); }); - per.getLanguage().ifPresent(lang -> { - LanguageCodeType lct = iso639Fac.createLanguageCodeType(); - PersonLanguageType plt = niemObjFac.createPersonLanguageType(); - // TODO: need to test this with Tyler still: - // lct.setValue(lang); - plt.getLanguage(); - plt.getLanguage().add(niemObjFac.createLanguageCode(lct)); - pt.setPersonPrimaryLanguage(plt); - }); + per.getLanguage() + .ifPresent( + lang -> { + LanguageCodeType lct = iso639Fac.createLanguageCodeType(); + PersonLanguageType plt = niemObjFac.createPersonLanguageType(); + // TODO: need to test this with Tyler still: + // lct.setValue(lang); + plt.getLanguage(); + plt.getLanguage().add(niemObjFac.createLanguageCode(lct)); + pt.setPersonPrimaryLanguage(plt); + }); per.getBirthdate() .ifPresent( @@ -184,8 +184,7 @@ public CaseParticipantType serializeEcfCaseParticipant( return cpt; } - public ContactInformationType serializeEcfContactInformation( - ContactInformation contactInfo) throws FilingError { + public ContactInformationType serializeEcfContactInformation(ContactInformation contactInfo) { ContactInformationType cit = niemObjFac.createContactInformationType(); if (contactInfo.getAddress().isPresent()) { Address addr = contactInfo.getAddress().get(); @@ -213,7 +212,7 @@ public ContactInformationType serializeEcfContactInformation( } public static tyler.efm.latest.services.schema.common.AddressType serializeTylerAddress( - Address myAddr) throws FilingError { + Address myAddr) { var efmObjFac = new tyler.efm.latest.services.schema.common.ObjectFactory(); var addr = efmObjFac.createAddressType(); addr.setAddressLine1(myAddr.getStreet()); @@ -276,8 +275,7 @@ public JAXBElement filingDocToXml( boolean isInitialFiling, CaseCategory caseCategory, CaseType motionType, - FilingCode filing, - JsonNode miscInfo) + FilingCode filing) throws IOException { DocumentType docType = tylerObjFac.createDocumentType(); doc.descriptionFromSpec() @@ -339,10 +337,12 @@ public JAXBElement filingDocToXml( // * ReviewFiling API w/o service contacts: EFile // * ReviewFiling API w/ service contacts: EfileAndServe // * ServeFiling API: Serve - doc.getFilingAction().ifPresent(action -> { - FilingTypeType act = filingActionToXml(action); - docType.setFilingAction(act); - }); + doc.getFilingAction() + .ifPresent( + action -> { + FilingTypeType act = filingActionToXml(action); + docType.setFilingAction(act); + }); for (OptionalService serv : doc.getOptionalServices()) { DocumentOptionalServiceType xmlServ = tylerObjFac.createDocumentOptionalServiceType(); @@ -360,9 +360,7 @@ public JAXBElement filingDocToXml( DocumentRenditionMetadataType renditionMetadata = ecfOf.createDocumentRenditionMetadataType(); int idx = 0; for (var attachment : doc.getFilingAttachments()) { - renditionMetadata - .getDocumentAttachment() - .add(attachmentToXml(attachment, filing, miscInfo, idx)); + renditionMetadata.getDocumentAttachment().add(attachmentToXml(attachment, filing, idx)); idx += 1; } @@ -386,22 +384,18 @@ private FilingTypeType filingActionToXml(FilingAction action) { }; } - private DocumentAttachmentType attachmentToXml( - FilingAttachment fa, - FilingCode filing, - JsonNode miscInfo, - int seqNum) + private DocumentAttachmentType attachmentToXml(FilingAttachment fa, FilingCode filing, int seqNum) throws IOException { // TODO(brycew-later): what should this actually be? Very unclear DocumentAttachmentType attachment = ecfOf.createDocumentAttachmentType(); - attachment.setBinaryDescriptionText(Ecf4Helper.convertText(fa.getDocumentDescription())); - FilingComponent filt = fa.getFilingComponent(); + attachment.setBinaryDescriptionText(Ecf4Helper.convertText(fa.documentDescription())); + FilingComponent filt = fa.filingComponentCode(); attachment.setBinaryCategoryText(Ecf4Helper.convertText(filt.code)); // Literally should just be if it's confidential or not. (or "Hot fix" or public). // Search options in "documenttype" table with location - fa.getDocumentTypeFormatStandardName() + fa.documentTypeFormatStandardName() .ifPresent( code -> { attachment.setBinaryFormatStandardName(Ecf4Helper.convertText(code.code)); @@ -409,20 +403,18 @@ private DocumentAttachmentType attachmentToXml( // log.info("Filing code: {} {}: {}///////{}", filing.code, filing.name, docType, attachment); // TODO(#62): DO this: make the file downloadable from the Proxy server - attachment.setBinaryLocationURI(Ecf4Helper.convertUri(fa.getFileName())); + attachment.setBinaryLocationURI(Ecf4Helper.convertUri(fa.fileName())); JAXBElement n = - niemObjFac.createBinaryBase64Object(Ecf4Helper.convertBase64(fa.getFileContents())); + niemObjFac.createBinaryBase64Object(Ecf4Helper.convertBase64(fa.fileContents())); // System.err.println(Ecf4Helper.objectToXmlStrOrError(n.getValue(), Base64Binary.class)); attachment.setBinaryObject(n); - // TODO(brycew): depends on some DA code, should read in the PDF if possible here. Might be - // risky though. - // https://stackoverflow.com/questions/6026971/page-count-of-pdf-with-java - if (miscInfo.has("page_count")) { - int count = miscInfo.get("page_count").asInt(1); - NonNegativeDecimalType nndt = new NonNegativeDecimalType(); - nndt.setValue(new BigDecimal(count)); - attachment.setBinarySizeValue(tylerObjFac.createPageCount(nndt)); - } + fa.pageCount() + .ifPresent( + count -> { + NonNegativeDecimalType nndt = new NonNegativeDecimalType(); + nndt.setValue(new BigDecimal(count)); + attachment.setBinarySizeValue(tylerObjFac.createPageCount(nndt)); + }); attachment.setAttachmentSequenceID(Ecf4Helper.convertString(Integer.toString(seqNum))); return attachment; } diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/Ecfv5CaseTypeFactory.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/Ecfv5CaseTypeFactory.java index ff88504a2..1acc6fe76 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/Ecfv5CaseTypeFactory.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/Ecfv5CaseTypeFactory.java @@ -6,9 +6,7 @@ import static edu.suffolk.litlab.efsp.server.utils.Ecfv5XmlHelper.convertNormalized; import static edu.suffolk.litlab.efsp.server.utils.Ecfv5XmlHelper.convertString; import static edu.suffolk.litlab.efsp.server.utils.Ecfv5XmlHelper.convertText; -import static edu.suffolk.litlab.efsp.utils.JsonHelpers.isNull; -import com.fasterxml.jackson.databind.JsonNode; import com.hubspot.algebra.Result; import ecf4.latest.gov.niem.release.niem.domains.jxdm._6.CaseAugmentationType; import ecf4.latest.gov.niem.release.niem.domains.jxdm._6.CaseOfficialType; @@ -79,16 +77,7 @@ public Result createCaseType( EcfCourtSpecificSerializer serializer, InfoCollector collector, Optional> existingParties) { - Optional maybeAmt = Optional.empty(); - if (allCodes.filings().stream() - .anyMatch(f -> f.amountincontroversy.equalsIgnoreCase("Required"))) { - log.info(info.getMiscInfo().toPrettyString()); - JsonNode jsonAmt = info.getMiscInfo().get("amount_in_controversy"); - if (isNull(jsonAmt) || !jsonAmt.isNumber()) { - return Result.err(FilingError.malformedInterview("Amount in controversy required")); - } - maybeAmt = Optional.of(jsonAmt.decimalValue()); - } + Optional maybeAmt = info.getAmountInControversy(); CaseType ct = niemObjFac.createCaseType(); diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/tyler/TylerCodesParser.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/tyler/TylerCodesParser.java index 5c2ba0edb..c04f50a62 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/tyler/TylerCodesParser.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/ecf4/tyler/TylerCodesParser.java @@ -29,6 +29,7 @@ import edu.suffolk.litlab.efsp.server.ecf4.CodesParser; import edu.suffolk.litlab.efsp.server.ecf4.Ecf4Helper; import edu.suffolk.litlab.efsp.utils.FilingError; +import java.math.BigDecimal; import java.time.LocalDate; import java.util.ArrayList; import java.util.Collection; @@ -319,6 +320,12 @@ public Result, CodeError> vetPartyTypes( Map partyInfos = new HashMap<>(); for (Person party : existingParties) { var key = party.getPartyId(); + if (key.isAlreadyInCase() && key.getIdentificationString().contains(" ")) { + FilingError err = + FilingError.serverError( + "Party ID " + key.getIdentificationString() + " should be a GUID but isn't"); + return Result.err(new BadCode(err)); + } if (party.getRole().isEmpty()) { log.warn("Existing party {} doesn't have a role?", key); continue; @@ -399,10 +406,10 @@ public Result, CodeError> vetPartyTypes( return Result.ok(partyInfos); } - public Result, RequiredFilingParty> vetFilingParties(List filingParties) { + public Result, ThingRequired> vetFilingParties(List filingParties) { // TODO(brycew): needs to handle when we can avoid using filing party ids if (filingParties.isEmpty()) { - return Result.err(new RequiredFilingParty()); + return Result.err(new ThingRequired()); } return Result.ok(filingParties); } @@ -915,15 +922,18 @@ public Result, InvalidFilingAction> vetFilingAction( case FALSE -> false; case DEFAULT -> allDataFields.getFieldRow("FilingServiceCheckBoxInitial").isvisible; }; - boolean tryingToDoService = (act.equals(FilingAction.E_FILE_AND_SERVE) || act.equals(FilingAction.SERVE) || hasServiceContacts); - if (isInitialFiling - && !serviceOnInitial - && tryingToDoService) { + boolean tryingToDoService = + (act.equals(FilingAction.E_FILE_AND_SERVE) + || act.equals(FilingAction.SERVE) + || hasServiceContacts); + if (isInitialFiling && !serviceOnInitial && tryingToDoService) { return Result.err(new InvalidFilingAction("Cannot do service on initial filing")); } DataFieldRow checkBoxSub = allDataFields.getFieldRow("FilingServiceCheckBoxSubsequent"); if (!isInitialFiling && !checkBoxSub.isvisible && tryingToDoService) { - return Result.err(new InvalidFilingAction("Court " + this.court.name + " cannot do service on subsequent filings")); + return Result.err( + new InvalidFilingAction( + "Court " + this.court.name + " cannot do service on subsequent filings")); } } return Result.ok(filingAction); @@ -993,6 +1003,27 @@ public Result vetFilingDocSize(List docs) return Result.nullOk(); } + public Result, ThingRequired> vetAmountInControversy( + Optional amt, List filings) { + boolean anyAmountInControversy = + filings.stream().anyMatch(f -> f.amountincontroversy.equalsIgnoreCase("Required")); + if (anyAmountInControversy) { + if (amt.isPresent()) { + return Result.ok(amt); + } else { + return Result.err(new ThingRequired()); + } + } + return Result.ok(Optional.empty()); + } + + public Optional vetMaxAmount(Optional maxAmount) { + if (court.allowmaxfeeamount) { + return maxAmount; + } + return Optional.empty(); + } + /** * Get if we need to add an association between filings and case parties. Is simply a boolean * because there's no filing error that needs to be swallowed. @@ -1001,5 +1032,5 @@ public Result vetFilingDocSize(List docs) */ public boolean useFilingAssociations() { return allDataFields.getFieldRow("FilingEventCaseParties").isrequired; - } + } } diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/services/CourtSchedulingService.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/services/CourtSchedulingService.java index 8c9a55f0a..fcb4f8f69 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/services/CourtSchedulingService.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/services/CourtSchedulingService.java @@ -411,11 +411,7 @@ public Response getReturnDate( m.setCase(niemObjFac.createCase(ct)); m.setReturnDate(Ecfv5XmlHelper.convertDate(returnDate.get())); - boolean outOfState = false; - if (info.getMiscInfo().has("out_of_state")) { - outOfState = info.getMiscInfo().get("out_of_state").asBoolean(false); - } - m.setOutOfStateIndicator(Ecfv5XmlHelper.convertBool(outOfState)); + m.setOutOfStateIndicator(Ecfv5XmlHelper.convertBool(info.getOutOfState())); ReturnDateRequestType r = oasisWrapObjFac.createReturnDateRequestType(); r.setReturnDateMessage(m); log.info( diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/services/FilingReviewService.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/services/FilingReviewService.java index 5dd15cc70..a0b7a841b 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/services/FilingReviewService.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/services/FilingReviewService.java @@ -1,9 +1,7 @@ package edu.suffolk.litlab.efsp.server.services; import static edu.suffolk.litlab.efsp.server.utils.EndpointReflection.replacePathParam; -import static edu.suffolk.litlab.efsp.utils.JsonHelpers.getStringDefault; -import com.fasterxml.jackson.databind.JsonNode; import com.hubspot.algebra.NullValue; import com.hubspot.algebra.Result; import com.webcohesion.enunciate.metadata.rs.ResourceGroup; @@ -399,16 +397,6 @@ private Response fileOrServe( phoneNumber = Optional.of(user.getContactInfo().getPhoneNumbers().get(0)); } Timestamp ts = new Timestamp(System.currentTimeMillis()); - JsonNode miscInfo = info.getMiscInfo(); - - String confirmationTemplate = getStringDefault(miscInfo, "email_confirmation_contents", ""); - String confirmationSubject = getStringDefault(miscInfo, "email_confirmation_subject", ""); - String acceptedTemplate = getStringDefault(miscInfo, "acceptance_contents", ""); - String acceptedSubject = getStringDefault(miscInfo, "acceptance_subject", ""); - String rejectedTemplate = getStringDefault(miscInfo, "rejected_contents", ""); - String rejectedSubject = getStringDefault(miscInfo, "rejected_subject", ""); - String neutralTemplate = getStringDefault(miscInfo, "neutral_contents", ""); - String neutralSubject = getStringDefault(miscInfo, "neutral_subject", ""); try (UserDatabase ud = udSupplier.get()) { // TODO(brycew): this is going to send case type code (i.e. random numbers to the user. @@ -427,12 +415,7 @@ private Response fileOrServe( info.getCaseTypeCode().code, courtId, ts, - acceptedTemplate, - acceptedSubject, - rejectedTemplate, - rejectedSubject, - neutralTemplate, - neutralSubject, + info.getEmailTemplates(), filingResult.caseTitle, filingResult.envelopeId); @@ -451,8 +434,7 @@ private Response fileOrServe( } msgSender.sendConfirmation( user.getContactInfo().getEmail().orElse(""), - confirmationTemplate, - confirmationSubject, + info.getEmailTemplates(), atRest.get().serverId, user.getName().getFullName(), filingResult.courtName, diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/setup/tyler/Ecf4Filer.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/setup/tyler/Ecf4Filer.java index 4eaa07d15..d174df394 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/setup/tyler/Ecf4Filer.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/setup/tyler/Ecf4Filer.java @@ -60,7 +60,6 @@ import edu.suffolk.litlab.efsp.model.Person; import edu.suffolk.litlab.efsp.server.auth.TylerLogin; import edu.suffolk.litlab.efsp.server.ecf4.CodesParser; -import edu.suffolk.litlab.efsp.server.ecf4.CoreMessageAndNames; import edu.suffolk.litlab.efsp.server.ecf4.Ecf4Helper; import edu.suffolk.litlab.efsp.server.ecf4.EcfCaseTypeFactory; import edu.suffolk.litlab.efsp.server.ecf4.EcfCourtSpecificSerializer; @@ -79,6 +78,7 @@ import edu.suffolk.litlab.efsp.utils.FilingError; import edu.suffolk.litlab.efsp.utils.InfoCollector; import edu.suffolk.litlab.efsp.utils.InterviewVariable; +import jakarta.annotation.Nullable; import jakarta.ws.rs.core.Response; import jakarta.xml.bind.JAXBElement; import jakarta.xml.ws.BindingProvider; @@ -200,6 +200,12 @@ private Optional getParser(CodeDatabase cd, String courtId, String return TylerCodesParser.makeParser(cd, policy, courtId, isIndividual); } + public record CoreMessageAndNames( + CoreFilingMessageType cfm, + @Nullable String existingCaseTitle, + String caseCategoryName, + String courtName) {} + private CoreMessageAndNames prepareFiling( FilingInformation info, InfoCollector collector, @@ -388,7 +394,6 @@ private CoreMessageAndNames prepareFiling( isInitialFiling, isFirstIndexedFiling, queryType, - info.getMiscInfo(), serializer, collector, serviceContactXmlObjs); @@ -441,13 +446,7 @@ private CoreMessageAndNames prepareFiling( collector.pushAttributeStack("al_court_bundle[" + seqNum + "]"); JAXBElement result = serializer.filingDocToXml( - filingDoc, - isInitialFiling, - allCodes.cat(), - allCodes.type(), - fc, - info.getMiscInfo(), - collector); + filingDoc, isInitialFiling, allCodes.cat(), allCodes.type(), fc); collector.popAttributeStack(); filingIdToObj.put(filingDoc.getIdString(), result.getValue()); if (filingDoc.sequenceNum() == 0) { @@ -479,7 +478,8 @@ private CoreMessageAndNames prepareFiling( Collectors.toMap(f -> f.getIdString(), f -> f.getFilingPartyIds())); if (parser.useFilingAssociations()) { for (var association : - ecfCaseFactory.lateStageFilingAssociationAdd(filingIdToObj, filingAssociations, pair.getRight())) { + ecfCaseFactory.lateStageFilingAssociationAdd( + filingIdToObj, filingAssociations, pair.getRight())) { aug.getFilingAssociation().add(association); } } diff --git a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/utils/OrgMessageSender.java b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/utils/OrgMessageSender.java index 6dbd0cd18..359d2024c 100644 --- a/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/utils/OrgMessageSender.java +++ b/proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/utils/OrgMessageSender.java @@ -3,6 +3,7 @@ import edu.suffolk.litlab.efsp.db.MessageSettingsDatabase; import edu.suffolk.litlab.efsp.db.model.MessageInfo; import edu.suffolk.litlab.efsp.db.model.Transaction; +import edu.suffolk.litlab.efsp.model.EmailTemplates; import edu.suffolk.litlab.efsp.server.services.api.UpdateMessageStatus; import java.io.IOException; import java.sql.SQLException; @@ -188,8 +189,7 @@ public boolean sendMessage( public boolean sendConfirmation( String email, - String emailTemplate, - String emailSubject, + EmailTemplates tmpls, UUID serverId, String name, String courtName, @@ -198,11 +198,13 @@ public boolean sendConfirmation( String caseTitle, String envelopeId) { MessageInfo msgSettings = getSettings(serverId); - if (emailTemplate == null || emailTemplate.isBlank()) { + String emailTemplate = tmpls.confirmationTemplate(); + if (tmpls == null || emailTemplate == null || emailTemplate.isBlank()) { log.warn("given email template was blank ({}), using default", emailTemplate); emailTemplate = msgSettings.emailConfirmation; } - if (emailSubject == null || emailSubject.isBlank()) { + String emailSubject = tmpls.confirmationSubject(); + if (tmpls == null || emailSubject == null || emailSubject.isBlank()) { emailSubject = msgSettings.subjectLine; } String ids = transactionIds.stream().map(t -> t.toString()).collect(Collectors.joining(", ")); diff --git a/proxyserver/src/test/java/edu/suffolk/litlab/efsp/db/UserDatabaseTest.java b/proxyserver/src/test/java/edu/suffolk/litlab/efsp/db/UserDatabaseTest.java index 0dbb40f6a..c3052e7fe 100644 --- a/proxyserver/src/test/java/edu/suffolk/litlab/efsp/db/UserDatabaseTest.java +++ b/proxyserver/src/test/java/edu/suffolk/litlab/efsp/db/UserDatabaseTest.java @@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import edu.suffolk.litlab.efsp.db.model.Transaction; +import edu.suffolk.litlab.efsp.model.EmailTemplates; import java.sql.Connection; import java.sql.SQLException; import java.sql.Timestamp; @@ -68,12 +69,7 @@ public void testFromNothing() throws SQLException { "Motion to File", courtId, new Timestamp(System.currentTimeMillis()), - "", - "", - "", - "", - "", - "", + new EmailTemplates(), "my title", "2021ENVL"); diff --git a/proxyserver/src/test/java/edu/suffolk/litlab/efsp/docassemble/DocassembleToFilingInformationConverterTest.java b/proxyserver/src/test/java/edu/suffolk/litlab/efsp/docassemble/DocassembleToFilingInformationConverterTest.java index f1a1d7433..6d4992e71 100644 --- a/proxyserver/src/test/java/edu/suffolk/litlab/efsp/docassemble/DocassembleToFilingInformationConverterTest.java +++ b/proxyserver/src/test/java/edu/suffolk/litlab/efsp/docassemble/DocassembleToFilingInformationConverterTest.java @@ -9,6 +9,7 @@ import static org.mockito.Mockito.when; import com.hubspot.algebra.Result; +import edu.suffolk.litlab.efsp.Jurisdiction; import edu.suffolk.litlab.efsp.ecfcodes.tyler.CaseCategory; import edu.suffolk.litlab.efsp.ecfcodes.tyler.CaseType; import edu.suffolk.litlab.efsp.ecfcodes.tyler.CodeDatabase; @@ -23,6 +24,7 @@ import edu.suffolk.litlab.efsp.model.Person; import edu.suffolk.litlab.efsp.server.ecf4.CodesParser; import edu.suffolk.litlab.efsp.server.ecf4.tyler.TylerCodesParser; +import edu.suffolk.litlab.efsp.tyler.TylerDomain; import edu.suffolk.litlab.efsp.tyler.TylerEnv; import edu.suffolk.litlab.efsp.utils.FilingError; import edu.suffolk.litlab.efsp.utils.InterviewToFilingInformationConverter; @@ -70,6 +72,8 @@ public void setUp() throws IOException { when(cd.getAllowedFileTypes("01")).thenReturn(List.of(new FileType("PDF", "PDF", "pdf", "01"))); when(cd.getFilingComponents("01", exampleFilingType.code)) .thenReturn(List.of(new FilingComponent("332", null, null, false, false, 0, null, null))); + when(cd.getStateCodes("01", "US")).thenReturn(List.of("MA", "TX", "IL", "VT")); + when(cd.getDomain()).thenReturn(new TylerDomain(Jurisdiction.ILLINOIS, TylerEnv.STAGE)); when(cd.getDataFields("01")) .thenReturn( new DataFields( diff --git a/proxyserver/src/test/java/edu/suffolk/litlab/efsp/docassemble/FilingDocDocassembleJacksonDeserializerTest.java b/proxyserver/src/test/java/edu/suffolk/litlab/efsp/docassemble/FilingDocDocassembleJacksonDeserializerTest.java index e7d323104..1623c1314 100644 --- a/proxyserver/src/test/java/edu/suffolk/litlab/efsp/docassemble/FilingDocDocassembleJacksonDeserializerTest.java +++ b/proxyserver/src/test/java/edu/suffolk/litlab/efsp/docassemble/FilingDocDocassembleJacksonDeserializerTest.java @@ -81,8 +81,14 @@ public void setUp() { "DocumentType", new DataFieldRow("DocumentType", "Document Type", true, false, "adams"), "DueDateAvailableForFilers", + new DataFieldRow("DueDateAvailableForFilers", "Due Date", true, false, "adams"), + "FilingServiceCheckBoxSubsequent", new DataFieldRow( - "DueDateAvailableForFilers", "Due Date", true, false, "adams")))); + "FilingServiceCheckBoxSubsequent", + "service on subsequent", + true, + false, + "adams")))); var maxMeasure = new MeasureType(); var niem2Fac = new ecf4.latest.gov.niem.niem.niem_core._2.ObjectFactory(); @@ -100,12 +106,23 @@ public void testWeirdJsonShouldBeEmpty() ObjectMapper m = new ObjectMapper(); assertThatThrownBy( () -> - fromNode(m.readTree("null"), varToPartyId, 0, filingCodes, true, false, parser, collector)) + fromNode( + m.readTree("null"), + varToPartyId, + 0, + filingCodes, + true, + false, + parser, + collector)) .isInstanceOf(FilingError.class); assertThatThrownBy( - () -> fromNode(m.readTree("[]"), varToPartyId, 0, filingCodes, true, false, parser, collector)) + () -> + fromNode( + m.readTree("[]"), varToPartyId, 0, filingCodes, true, false, parser, collector)) .isInstanceOf(FilingError.class); - var doc = fromNode(m.readTree("{}"), varToPartyId, 0, filingCodes, true, false, parser, collector); + var doc = + fromNode(m.readTree("{}"), varToPartyId, 0, filingCodes, true, false, parser, collector); assertThat(doc).isEmpty(); } @@ -119,8 +136,8 @@ public void noAttachmentsShouldLoadDocument() throws FilingError, IOException { assertThat(doc).isPresent(); var attachments = doc.get().getFilingAttachments(); assertThat(attachments.length()).isEqualTo(1); - assertThat(attachments.head().getDocumentTypeFormatStandardName()).isPresent(); - assertThat(attachments.head().getDocumentTypeFormatStandardName().get().code).isEqualTo("6586"); + assertThat(attachments.head().documentTypeFormatStandardName()).isPresent(); + assertThat(attachments.head().documentTypeFormatStandardName().get().code).isEqualTo("6586"); } @Test @@ -135,8 +152,8 @@ public void oneAttachmentShouldLoadDocument() throws FilingError, IOException { assertThat(doc.sequenceNum()).isEqualTo(0); var attachments = doc.getFilingAttachments(); assertThat(attachments.length()).isEqualTo(1); - assertThat(attachments.head().getDocumentTypeFormatStandardName()).isPresent(); - assertThat(attachments.head().getDocumentTypeFormatStandardName().get().code).isEqualTo("6586"); + assertThat(attachments.head().documentTypeFormatStandardName()).isPresent(); + assertThat(attachments.head().documentTypeFormatStandardName().get().code).isEqualTo("6586"); var parties = doc.getFilingPartyIds(); assertThat(parties.size()).isEqualTo(1); assertThat(parties.get(0).isNewInCurrentFiling()).isTrue(); @@ -155,8 +172,8 @@ public void oneAttachmentAsSecondSequenceShouldLoadDocument() throws FilingError assertThat(doc.get().sequenceNum()).isEqualTo(2); var attachments = doc.get().getFilingAttachments(); assertThat(attachments.length()).isEqualTo(1); - assertThat(attachments.head().getDocumentTypeFormatStandardName()).isPresent(); - assertThat(attachments.head().getDocumentTypeFormatStandardName().get().code).isEqualTo("6586"); + assertThat(attachments.head().documentTypeFormatStandardName()).isPresent(); + assertThat(attachments.head().documentTypeFormatStandardName().get().code).isEqualTo("6586"); var parties = doc.get().getFilingPartyIds(); assertThat(parties.size()).isEqualTo(1); assertThat(parties.get(0).isNewInCurrentFiling()).isTrue(); @@ -183,8 +200,8 @@ public void oneEnabledOneDisabledShouldLoadOneAttachment() throws FilingError, I assertThat(doc).isPresent(); var attachments = doc.get().getFilingAttachments(); assertThat(attachments.length()).isEqualTo(1); - assertThat(attachments.head().getDocumentTypeFormatStandardName()).isPresent(); - assertThat(attachments.head().getDocumentTypeFormatStandardName().get().code).isEqualTo("6586"); + assertThat(attachments.head().documentTypeFormatStandardName()).isPresent(); + assertThat(attachments.head().documentTypeFormatStandardName().get().code).isEqualTo("6586"); } @Test @@ -205,9 +222,9 @@ public void shouldFallbackToParentDocIfNoEnabled() throws FilingError, IOExcepti assertThat(doc).isPresent(); var attachments = doc.get().getFilingAttachments(); assertThat(attachments.length()).isEqualTo(1); - assertThat(attachments.head().getDocumentTypeFormatStandardName()).isPresent(); - assertThat(attachments.head().getDocumentTypeFormatStandardName().get().code).isEqualTo("6586"); - assertThat(attachments.head().getFileName()).isEqualTo("motion_to_stay_eviction.pdf"); + assertThat(attachments.head().documentTypeFormatStandardName()).isPresent(); + assertThat(attachments.head().documentTypeFormatStandardName().get().code).isEqualTo("6586"); + assertThat(attachments.head().fileName()).isEqualTo("motion_to_stay_eviction.pdf"); } @Test @@ -231,10 +248,10 @@ public void twoAttachmentsShouldLoadTwoAttachments() throws FilingError, IOExcep assertThat(doc).isPresent(); var attachments = doc.get().getFilingAttachments(); assertThat(attachments.length()).isEqualTo(2); - assertThat(attachments.head().getDocumentTypeFormatStandardName()).isPresent(); - assertThat(attachments.head().getDocumentTypeFormatStandardName().get().code).isEqualTo("6586"); - assertThat(attachments.head().getFileName()).isEqualTo("motion-to-stay-eviction.pdf"); - assertThat(attachments.tail().head().getFileName()).isEqualTo("exhibits.pdf"); + assertThat(attachments.head().documentTypeFormatStandardName()).isPresent(); + assertThat(attachments.head().documentTypeFormatStandardName().get().code).isEqualTo("6586"); + assertThat(attachments.head().fileName()).isEqualTo("motion-to-stay-eviction.pdf"); + assertThat(attachments.tail().head().fileName()).isEqualTo("exhibits.pdf"); } // TODO: use readTemplate to test has_optional_services.json, with various numbers in place of @@ -286,10 +303,9 @@ public void testTylerMergeAttachments() throws IOException, FilingError { assertThat(doc).isPresent(); var attachments = doc.get().getFilingAttachments(); assertThat(attachments.length()).isEqualTo(1); - assertThat(attachments.head().getDocumentTypeFormatStandardName()).isPresent(); - assertThat(attachments.head().getDocumentTypeFormatStandardName().get().code).isEqualTo("7788"); - assertThat(attachments.head().getFileName()) - .isEqualTo("motion-to-stay-eviction-root-object.pdf"); + assertThat(attachments.head().documentTypeFormatStandardName()).isPresent(); + assertThat(attachments.head().documentTypeFormatStandardName().get().code).isEqualTo("7788"); + assertThat(attachments.head().fileName()).isEqualTo("motion-to-stay-eviction-root-object.pdf"); } @Nested diff --git a/proxyserver/src/test/java/edu/suffolk/litlab/efsp/docassemble/PersonDocassembleJacksonDeserializerTest.java b/proxyserver/src/test/java/edu/suffolk/litlab/efsp/docassemble/PersonDocassembleJacksonDeserializerTest.java index e6ee0b983..0cb993700 100644 --- a/proxyserver/src/test/java/edu/suffolk/litlab/efsp/docassemble/PersonDocassembleJacksonDeserializerTest.java +++ b/proxyserver/src/test/java/edu/suffolk/litlab/efsp/docassemble/PersonDocassembleJacksonDeserializerTest.java @@ -8,6 +8,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import edu.suffolk.litlab.efsp.Jurisdiction; import edu.suffolk.litlab.efsp.ecfcodes.tyler.CodeDatabase; import edu.suffolk.litlab.efsp.ecfcodes.tyler.CourtLocationInfo; import edu.suffolk.litlab.efsp.ecfcodes.tyler.DataFieldRow; @@ -15,12 +16,15 @@ import edu.suffolk.litlab.efsp.model.PartyId; import edu.suffolk.litlab.efsp.server.ecf4.CodesParser; import edu.suffolk.litlab.efsp.server.ecf4.tyler.TylerCodesParser; +import edu.suffolk.litlab.efsp.tyler.TylerDomain; +import edu.suffolk.litlab.efsp.tyler.TylerEnv; import edu.suffolk.litlab.efsp.utils.AllWrongCollector; import edu.suffolk.litlab.efsp.utils.FailFastCollector; import edu.suffolk.litlab.efsp.utils.FilingError; import edu.suffolk.litlab.efsp.utils.InfoCollector; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -35,7 +39,9 @@ public void setUp() { collector = new FailFastCollector(); var cd = mock(CodeDatabase.class); var allDataFields = mock(DataFields.class); + when(cd.getStateCodes("adams", "US")).thenReturn(List.of("MA", "TX", "IL", "VT")); when(cd.getDataFields("adams")).thenReturn(allDataFields); + when(cd.getDomain()).thenReturn(new TylerDomain(Jurisdiction.ILLINOIS, TylerEnv.STAGE)); when(allDataFields.getFieldRow("PartyFirstName")) .thenReturn(new DataFieldRow("PartyFirstName", "", true, true, "adams")); when(allDataFields.getFieldRow("PartyMiddleName")) diff --git a/proxyserver/src/test/java/edu/suffolk/litlab/efsp/server/AddressTest.java b/proxyserver/src/test/java/edu/suffolk/litlab/efsp/server/AddressTest.java index 67d5b38c3..c112c6197 100644 --- a/proxyserver/src/test/java/edu/suffolk/litlab/efsp/server/AddressTest.java +++ b/proxyserver/src/test/java/edu/suffolk/litlab/efsp/server/AddressTest.java @@ -13,11 +13,9 @@ import ecf4.latest.gov.niem.niem.niem_core._2.ProperNameTextType; import ecf4.latest.gov.niem.niem.niem_core._2.StructuredAddressType; import edu.suffolk.litlab.efsp.ecfcodes.tyler.CodeDatabase; -import edu.suffolk.litlab.efsp.ecfcodes.tyler.CourtLocationInfo; import edu.suffolk.litlab.efsp.model.Address; import edu.suffolk.litlab.efsp.server.ecf4.Ecf4Helper; import edu.suffolk.litlab.efsp.server.ecf4.EcfCourtSpecificSerializer; -import edu.suffolk.litlab.efsp.utils.FailFastCollector; import edu.suffolk.litlab.efsp.utils.FilingError; import jakarta.xml.bind.JAXBElement; import jakarta.xml.bind.JAXBException; diff --git a/proxyserver/src/test/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCaseTypeFactoryTest.java b/proxyserver/src/test/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCaseTypeFactoryTest.java index 18c61923d..2ac8279e3 100644 --- a/proxyserver/src/test/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCaseTypeFactoryTest.java +++ b/proxyserver/src/test/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCaseTypeFactoryTest.java @@ -134,7 +134,7 @@ public void shouldMatchExistingPartyPersonOrOrgXmlWrappers() throws Exception { EcfCourtSpecificSerializer courtSer = new EcfCourtSpecificSerializer(cd, loc); JAXBElement retVal = caseFactory.makeCaseTypeFromTylerCategory(loc, combos, info, false, false, - List.of("177239"), "filing", info.getMiscInfo(), courtSer, collector, Map.of()); + List.of("177239"), "filing", courtSer, collector, Map.of()); assertTrue(retVal.getValue() != null); */ } diff --git a/proxyserver/src/test/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCourtSpecificSerializerTest.java b/proxyserver/src/test/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCourtSpecificSerializerTest.java index 7de5448fd..f1a5062f9 100644 --- a/proxyserver/src/test/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCourtSpecificSerializerTest.java +++ b/proxyserver/src/test/java/edu/suffolk/litlab/efsp/server/ecf4/EcfCourtSpecificSerializerTest.java @@ -52,7 +52,6 @@ public class EcfCourtSpecificSerializerTest { private static final String caseType = "78334"; EcfCourtSpecificSerializer courtSer = new EcfCourtSpecificSerializer(); - @BeforeEach public void setUp() { cd = mock(CodeDatabase.class); @@ -228,11 +227,7 @@ public void shouldParseDoc() throws IOException, FilingError { FilingDocDocassembleJacksonDeserializer.fromNode( node, varToPartyId, 2, List.of(filing), true, false, parser, collector); - ObjectMapper mapper = new ObjectMapper(); - JsonNode miscNode = mapper.createObjectNode(); - var xmlDoc = - courtSer.filingDocToXml( - doc.get(), true, caseCategory, caseType, filing, miscNode); + var xmlDoc = courtSer.filingDocToXml(doc.get(), true, caseCategory, caseType, filing); assertThat(xmlDoc.getValue().getDocumentSequenceID().getValue()).isEqualTo("2"); assertThat(xmlDoc.getValue().getDocumentDescriptionText().getValue()) .isEqualTo("The Motion to Stay Eviction for Bob Ma"); diff --git a/proxyserver/src/test/resources/housing_tro_2_plaintiff_business_def.json b/proxyserver/src/test/resources/housing_tro_2_plaintiff_business_def.json index fb356b5d1..41aeee08a 100644 --- a/proxyserver/src/test/resources/housing_tro_2_plaintiff_business_def.json +++ b/proxyserver/src/test/resources/housing_tro_2_plaintiff_business_def.json @@ -172,6 +172,7 @@ "title": "Housing Temporary Restraining Order", "filename": "housing_tro", "filing_component": "332", + "filing_parties": ["users[0]"], "proxy_enabled": true } ],