The Litigation Management Service manages the relation between entities in the Content Repository Service and legal cases.
If an entity is relevant for a legal case, it must not be deleted until the case is resolved. The Content Repository Service provides the litigation-hold feature that prohibits deletion of entities in litigation-hold. The Litigation Management Service extends this feature by managing collections of legal cases that are related to one or more entities. Each entity related to a collection of legal cases will be put under litigation-hold until all cases in the collection are resolved.
Installation
The Litigation Management Service is an extension of the Content Repository Service. It consists of a standalone
service application providing the API and type definitions used to store legal cases and case collections. These
type definitions must be present in the libs directory of the Content Repository Service. A containerized version
of the Content Repository Service, including the required type definitions, is available in an image called
litigation-management-service-content-repository-service.
Access rights
The Litigation Management Service uses impersonation to authenticate its requests to the Content Repository Service. The impersonation feature must be enabled in the Content Repository Service using the property:
commons:
security:
oauth2:
impersonation-enabled: true
To allow the Litigation Management Service to update the litigation-hold flags of entities, it needs the following authorities. These authorities must be assigned to the service account user of the OAuth2 client used by the service:
| Authority | Description |
|---|---|
|
Allows the service to set the litigation-hold flag. |
|
Allows the service to delete empty collections (which are retention-protected, too). |
|
Allows the service to impersonate the actual user. |
|
The authenticated request will inherit the service’s authorities in addition to the user’s own authorities. |
Data model
The following diagram shows a simplified view of the data model used by the Litigation Management Service.
Legal cases are assigned to case collections using an n:m relation. Each case collection keeps track of the current number of related legal cases and is never empty. When the collection is created, it must contain one or more legal cases. As soon as the last case is resolved or removed from the collection, the empty collection is deleted.
An entity can be assigned to one case collection. As long as this assignment exists, the litigation-hold flag of the entity will be true. When the collection is deleted because the last case was resolved, the litigation-hold flag is reset to null.
The referential integrity of the data is ensured by foreign keys.
Creating type definitions
The following paragraphs describe how to create type definitions with litigation management.
To be able to manage the relation of legal cases to entities in the Content Repository Service, the type definitions containing the entities must meet some requirements. The type definitions must:
-
Use retention protection
-
Contain an attribute named
case_collection_id -
Define the required foreign keys to the case collection type.
The easiest way to assure that the type definitions meet the expected requirements, is to use the
de.eitco.ecr.lms.types.EntityWithLitigationManagement interface as shown in the following example:
@Type(ObjectType.CONTAINER)
public interface TestRecord extends EntityWithLitigationManagement {
}
To use the interface, add the following dependency to your types module:
<dependency>
<groupId>de.eitco.ecr</groupId>
<artifactId>litigation-management-service-type-definitions</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
Using inheritance for litigation management
The Litigation Management Service can make use of the inheritance feature of the Content Repository Service. The following example shows a simple record scenario with records, registers and documents. When the record is assigned to a case collection, all registers and documents of the record will be put under litigation-hold automatically. Once all legal cases are resolved, the litigation hold will be removed from the entire record including its documents and registers. This is achieved by inheriting the case collection ID and the litigation hold flag from the record.
@Type(ObjectType.CONTAINER)
public interface TestRecord extends EntityWithLitigationManagement {
}
@Type(ObjectType.CONTAINER)
public interface TestRegister extends EntityWithLitigationManagement {
@ForeignKey(target = TestRecord.class, targetProperty = "id")
@CascadeDelete
ContainerId getRecordId();
void setRecordId(ContainerId recordId);
@SystemProperty(value = SystemPropertyName.RETENTION_DATE)
@InheritedProperty(foreignKeyPropertyName = "record_id", sourcePropertyName = "retention_date")
ZonedDateTime getRetentionDate();
void setRetentionDate(ZonedDateTime retentionDate);
@InheritedProperty(foreignKeyPropertyName = "record_id", sourcePropertyName = "case_collection_id")
@Override
ContainerId getCaseCollectionId();
@InheritedProperty(foreignKeyPropertyName = "record_id", sourcePropertyName = "litigation_hold")
@Override
boolean isLitigationHold();
}
@Type(ObjectType.DOCUMENT)
public interface TestDocument extends EntityWithLitigationManagement {
@ForeignKey(target = TestRegister.class, targetProperty = "id")
@CascadeDelete
ContainerId getRegisterId();
void setRegisterId(ContainerId registerId);
@SystemProperty(value = SystemPropertyName.RETENTION_DATE)
@InheritedProperty(foreignKeyPropertyName = "register_id", sourcePropertyName = "retention_date")
ZonedDateTime getRetentionDate();
void setRetentionDate(ZonedDateTime retentionDate);
@InheritedProperty(foreignKeyPropertyName = "register_id", sourcePropertyName = "case_collection_id")
@Override
ContainerId getCaseCollectionId();
@InheritedProperty(foreignKeyPropertyName = "register_id", sourcePropertyName = "litigation_hold")
@Override
boolean isLitigationHold();
}
Usage
The following examples show the basic usage of the service’s API.
Creating a legal case
Legal cases contain an optional external ID that can be used to link the case to another entity or system containing more information about the case and an optional description.
CaseManagementResourceClient client = caseManagementResourceClientFactory.newClient();
String caseDesc = "test-case-" + UUIDGenerator.randomUUID();
CaseCreationResult result = client.createCase(new CaseInput(caseDesc, externalId, null, false, null));
The CaseInput model class accepts five parameters:
-
The optional description
-
The optional external ID
-
The ID of the case collection to add the case to or null
-
A boolean indicating whether to automatically create a new case collection containing the new case
-
An optional description of the new case collection (only relevant if parameter 4 is true)
The returned result will contain the case’s ID and the collection’s ID if a new collection was created.
Adding and removing a case from a collection
Cases can be added to and removed from collections.
client.addCaseToCollection(caseId, collectionId);
client.removeCaseFromCollection(caseId, collectionId);
client.removeCaseFromAllCollections(caseId);
If a collection is empty after the case was removed, it will be deleted. The litigation-hold flag of entities assigned to this collection will be reset to null.
Assigning a collection to an entity
Assigning a collection (which will contain at least one legal case) to an entity causes the litigation-hold flag of the entity being set to true.
testDocumentId = documentClient.getIdentifier();
EntityId entityId = new EntityId(testDocumentId.value());
caseManagementResourceClientFactory.newClient().assignCollectionToEntity(testCollectionId, entityId);
Resolving a case
If a case is resolved, it is removed from all collections and deleted.
CaseManagementResourceClient caseManagementResourceClient = caseManagementResourceClientFactory.newClient();
caseManagementResourceClient.resolveCase(assignedCaseId);
If a collection is empty after the case was removed, it will be deleted. The litigation-hold flag of entities assigned to this collection will be reset to null.