Without true automation, guided interviews that produce legal forms are too difficult to justify the learning curve. As I have stated on this blog before, I am working on updating the Greater Boston Legal Services Eviction Defense System, a tool that helps lawyers and nonlawyer advocates complete legal forms for an eviction. The original system used some automation, but it was in some ways limited by its 25 years of development on older platforms. I had some ideas on how to reduce clicks and organize the content that come from my own experience interviewing tenants across the desk while I complete a paper answer and discovery form for them. Modern HotDocs has some new features I can take advantage of.
My goal is to link each of about 120 possible defenses and counterclaims with one of the 300 discovery requests that match. One possible way to do this would be to click through the multiple dialogs, look up the name of each variable, copy and paste it into the HotDocs computation editor, and then double-check my work to make sure I didn’t miss anything. Not my first choice! I did some learning today in both PowerShell and HotDocs, and I made good use of my PS-HotDocs scripts. Today’s post is a pretty technical deep-dive into using my scripts on a real HotDocs component file to make it easier to maintain.
PowerShell to the Rescue
The solution for me was to use PowerShell to export the lists of claims and defenses, using about 4 lines of code. I then copied the lists into a spreadsheet. My very capable law intern will help me link up the claims with a defense in a spreadsheet, and then I’ll use HotDocs again to generate the HotDocs computations that will represent the association between the two. If I ever add a new claim or defense, I can just add a new row to the spreadsheet and re-run my PowerShell script to get an updated computation.
Four lines of code doesn’t mean 4 minutes of work. It took longer than that to learn the right 4 lines, and I learned some new PowerShell syntax along the way. I’m always happier when I can share my work, so that I know doing it the “right” (automated) way was worthwhile. The details below may not be of interest to most of you, but I firmly believe that writing about my work can be useful documentation to my future self.
Exporting the list of claims and defenses
First, I loaded my get-dialogcontents script in the Interactive Script Editor. I like working in the ISE over the standard shell sometimes for the command history and easy ability to update and re-import a short script while I’m learning. For other uses, my standard editors are Notepad++ and VS Code. To save typing, I put in the path to my HotDocs component file as the default path.
I wanted to get the contents of two dialogs recursively: the dialog listing the claims and defenses, and the dialog listing the discovery. This is where the power of PowerShell’s object oriented nature and object pipeline truly save us time.
First, I retrieved the contents of the claims dialog and assigned it to the variable $claimdialogs:
PS U:\> $claimdialogs = get-dialogcontents -dialog "Defenses and counterclaims DI"
name
—-
Answer and discovery prescreen DI
Jursidictional defenses DI
Defenses nonpayment DI
Defenses fault DI
DEF Retaliation DI
AD Subsidized housing DI
Discrimination DI
AD Domestic violence DI
…
At this point I took a look at the XML file to see how it was structured.
As you can see, the contents of a dialog just are a list of names that each represent a HotDocs dialog component. They are not the dialogs themselves. So I’ll need to rerun the get-dialogcontents function on each item in the list.
$claims = foreach ($dialog in $claimdialogs) { get-dialogcontents -dialog $dialog.name | where {$_.name -like "* TF"} | sort}
Breaking this down: I created a new variable, $claims, which is assigned to the value of a PowerShell “foreach-object” loop. We’re looping through each child dialog, and getting the components in that dialog. They’ll all be put into a single PowerShell array. I’m filtering the list for components that end in ” TF” and sorting the list alphabetically.
Once again, in the XML file, the only information stored in a dialog is the component’s name. So I’ll need to retrieve the value of each component individually. I already wrote this function as an internal helper for my get-dialogsummary function:
function get-component($xml=$xml, $component=$component, $type="truefalse") {
$xml.componentlibrary.components.trueFalse | where {$_.name -like $component}
}
Note that it will only retrieve trueFalse variables, which works for my needs here. The final line I had to run is below:
$expandedclaims = foreach ($claim in $claims) { get-component -component $claim.name | select-object @{Name='Variable';Expression={$_.name}}, prompt, title -ExpandProperty resource}
Few things to note here. We use the same foreach syntax to go through each claim, and then we’ll get some additional properties for the claim. Select-object is a built-in PowerShell cmdlet that retrieves a specified list of variables. That odd @{Name=… syntax lets us do something that saves us a lot of time. Notice the expandProperty argument near the end of the line? We’re taking the “resource” property of the component, which is a separate XML element, and splatting it into our data table. Without this “expansion” we’d end up with an ugly XMLObject in that column of the spreadsheet. The problem is when we expand the property, we now have two items that have a “name” (at least as far as I can tell, the XML “resource” node has an implicit name, because I can’t see it in the file. That threw me off at first). That syntax lets us rename the first name column so that the expansion works. Below’s the full XML for a real trueFalse component in a HotDocs component file. As you can see, the resource has a plainText element that is a level below the other properties of the component. That’s because a HotDocs component can have multiple types of resources, not just plain text. It took me some time to figure out the correct syntax to avoid an error with the column names colliding.
Then I exported the expanded list to a CSV (spreadsheet) file, and imported it into Google Sheets.
$expandedclaims | Export-csv -NoTypeInformation 'claimsanddefenses.csv'
I did the same thing with the discovery requests. One nice shortcut: when it was time to sort the discovery, each discovery has the same number of letters that specify what type of discovery it is (INT, DRQ, or ADM for interrogatory, document request, or admission). I used a new-to-me trick to strip off the first three characters of the discovery name, so that when I sorted the discovery, they would be ordered by subject, not by discovery type (which is essentially irrelevant).
$subcontents | where {$_.name -like "* TF"} | sort -property @{Expression={$_.name.substring(3)} }
Here’s what it looks like in Google Sheets:
I created a separate tab in the spreadsheet that shows the link between the two claims, just as it would in a relational database. Each row represents a relationship. There can be multiple claims that each relate to the same discovery request, and multiple discovery requests that each relate to a single claim. The Priority column is just a concept right now. In Massachusetts summary process cases, both interrogatories and admissions are limited to 30. My concept is to assign a priority to each discovery request to help keep the number under 30. It’s just an untested idea now, so I’ll keep you updated on whether it’s realistic to implement.
When this important relational work is done, I will use another PowerShells script to turn these relationships into a HotDocs computation.
Lessons learned and next steps
I learned at least two new features of PowerShell today: sorting with a custom expression, and expanding a property with a renamed property to allow for duplicate property names. The goal of all of this work is to make it simple to update this in the future. Even if I would save a little time by hardcoding the computations, it would ultimately take me more time in the future to go back, read, and understand the right place to make a change if I add any new defenses, claims, or discovery requests. I already plan to add new claims in the next few months, so I’m hoping this up-front work will pay off soon.
I also learned that in the future, it may be worth learning how to build a GUI in PowerShell or .NET to make a more interactive version of these simple PowerShell scripts. I can see that having a lot of use in the future. The scripts in the their current form do take a bit of work to set up each time I want to use them, and a GUI that lets you visually browse the component file could save even more typing and switching back and forth between the script editor and HotDocs. The advantage of the command line is its flexibility, especially with the object pipeline, to build on my existing work to create new ways to automate.
0 Comments