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
33 changes: 29 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,31 @@
# 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

Expand All @@ -17,10 +42,10 @@ All notable changes to this project will be documented in this file.

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

## [1.97.0]
Expand Down
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.0</version>
<version>1.99.1</version>
<name>rspace-client-java-model</name>
Comment on lines 6 to 8
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description mentions only the version bump, but this PR also introduces new Form/Field/AccessControl models and multiple new tests/resources. Please update the PR description to reflect the functional scope so reviewers/release notes are accurate.

Copilot uses AI. Check for mistakes.
<parent>
<groupId>com.github.rspace-os</groupId>
Expand Down
21 changes: 21 additions & 0 deletions src/main/java/com/researchspace/api/clientmodel/AccessControl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.researchspace.api.clientmodel;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
* Information about the permissions to view or edit a form.
*
* @author rspace
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AccessControl {
private String ownerPermissionType;
private String groupPermissionType;
private String worldPermissionType;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.researchspace.api.clientmodel;

import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

import javax.validation.constraints.Size;
import java.util.ArrayList;
import java.util.List;

/**
* A Choice form field defines a list of checkboxes, some of which can be selected by default.
* @author rspace
*/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@SuperBuilder
@JsonPropertyOrder(value = {"id", "globalId", "name", "type", "lastModified", "index",
"multipleChoice", "options", "defaultOptions"})
public class ChoiceFormField extends FormField {

private boolean multipleChoice;
@Size(min = 1, message = "Please provide at least one option")
@Builder.Default
private List<String> options = new ArrayList<>();
@Builder.Default
private List<String> defaultOptions = new ArrayList<>();

public ChoiceFormField(String name, boolean multipleChoice, List<String> options, List<String> defaultOptions) {
super();
setName(name);
setType("Choice");
this.multipleChoice = multipleChoice;
this.options = options != null ? options : new ArrayList<>();
this.defaultOptions = defaultOptions != null ? defaultOptions : new ArrayList<>();
}
}
42 changes: 42 additions & 0 deletions src/main/java/com/researchspace/api/clientmodel/DateFormField.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.researchspace.api.clientmodel;

import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.researchspace.api.jackson.ISO8601DateSerialiser;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

import java.util.Date;

/**
* A Date form field - defines a DateField.
* @author rspace
*/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@SuperBuilder
@JsonPropertyOrder(value = {"id", "globalId", "name", "type", "lastModified", "index",
"defaultValue", "min", "max"})
public class DateFormField extends FormField {


@JsonSerialize(using = ISO8601DateSerialiser.class)
private Date defaultValue;
@JsonSerialize(using = ISO8601DateSerialiser.class)
private Date min;

@JsonSerialize(using = ISO8601DateSerialiser.class)
private Date max;

public DateFormField(String name, Date defaultValue, Date min, Date max) {
super();
setName(name);
setType("Date");
this.defaultValue = defaultValue != null ? new Date(defaultValue.getTime()) : null;
this.min = min != null ? new Date(min.getTime()) : null;
this.max = max != null ? new Date(max.getTime()) : null;
}
}
42 changes: 42 additions & 0 deletions src/main/java/com/researchspace/api/clientmodel/Form.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.researchspace.api.clientmodel;

import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

import java.util.ArrayList;
import java.util.List;

/**
* A Form. A complete form definition including field definitions.
* @author rspace
*/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@SuperBuilder
@JsonPropertyOrder(value = {
"id", "globalId", "stableId", "version", "name", "tags",
"formState", "accessControl", "fields", "_links"
})
public class Form extends FormInfo {

@Builder.Default
private List<FormField> fields = new ArrayList<>();

/**
* Adds a field to this form
* @param field the FormField to add
* @return this Form for method chaining
*/
public Form addField(FormField field) {
if (this.fields == null) {
this.fields = new ArrayList<>();
}
this.fields.add(field);
return this;
}
}
49 changes: 49 additions & 0 deletions src/main/java/com/researchspace/api/clientmodel/FormField.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.researchspace.api.clientmodel;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

/**
* A FormField definition. This is an abstract type for all form field types.
* The properties listed here are common to all types.
*
* @author rspace
*/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
@JsonTypeInfo(
use = Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type",
visible = true
)
@JsonSubTypes({
@Type(value = ChoiceFormField.class, name = "Choice"),
@Type(value = TextFormField.class, name = "Text"),
@Type(value = StringFormField.class, name = "String"),
@Type(value = NumberFormField.class, name = "Number"),
@Type(value = RadioFormField.class, name = "Radio"),
@Type(value = DateFormField.class, name = "Date"),
@Type(value = TimeFormField.class, name = "Time"),
})
@JsonPropertyOrder(value = {"id", "globalId", "name", "type", "lastModified", "index"})
public abstract class FormField extends IdentifiableNameable {

@JsonProperty("lastModified")
private String lastModifiedMillis;
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lastModified is represented as an epoch-millis number in the test JSON (e.g., Form.json), but the model maps it to a String (lastModifiedMillis). This will coerce numbers to strings on deserialization and will serialize back as a JSON string, which is likely not what the API returns/expects. Consider changing this to a Long (or Date/Instant with appropriate Jackson config) and renaming the field to match its semantics (e.g., lastModified).

Suggested change
private String lastModifiedMillis;
private Long lastModifiedMillis;

Copilot uses AI. Check for mistakes.
private Integer index;
@JsonProperty("type")
private String type;
}
19 changes: 16 additions & 3 deletions src/main/java/com/researchspace/api/clientmodel/FormInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,32 @@

package com.researchspace.api.clientmodel;

import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

/**
* The Form on which the document structure is based.
*/
@Data
@EqualsAndHashCode(callSuper=true)
@NoArgsConstructor
public class FormInfo extends IdentifiableNameable {
@AllArgsConstructor
@SuperBuilder
@JsonPropertyOrder(value = {
"id", "globalId", "stableId", "version", "name", "tags",
"formState", "accessControl", "iconId", "_links"
})
public class FormInfo extends IdentifiableNameable {

private String stableId = null;
private Integer version = null;
private String stableId;
private Integer version;
private FormState formState;
private AccessControl accessControl;
private String tags;
private Long iconId;

}
14 changes: 14 additions & 0 deletions src/main/java/com/researchspace/api/clientmodel/FormState.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.researchspace.api.clientmodel;

/**
* Enumeration representing the publishing state of a Form.
*
* @author rspace
*/
public enum FormState {

NEW,
PUBLISHED,
UNPUBLISHED,
OLD
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.researchspace.api.clientmodel;

import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

import javax.validation.constraints.Min;

/**
* A Number form field - for numeric input with constraints.
* @author rspace
*/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@SuperBuilder
@JsonPropertyOrder(value = {"id", "globalId", "name", "type", "lastModified", "index",
"min", "max", "decimalPlaces", "defaultValue"})
public class NumberFormField extends FormField {
private Double min;
private Double max;
@Min(0)
private Byte decimalPlaces;
private Double defaultValue;

public NumberFormField(String name, Double defaultValue, Double min, Double max, Byte decimalPlaces) {
super();
setName(name);
setType("Number");
this.defaultValue = defaultValue;
this.min = min;
this.max = max;
this.decimalPlaces = decimalPlaces;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.researchspace.api.clientmodel;

import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

import javax.validation.constraints.Size;
import java.util.ArrayList;
import java.util.List;

/**
* A Radio form field defines a list of radio buttons, one of which can be selected by default.
* @author rspace
*/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@SuperBuilder
@JsonPropertyOrder(value = {"id", "globalId", "name", "type", "lastModified", "index",
"options", "defaultOption"})
public class RadioFormField extends FormField {

@Size(min = 1, message = "Please provide at least one option")
@Builder.Default
private List<String> options = new ArrayList<>();
private String defaultOption;

public RadioFormField(String name, List<String> options, String defaultOption) {
super();
setName(name);
setType("Radio");
this.options = options != null ? options : new ArrayList<>();
this.defaultOption = defaultOption;
}
}
Loading
Loading