Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ hs_err_pid*
/.gradle/
/target/*
.idea/*
.vscode/
.vscode/
.claude/
167 changes: 105 additions & 62 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,62 +1,105 @@
# Changelog
All notable changes to this project will be documented in this file.

## [1.99.1]

### Added

- Add support for form features:
- `AccessControl` model - Represents permissions for view/edit access to forms
- `Form` model - Complete form definition including field definitions
- `FormField` abstract model – for all form field types
- `FormState` enum - Enumeration for form publishing states (NEW, PUBLISHED, UNPUBLISHED, OLD)
- `ChoiceFormField` model - Checkbox field with multiple selection support
- `DateFormField` model - Date input field with min/max validation
- `NumberFormField` model - Numeric field with range and decimal places
- `RadioFormField` model - Radio button field for single selection
- `StringFormField` model - Short text input field (max 255 characters)
- `TextFormField` model - Long text field supporting HTML content
- `TimeFormField` model - Time input field storing millisecond values

### Changed

- Enhanced `FormInfo` model with additional properties:
- Added `formState` property for tracking publishing status
- Added `accessControl` property for permission management
- Added `tags` property for form categorization
- Added `iconId` property for form visual identification

## [1.99.0]
- switch from rspace-os-parent to rspace-parent as parent pom

## [1.98.1]

### Added
- Introduced support for document:
- `MoveRequest` model

### Changed
- Upgrade dependency: lombok 1.18.42.

## [1.98.0]

### Added
- Introduced support for Inventory features:
- `Barcode` model
- `TagInfo` model
- `RecordInfo` model
- `SharedWith` model
- Added the ability to represent sharing mode, barcodes, and tags for Inventory.

## [1.97.0]

- Support newly added audit (activity) actions: DUPLICATE and RENAME
- Update list of possible audit (activity) domains

## [1.95.0]
- Compile with java 17
- Switch to using parent pom from rspace-os-parent project
- Change <groupId> of produced artifact to from com.researchspace to com.github.rspace-os

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
# Changelog
All notable changes to this project will be documented in this file.

## [1.100.0]

### Breaking Changes

- **`AbstractExportPost`** — `scope()` renamed to `getScopeAsString()`, `format()` renamed to `getFormatAsString()`.
Update any callers of the old method names.

- **`ApiShareInfo.sharedItemName`** — field type corrected from `Long` to `String`.
Update any code that stores or passes `getSharedItemName()` as a `Long`.

- **`FieldPut`** — locally-shadowed `content` field removed; `FieldPut` now inherits `content` from `FieldPost`.
The two-arg constructor `FieldPut(String content, Long id)` is preserved so existing callers still compile.
However, `equals()`/`hashCode()` no longer compare two separate `content` fields, and any code that set
the shadowed field via reflection must switch to the inherited field.

- **`ActivitySearchResult`, `DocumentSearchResult`, `FileSearchResult`, `FormSearchResult`, `ShareSearchResult`** —
changed from `@Value` (immutable, all-args constructor) to `@Data @NoArgsConstructor` (mutable, no all-args constructor).
These are response POJOs and should not be constructed directly, but any code using the `@Value`-generated
constructor will no longer compile.

- **`User`** — replaced `@Value @NoArgsConstructor` with `@Data @NoArgsConstructor`.
Any code using positional construction (`new User(id, username, …)`) will no longer compile.

- **`ISO8601DateSerialiser`** — dates are now always serialised in UTC (previously used the JVM default timezone).
A `Date` value whose local-timezone calendar date differs from its UTC date will now serialise differently.
Ensure all `Date` values passed to `DateFormField` represent midnight UTC if exact date identity matters.

### Added

- `UserInfo` — full user information returned by the sysadmin user-listing endpoint.
- `UserSearchResult` — paginated wrapper for `UserInfo` lists.
- `GroupSearchResult` — paginated wrapper for `GroupInfo` lists returned by the sysadmin group-listing endpoint.
- `SharePermissionUpdate` — request body for `PUT /share` (update permission of an existing share).
- `DocumentShares` — response for `GET /share/document/{id}`; contains `directShares` and `notebookShares` as `List<DocumentShareEntry>`.
- `DocumentShareEntry` — a single entry within a `DocumentShares` response.

### Fixed

- `@JsonIgnoreProperties(ignoreUnknown = true)` added to all response POJOs. Prevents `UnrecognizedPropertyException`
when the server adds new fields in future releases.
- `ISO8601DateSerialiser` — replaced per-call `SimpleDateFormat` with a thread-safe static `DateTimeFormatter`.
- Removed stale swagger-codegen `DO NOT EDIT` headers from 12 source files.

## [1.99.1]

### Added

- Add support for form features:
- `AccessControl` model - Represents permissions for view/edit access to forms
- `Form` model - Complete form definition including field definitions
- `FormField` abstract model – for all form field types
- `FormState` enum - Enumeration for form publishing states (NEW, PUBLISHED, UNPUBLISHED, OLD)
- `ChoiceFormField` model - Checkbox field with multiple selection support
- `DateFormField` model - Date input field with min/max validation
- `NumberFormField` model - Numeric field with range and decimal places
- `RadioFormField` model - Radio button field for single selection
- `StringFormField` model - Short text input field (max 255 characters)
- `TextFormField` model - Long text field supporting HTML content
- `TimeFormField` model - Time input field storing millisecond values

### Changed

- Enhanced `FormInfo` model with additional properties:
- Added `formState` property for tracking publishing status
- Added `accessControl` property for permission management
- Added `tags` property for form categorization
- Added `iconId` property for form visual identification

## [1.99.0]
- switch from rspace-os-parent to rspace-parent as parent pom

## [1.98.1]

### Added
- Introduced support for a document:
- `MoveRequest` model

### Changed
- Upgrade dependency: lombok 1.18.42.

## [1.98.0]

### Added
- Introduced support for Inventory features:
- `Barcode` model
- `TagInfo` model
- `RecordInfo` model
- `SharedWith` model
- Added the ability to represent sharing mode, barcodes, and tags for Inventory.

## [1.97.0]

- Support newly added audit (activity) actions: DUPLICATE and RENAME
- Update list of possible audit (activity) domains

## [1.95.0]
- Compile with java 17
- Switch to using parent pom from rspace-os-parent project
- Change <groupId> of produced artifact to from com.researchspace to com.github.rspace-os

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
93 changes: 93 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# rspace-client-java-model

Pure POJO library. No HTTP. No Spring. No business logic.
Provides request and response model classes for the RSpace REST API, consumed by:
- `rspace-api-acceptance` — the API client and acceptance test repo
- `rspace-playwright-java` — the UI E2E test framework (via `ApiUtils`)

**Cross-repo rule:** Any change to this library that renames, removes, or changes the type of a field or method must also be checked (and fixed if broken) in both `rspace-api-acceptance` and `rspace-playwright-java` before the PR is merged.

---

## Module layout

```
src/main/java/
com.researchspace.api.clientmodel/ ← ELN request + response POJOs
com.researchspace.api.clientmodel.inventory/ ← Inventory base types only
com.researchspace.api.jackson/ ← Custom Jackson serialisers

src/test/java/
com.researchspace.api.clientmodel/ ← Unit tests: serialisation + builder contracts
```

### Inheritance hierarchy — never instantiate base classes directly

```
Linkable ← _links list + getLinkByType()
└── PaginatedResultList ← totalHits, pageNumber, pageSize
└── IdentifiableNameable ← id, globalId, name
└── DocumentInfo ← created, lastModified, tags, form, owner, parentFolderId
└── Document ← fields: List<Field>
└── FormInfo ← stableId, version, formState, accessControl, tags
└── Form ← fields: List<FormField>
└── GroupInfo ← type, sharedFolderId, members
└── ApiFile ← contentType, size, caption, created, version
└── RecordInfo (inventory) ← description, tags, sharingMode, barcodes
```

## Testing rules

All tests use **JUnit 5** (`org.junit.jupiter.api.Test`). Do not use JUnit 4.

### Two test patterns

**JSON fixture roundtrip** (via `AbstractModelTest`) — use for response POJOs:
```java
MyType result = readFileToClass(new File("src/test/resources/MyType.json"), MyType.class);
assertEquals("expectedValue", result.getSomeField());
```

**Serialisation roundtrip** (inline `ObjectMapper`) — use for request POJOs and serialisation contracts:
```java
ObjectMapper om = new ObjectMapper();
String json = om.writeValueAsString(myObject);
MyType deserialised = om.readValue(json, MyType.class);
assertEquals(expected, deserialised.getSomeField());
```

### Every new POJO needs at least one test

Minimum: deserialise from a representative JSON fixture and assert on the fields. If the class has builder methods (`addField()`, `appendContent()`), test those too.

### JSON fixtures

Location: `src/test/resources/`. Every `PaginatedResultList` fixture must include `totalHits`, `pageNumber`, and `pageSize`.

Existing fixtures: `Document.json`, `DocumentSearchResult.json`, `DocumentSearchQuery.json`, `ActivitySearchResult.json`, `FileSearchResult.json`, `File.json`, `Folder.json`, `FormSearchResult.json`, `Form.json`, `FolderTreeItemListing.json`, `GroupSearchResult.json`, `User.json`, `UserInfo.json`, `UserSearchResult.json`, `completedJob.json`.

---

## Adding a new class — checklist

1. Decide which category: response POJO, request POJO, base class, or inventory base
2. Choose Lombok annotations from the taxonomy table — do not invent new combinations
3. Add `@JsonIgnoreProperties(ignoreUnknown = true)` if it is a response POJO
4. Add a JSON fixture in `src/test/resources/` (or use a serialisation roundtrip test for request POJOs)
5. Write a unit test asserting on fields
6. Verify field names against the server source before adding fields not in the current Swagger: `https://github.com/rspace-os/rspace-web/tree/main/src/main/java/com/researchspace/api/v1`
7. Check `rspace-api-acceptance` and `rspace-playwright-java` for any callers affected by the change

---

## Constraints

- No Spring, RestTemplate, or HTTP dependencies in this module
- No concrete inventory response types (`RSSample`, `RSInvContainer`, etc.) — those belong in `rspace-api-acceptance`
- No `@Value` on classes that Jackson needs to deserialise
- No swagger-codegen `DO NOT EDIT` header comments — those files are manually maintained
- No `jakarta.validation` — use `javax.validation` only
- No new field on a response POJO without a test that verifies it deserialises correctly
- No new Lombok combinations not in the taxonomy table

---
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>

<artifactId>rspace-client-java-model</artifactId>
<version>1.99.1</version>
<version>1.100.0</version>
<name>rspace-client-java-model</name>
<parent>
<groupId>com.github.rspace-os</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.researchspace.api.clientmodel;

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
Expand All @@ -12,11 +13,13 @@ public class AbstractExportPost {
private ExportScope scope = ExportScope.USER;
private ExportFormat format = ExportFormat.HTML;

public String scope () {
@JsonIgnore
public String getScopeAsString() {
return scope.name().toLowerCase();
}

public String format () {

@JsonIgnore
public String getFormatAsString() {
return format.name().toLowerCase();
}

Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/researchspace/api/clientmodel/Activity.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.util.Date;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
Expand All @@ -12,6 +13,7 @@
*/
@Data
@EqualsAndHashCode(of={"timestamp", "username", "domain","action"})
@JsonIgnoreProperties(ignoreUnknown = true)
public class Activity {

private Date timestamp;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,20 @@
import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.Value;

/**
* ActivitySearchResults
*/
@Value
@EqualsAndHashCode(callSuper=true)
@ToString(callSuper=true)
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class ActivitySearchResult extends PaginatedResultList {

private List<Activity> activities = new ArrayList<>();
Expand Down
24 changes: 0 additions & 24 deletions src/main/java/com/researchspace/api/clientmodel/ApiFile.java
Original file line number Diff line number Diff line change
@@ -1,27 +1,3 @@
/**
* RSpace API
* Access your RSpace documents programmatically. All requests require authentication using an API key set as the value of the header `RSpace-API-Key`.
*
* OpenAPI spec version: 0.1
* Contact: support@researchspace.com
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.researchspace.api.clientmodel;

import java.util.Date;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@



import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
Expand All @@ -13,10 +14,14 @@
@Data
@EqualsAndHashCode(callSuper = false)
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class ApiShareInfo {

private Long id, sharedItemId,sharedItemName;
private String sharedTargetType, permission;

private Long id;
private Long sharedItemId;
private String sharedItemName;
private String sharedTargetType;
private String permission;


}
Loading
Loading