diff --git a/CHANGELOG.md b/CHANGELOG.md
index 20cd3e4d..f1a40094 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ The format is based on [Keep a Changelog 1.0.0].
## Unreleased
- **Breaking:** `Client.get_pending_enrichment_for_version` now requires both a target enrichment version and a target parser version, and will not include documents which have not been parsed with the target version.
+- **Feature:** Add accessors for judgment jurisdiction
## [Release 20.0.0]
diff --git a/src/caselawclient/Client.py b/src/caselawclient/Client.py
index 007ac6ac..f77d206b 100644
--- a/src/caselawclient/Client.py
+++ b/src/caselawclient/Client.py
@@ -446,6 +446,24 @@ def set_document_court(
return self._send_to_eval(vars, "set_metadata_court.xqy")
+ def set_document_jurisdiction(
+ self, document_uri: DocumentURIString, content: str
+ ) -> requests.Response:
+ uri = self._format_uri_for_marklogic(document_uri)
+ vars: query_dicts.SetMetadataJurisdictionDict = {"uri": uri, "content": content}
+ return self._send_to_eval(vars, "set_metadata_jurisdiction.xqy")
+
+ def set_document_court_and_jurisdiction(
+ self, document_uri: DocumentURIString, content: str
+ ) -> requests.Response:
+ if "/" in content:
+ court, jurisdiction = re.split("\\s*/\\s*", content)
+ self.set_document_court(document_uri, court)
+ return self.set_document_jurisdiction(document_uri, jurisdiction)
+ else:
+ self.set_document_court(document_uri, content)
+ return self.set_document_jurisdiction(document_uri, "")
+
def set_judgment_this_uri(
self, judgment_uri: DocumentURIString
) -> requests.Response:
diff --git a/src/caselawclient/models/documents.py b/src/caselawclient/models/documents.py
index e88b0a85..4674aca1 100644
--- a/src/caselawclient/models/documents.py
+++ b/src/caselawclient/models/documents.py
@@ -198,6 +198,20 @@ def court(self) -> str:
},
)
+ @cached_property
+ def jurisdiction(self) -> str:
+ return self.xml.get_xpath_match_string(
+ "/akn:akomaNtoso/akn:*/akn:meta/akn:proprietary/uk:jurisdiction/text()",
+ {
+ "uk": "https://caselaw.nationalarchives.gov.uk/akn",
+ "akn": "http://docs.oasis-open.org/legaldocml/ns/akn/3.0",
+ },
+ )
+
+ @property
+ def court_and_jurisdiction(self) -> str:
+ return "/".join((self.court, self.jurisdiction))
+
@cached_property
def document_date_as_string(self) -> str:
return self.xml.get_xpath_match_string(
diff --git a/src/caselawclient/xquery/set_metadata_jurisdiction.xqy b/src/caselawclient/xquery/set_metadata_jurisdiction.xqy
new file mode 100644
index 00000000..3c9f8d21
--- /dev/null
+++ b/src/caselawclient/xquery/set_metadata_jurisdiction.xqy
@@ -0,0 +1,37 @@
+xquery version "1.0-ml";
+
+declare namespace akn = "http://docs.oasis-open.org/legaldocml/ns/akn/3.0";
+declare namespace uk = "https://caselaw.nationalarchives.gov.uk/akn";
+
+declare variable $uri as xs:string external;
+declare variable $content as xs:string external;
+declare variable $proprietary-node := document($uri)/akn:akomaNtoso/akn:*/akn:meta/akn:proprietary;
+declare variable $jurisdiction-node := $proprietary-node/uk:jurisdiction;
+
+declare function local:delete($uri)
+{
+ xdmp:node-delete($jurisdiction-node)
+};
+
+declare function local:edit($uri, $content)
+{
+ xdmp:node-replace(
+ $jurisdiction-node,
+ {$content}
+ )
+};
+
+declare function local:add($uri, $content)
+{
+ xdmp:node-insert-child(
+ $proprietary-node,
+ {$content}
+ )
+};
+
+if (fn:boolean(
+cts:search(doc($uri),
+cts:element-query(xs:QName('uk:jurisdiction'),cts:and-query(()))))) then
+ if ($content = "") then local:delete($uri) else local:edit($uri, $content)
+else
+ local:add($uri, $content)
diff --git a/src/caselawclient/xquery_type_dicts.py b/src/caselawclient/xquery_type_dicts.py
index 543347c2..13a7c6d8 100644
--- a/src/caselawclient/xquery_type_dicts.py
+++ b/src/caselawclient/xquery_type_dicts.py
@@ -144,6 +144,12 @@ class SetMetadataCourtDict(MarkLogicAPIDict):
uri: MarkLogicDocumentURIString
+# set_metadata_jurisdiction.xqy
+class SetMetadataJurisdictionDict(MarkLogicAPIDict):
+ content: str
+ uri: MarkLogicDocumentURIString
+
+
# set_metadata_name.xqy
class SetMetadataNameDict(MarkLogicAPIDict):
content: str
diff --git a/tests/client/test_get_set_metadata.py b/tests/client/test_get_set_metadata.py
index e421ae60..b78ddaf2 100644
--- a/tests/client/test_get_set_metadata.py
+++ b/tests/client/test_get_set_metadata.py
@@ -64,6 +64,70 @@ def test_set_document_court(self):
)
assert mock_eval.call_args.kwargs["vars"] == json.dumps(expected_vars)
+ def test_set_document_jurisdiction(self):
+ with patch.object(self.client, "eval") as mock_eval:
+ uri = "judgment/uri"
+ content = "new jurisdiction"
+ expected_vars = {"uri": "/judgment/uri.xml", "content": content}
+ self.client.set_document_jurisdiction(uri, content)
+
+ assert mock_eval.call_args.args[0] == (
+ os.path.join(ROOT_DIR, "xquery", "set_metadata_jurisdiction.xqy")
+ )
+ assert mock_eval.call_args.kwargs["vars"] == json.dumps(expected_vars)
+
+ def test_set_document_court_and_jurisdiction_when_both_passed(self):
+ # It splits the provided value on '/'
+ # and sets both court and jurisdiction
+ with patch.object(self.client, "eval") as mock_eval:
+ uri = "judgment/uri"
+ court_content = "court"
+ jurisdiction_content = "jurisdiction"
+ court_expected_vars = {"uri": "/judgment/uri.xml", "content": court_content}
+ jurisdiction_expected_vars = {
+ "uri": "/judgment/uri.xml",
+ "content": jurisdiction_content,
+ }
+ self.client.set_document_court_and_jurisdiction(uri, "court/jurisdiction")
+
+ assert mock_eval.call_args_list[0].args[0] == (
+ os.path.join(ROOT_DIR, "xquery", "set_metadata_court.xqy")
+ )
+ assert mock_eval.call_args_list[0].kwargs["vars"] == json.dumps(
+ court_expected_vars
+ )
+
+ assert mock_eval.call_args_list[1].args[0] == (
+ os.path.join(ROOT_DIR, "xquery", "set_metadata_jurisdiction.xqy")
+ )
+ assert mock_eval.call_args_list[1].kwargs["vars"] == json.dumps(
+ jurisdiction_expected_vars
+ )
+
+ def test_set_document_court_and_jurisdiction_when_just_court_passed(self):
+ # When no jurisdiction is included
+ # It sets the court and deletes the jurisdiction.
+ with patch.object(self.client, "eval") as mock_eval:
+ uri = "judgment/uri"
+ content = "court"
+ court_expected_vars = {"uri": "/judgment/uri.xml", "content": content}
+ jurisdiction_expected_vars = {"uri": "/judgment/uri.xml", "content": ""}
+ self.client.set_document_court_and_jurisdiction(uri, content)
+
+ assert mock_eval.call_args_list[0].args[0] == (
+ os.path.join(ROOT_DIR, "xquery", "set_metadata_court.xqy")
+ )
+ assert mock_eval.call_args_list[0].kwargs["vars"] == json.dumps(
+ court_expected_vars
+ )
+
+ assert mock_eval.call_args_list[1].args[0] == (
+ os.path.join(ROOT_DIR, "xquery", "set_metadata_jurisdiction.xqy")
+ )
+ assert mock_eval.call_args_list[1].kwargs["vars"] == json.dumps(
+ jurisdiction_expected_vars
+ )
+
def test_set_document_date(self):
with patch.object(self.client, "eval") as mock_eval:
uri = "judgment/uri"
diff --git a/tests/models/test_documents.py b/tests/models/test_documents.py
index 75322eee..03f7a54a 100644
--- a/tests/models/test_documents.py
+++ b/tests/models/test_documents.py
@@ -543,6 +543,67 @@ def test_court(self, opening_tag, closing_tag, mock_api_client):
"test/1234", show_unpublished=True
)
+ @pytest.mark.parametrize(
+ "opening_tag, closing_tag",
+ [
+ ("judgment", "judgment"),
+ ('doc name="pressSummary"', "doc"),
+ ],
+ )
+ def test_jurisdiction(self, opening_tag, closing_tag, mock_api_client):
+ mock_api_client.get_judgment_xml_bytestring.return_value = f"""
+
+ <{opening_tag}>
+
+
+ SoftwareTesting
+
+
+ {closing_tag}>
+
+ """.encode(
+ "utf-8"
+ )
+
+ document = Document("test/1234", mock_api_client)
+
+ assert document.jurisdiction == "SoftwareTesting"
+ mock_api_client.get_judgment_xml_bytestring.assert_called_once_with(
+ "test/1234", show_unpublished=True
+ )
+
+ @pytest.mark.parametrize(
+ "opening_tag, closing_tag",
+ [
+ ("judgment", "judgment"),
+ ('doc name="pressSummary"', "doc"),
+ ],
+ )
+ def test_court_and_jurisdiction(self, opening_tag, closing_tag, mock_api_client):
+ mock_api_client.get_judgment_xml_bytestring.return_value = f"""
+
+ <{opening_tag}>
+
+
+ UKFTT-CourtOfTesting
+ SoftwareTesting
+
+
+ {closing_tag}>
+
+ """.encode(
+ "utf-8"
+ )
+
+ document = Document("test/1234", mock_api_client)
+
+ assert document.court_and_jurisdiction == "UKFTT-CourtOfTesting/SoftwareTesting"
+ mock_api_client.get_judgment_xml_bytestring.assert_called_once_with(
+ "test/1234", show_unpublished=True
+ )
+
@pytest.mark.parametrize(
"opening_tag, closing_tag",
[