Update dependencies, add character and scenario management features
- Upgrade Quarkus and OpenAPI generator versions in pom.xml. - Introduce CharacterService and ScenarioService for managing character and scenario templates. - Implement CharacterEntity and ScenarioEntity JPA entities with corresponding repositories. - Add RESTful APIs for listing and retrieving characters and scenarios. - Create JSON converter for persisting lists of strings in the database. - Update OpenAPI specification to include new endpoints for character and scenario management. - Add Liquibase migration scripts for character and scenario tables. - Configure application settings for Hibernate ORM and database generation.
This commit is contained in:
parent
cf93b35dd6
commit
3ce1215487
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"java.configuration.updateBuildConfiguration": "automatic"
|
||||||
|
}
|
||||||
20
pom.xml
20
pom.xml
@ -15,12 +15,14 @@
|
|||||||
<maven.surefire.plugin.version>3.2.5</maven.surefire.plugin.version>
|
<maven.surefire.plugin.version>3.2.5</maven.surefire.plugin.version>
|
||||||
<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
|
<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
|
||||||
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
|
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
|
||||||
<quarkus.platform.version>3.15.3</quarkus.platform.version>
|
<quarkus.platform.version>3.31.2</quarkus.platform.version>
|
||||||
<quarkus.plugin.version>${quarkus.platform.version}</quarkus.plugin.version>
|
<quarkus.plugin.version>${quarkus.platform.version}</quarkus.plugin.version>
|
||||||
|
<jackson.version>2.20.1</jackson.version>
|
||||||
|
<jackson.annotations.version>2.20</jackson.annotations.version>
|
||||||
<lombok.version>1.18.42</lombok.version>
|
<lombok.version>1.18.42</lombok.version>
|
||||||
<junit.jupiter.version>5.10.3</junit.jupiter.version>
|
<junit.jupiter.version>5.10.3</junit.jupiter.version>
|
||||||
<mockito.version>5.12.0</mockito.version>
|
<mockito.version>5.12.0</mockito.version>
|
||||||
<openapi.generator.version>7.11.0</openapi.generator.version>
|
<openapi.generator.version>7.13.0</openapi.generator.version>
|
||||||
<frontend.plugin.version>1.15.1</frontend.plugin.version>
|
<frontend.plugin.version>1.15.1</frontend.plugin.version>
|
||||||
<node.version>v22.13.1</node.version>
|
<node.version>v22.13.1</node.version>
|
||||||
<npm.version>10.9.2</npm.version>
|
<npm.version>10.9.2</npm.version>
|
||||||
@ -68,6 +70,10 @@
|
|||||||
<groupId>io.quarkus</groupId>
|
<groupId>io.quarkus</groupId>
|
||||||
<artifactId>quarkus-liquibase</artifactId>
|
<artifactId>quarkus-liquibase</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-hibernate-orm-panache</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.quarkus</groupId>
|
<groupId>io.quarkus</groupId>
|
||||||
<artifactId>quarkus-rest-client-config</artifactId>
|
<artifactId>quarkus-rest-client-config</artifactId>
|
||||||
@ -135,6 +141,7 @@
|
|||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<!-- On Java 25, skip to avoid VerifyError; run JAVA_HOME=/path/to/jdk21 mvn generate-sources first. -->
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.openapitools</groupId>
|
<groupId>org.openapitools</groupId>
|
||||||
<artifactId>openapi-generator-maven-plugin</artifactId>
|
<artifactId>openapi-generator-maven-plugin</artifactId>
|
||||||
@ -148,6 +155,7 @@
|
|||||||
<configuration>
|
<configuration>
|
||||||
<inputSpec>${project.basedir}/src/main/resources/openapi-roleplay-public-v1.yml</inputSpec>
|
<inputSpec>${project.basedir}/src/main/resources/openapi-roleplay-public-v1.yml</inputSpec>
|
||||||
<generatorName>jaxrs-spec</generatorName>
|
<generatorName>jaxrs-spec</generatorName>
|
||||||
|
<templateDirectory>${project.basedir}/src/main/resources/openapi-templates</templateDirectory>
|
||||||
<output>${project.build.directory}/generated-sources/openapi</output>
|
<output>${project.build.directory}/generated-sources/openapi</output>
|
||||||
<apiPackage>de.neitzel.roleplay.generated.api</apiPackage>
|
<apiPackage>de.neitzel.roleplay.generated.api</apiPackage>
|
||||||
<modelPackage>de.neitzel.roleplay.fascade.model</modelPackage>
|
<modelPackage>de.neitzel.roleplay.fascade.model</modelPackage>
|
||||||
@ -172,6 +180,7 @@
|
|||||||
<goal>generate</goal>
|
<goal>generate</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
|
<skip>${skip.openapi.generate}</skip>
|
||||||
<inputSpec>${project.basedir}/src/main/resources/openapi-roleplay-public-v1.yml</inputSpec>
|
<inputSpec>${project.basedir}/src/main/resources/openapi-roleplay-public-v1.yml</inputSpec>
|
||||||
<generatorName>typescript-fetch</generatorName>
|
<generatorName>typescript-fetch</generatorName>
|
||||||
<output>${project.basedir}/src/main/web/src/api/generated</output>
|
<output>${project.basedir}/src/main/web/src/api/generated</output>
|
||||||
@ -207,8 +216,11 @@
|
|||||||
<artifactId>maven-surefire-plugin</artifactId>
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
<version>${maven.surefire.plugin.version}</version>
|
<version>${maven.surefire.plugin.version}</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<useModulePath>false</useModulePath>
|
<argLine>@{argLine}</argLine>
|
||||||
<argLine>-Dnet.bytebuddy.experimental=true</argLine>
|
<systemPropertyVariables>
|
||||||
|
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
||||||
|
<maven.home>${maven.home}</maven.home>
|
||||||
|
</systemPropertyVariables>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
|||||||
@ -0,0 +1,69 @@
|
|||||||
|
package de.neitzel.roleplay.business;
|
||||||
|
|
||||||
|
import de.neitzel.roleplay.data.CharacterEntity;
|
||||||
|
import de.neitzel.roleplay.data.CharacterRepository;
|
||||||
|
import de.neitzel.roleplay.fascade.model.CharacterDefinition;
|
||||||
|
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Business service for stored character templates. Maps entities to API DTOs.
|
||||||
|
*/
|
||||||
|
@ApplicationScoped
|
||||||
|
public class CharacterService {
|
||||||
|
|
||||||
|
private final CharacterRepository characterRepository;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public CharacterService(final CharacterRepository characterRepository) {
|
||||||
|
this.characterRepository = characterRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all stored characters as API definitions.
|
||||||
|
*
|
||||||
|
* @return list of character definitions, ordered by name
|
||||||
|
*/
|
||||||
|
public List<CharacterDefinition> listCharacters() {
|
||||||
|
return characterRepository.listAll().stream()
|
||||||
|
.map(CharacterService::toCharacterDefinition)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a single character by id, if present.
|
||||||
|
*
|
||||||
|
* @param id the character UUID
|
||||||
|
* @return the character definition or empty
|
||||||
|
*/
|
||||||
|
public Optional<CharacterDefinition> getCharacter(final UUID id) {
|
||||||
|
CharacterEntity entity = characterRepository.findByIdOptional(id);
|
||||||
|
return entity != null ? Optional.of(toCharacterDefinition(entity)) : Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps a character entity to the API CharacterDefinition. Uses entity id as string for API id.
|
||||||
|
*/
|
||||||
|
public static CharacterDefinition toCharacterDefinition(final CharacterEntity entity) {
|
||||||
|
CharacterDefinition def = new CharacterDefinition(
|
||||||
|
entity.getId().toString(),
|
||||||
|
entity.getName(),
|
||||||
|
entity.getRole()
|
||||||
|
);
|
||||||
|
def.setBackstory(entity.getBackstory());
|
||||||
|
def.setSpeakingStyle(entity.getSpeakingStyle());
|
||||||
|
if (entity.getPersonalityTraits() != null && !entity.getPersonalityTraits().isEmpty()) {
|
||||||
|
def.setPersonalityTraits(entity.getPersonalityTraits());
|
||||||
|
}
|
||||||
|
if (entity.getGoals() != null && !entity.getGoals().isEmpty()) {
|
||||||
|
def.setGoals(entity.getGoals());
|
||||||
|
}
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -36,6 +36,7 @@ public class InMemorySessionService implements SessionService {
|
|||||||
|
|
||||||
private final OllamaClient ollamaClient;
|
private final OllamaClient ollamaClient;
|
||||||
private final com.fasterxml.jackson.databind.ObjectMapper objectMapper;
|
private final com.fasterxml.jackson.databind.ObjectMapper objectMapper;
|
||||||
|
private final ScenarioService scenarioService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In-memory store mapping session IDs to their current state.
|
* In-memory store mapping session IDs to their current state.
|
||||||
@ -47,12 +48,15 @@ public class InMemorySessionService implements SessionService {
|
|||||||
*
|
*
|
||||||
* @param ollamaClient client for Ollama narrative and state-update calls
|
* @param ollamaClient client for Ollama narrative and state-update calls
|
||||||
* @param objectMapper mapper to serialize turn context to JSON
|
* @param objectMapper mapper to serialize turn context to JSON
|
||||||
|
* @param scenarioService service to resolve scenario by id from the database
|
||||||
*/
|
*/
|
||||||
@Inject
|
@Inject
|
||||||
public InMemorySessionService(final OllamaClient ollamaClient,
|
public InMemorySessionService(final OllamaClient ollamaClient,
|
||||||
final com.fasterxml.jackson.databind.ObjectMapper objectMapper) {
|
final com.fasterxml.jackson.databind.ObjectMapper objectMapper,
|
||||||
|
final ScenarioService scenarioService) {
|
||||||
this.ollamaClient = ollamaClient;
|
this.ollamaClient = ollamaClient;
|
||||||
this.objectMapper = objectMapper;
|
this.objectMapper = objectMapper;
|
||||||
|
this.scenarioService = scenarioService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -77,11 +81,12 @@ public class InMemorySessionService implements SessionService {
|
|||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
if (request.getScenario() != null) {
|
ScenarioSetup scenario = resolveScenario(request);
|
||||||
session.setSituation(buildSituationFromScenario(request.getScenario()));
|
if (scenario != null) {
|
||||||
session.setCharacters(buildCharactersFromScenario(request.getScenario()));
|
session.setSituation(buildSituationFromScenario(scenario));
|
||||||
|
session.setCharacters(buildCharactersFromScenario(scenario));
|
||||||
try {
|
try {
|
||||||
String contextJson = objectMapper.writeValueAsString(OllamaContextBuilder.fromScenario(request.getScenario()));
|
String contextJson = objectMapper.writeValueAsString(OllamaContextBuilder.fromScenario(scenario));
|
||||||
String narrative = ollamaClient.generateNarrative(model, OllamaPrompts.INIT_NARRATIVE, contextJson);
|
String narrative = ollamaClient.generateNarrative(model, OllamaPrompts.INIT_NARRATIVE, contextJson);
|
||||||
String userContentForCall2 = contextJson + "\n\nNarrative that was just generated:\n" + narrative;
|
String userContentForCall2 = contextJson + "\n\nNarrative that was just generated:\n" + narrative;
|
||||||
StateUpdateResponse stateUpdate = ollamaClient.generateStateUpdate(model, OllamaPrompts.STATE_EXTRACTION, userContentForCall2);
|
StateUpdateResponse stateUpdate = ollamaClient.generateStateUpdate(model, OllamaPrompts.STATE_EXTRACTION, userContentForCall2);
|
||||||
@ -98,6 +103,19 @@ public class InMemorySessionService implements SessionService {
|
|||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the effective scenario: scenarioId from DB takes precedence over inline scenario.
|
||||||
|
*
|
||||||
|
* @param request the create session request
|
||||||
|
* @return the scenario to use, or null if none
|
||||||
|
*/
|
||||||
|
private ScenarioSetup resolveScenario(final CreateSessionRequest request) {
|
||||||
|
if (request.getScenarioId() != null) {
|
||||||
|
return scenarioService.getScenarioAsSetup(request.getScenarioId()).orElse(null);
|
||||||
|
}
|
||||||
|
return request.getScenario();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds initial situation state from the scenario setup.
|
* Builds initial situation state from the scenario setup.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -0,0 +1,83 @@
|
|||||||
|
package de.neitzel.roleplay.business;
|
||||||
|
|
||||||
|
import de.neitzel.roleplay.data.ScenarioCharacterEntity;
|
||||||
|
import de.neitzel.roleplay.data.ScenarioEntity;
|
||||||
|
import de.neitzel.roleplay.data.ScenarioRepository;
|
||||||
|
import de.neitzel.roleplay.fascade.model.CharacterDefinition;
|
||||||
|
import de.neitzel.roleplay.fascade.model.ScenarioSetup;
|
||||||
|
import de.neitzel.roleplay.fascade.model.ScenarioSummary;
|
||||||
|
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Business service for stored scenario templates. Maps entities to API DTOs.
|
||||||
|
*/
|
||||||
|
@ApplicationScoped
|
||||||
|
public class ScenarioService {
|
||||||
|
|
||||||
|
private final ScenarioRepository scenarioRepository;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public ScenarioService(final ScenarioRepository scenarioRepository) {
|
||||||
|
this.scenarioRepository = scenarioRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all stored scenarios as summaries.
|
||||||
|
*
|
||||||
|
* @return list of scenario summaries
|
||||||
|
*/
|
||||||
|
public List<ScenarioSummary> listScenarios() {
|
||||||
|
return scenarioRepository.listAll().stream()
|
||||||
|
.map(ScenarioService::toScenarioSummary)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the full scenario setup for the given id, if present.
|
||||||
|
*
|
||||||
|
* @param id the scenario UUID
|
||||||
|
* @return the scenario setup (setting, conflict, user character, AI characters) or empty
|
||||||
|
*/
|
||||||
|
public Optional<ScenarioSetup> getScenarioAsSetup(final UUID id) {
|
||||||
|
ScenarioEntity entity = scenarioRepository.findByIdWithCharacters(id);
|
||||||
|
return entity != null ? Optional.of(toScenarioSetup(entity)) : Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps a scenario entity to the list-summary DTO.
|
||||||
|
*/
|
||||||
|
public static ScenarioSummary toScenarioSummary(final ScenarioEntity entity) {
|
||||||
|
ScenarioSummary summary = new ScenarioSummary(entity.getId(), entity.getName());
|
||||||
|
summary.setSetting(entity.getSetting());
|
||||||
|
summary.setInitialConflict(entity.getInitialConflict());
|
||||||
|
return summary;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps a scenario entity (with characters loaded) to the full ScenarioSetup for session creation.
|
||||||
|
*/
|
||||||
|
public static ScenarioSetup toScenarioSetup(final ScenarioEntity entity) {
|
||||||
|
ScenarioSetup setup = new ScenarioSetup();
|
||||||
|
setup.setSetting(entity.getSetting());
|
||||||
|
setup.setInitialConflict(entity.getInitialConflict());
|
||||||
|
List<ScenarioCharacterEntity> links = entity.getScenarioCharacters();
|
||||||
|
if (links != null && !links.isEmpty()) {
|
||||||
|
for (ScenarioCharacterEntity link : links) {
|
||||||
|
CharacterDefinition def = CharacterService.toCharacterDefinition(link.getCharacter());
|
||||||
|
if (link.isUserCharacter()) {
|
||||||
|
setup.setUserCharacter(def);
|
||||||
|
} else {
|
||||||
|
setup.addAiCharactersItem(def);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return setup;
|
||||||
|
}
|
||||||
|
}
|
||||||
148
src/main/java/de/neitzel/roleplay/data/CharacterEntity.java
Normal file
148
src/main/java/de/neitzel/roleplay/data/CharacterEntity.java
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
package de.neitzel.roleplay.data;
|
||||||
|
|
||||||
|
import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
|
||||||
|
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Convert;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JPA entity for a reusable character definition stored in {@code rp_character}.
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name = "rp_character")
|
||||||
|
public class CharacterEntity extends PanacheEntityBase {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column(name = "id", length = 36, nullable = false, updatable = false)
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
@Column(name = "name", nullable = false, length = 255)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Column(name = "role", nullable = false, length = 255)
|
||||||
|
private String role;
|
||||||
|
|
||||||
|
@Column(name = "backstory", columnDefinition = "clob")
|
||||||
|
private String backstory;
|
||||||
|
|
||||||
|
@Convert(converter = JsonListStringConverter.class)
|
||||||
|
@Column(name = "personality_traits", columnDefinition = "clob")
|
||||||
|
private List<String> personalityTraits;
|
||||||
|
|
||||||
|
@Column(name = "speaking_style", length = 1000)
|
||||||
|
private String speakingStyle;
|
||||||
|
|
||||||
|
@Convert(converter = JsonListStringConverter.class)
|
||||||
|
@Column(name = "goals", columnDefinition = "clob")
|
||||||
|
private List<String> goals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor for JPA.
|
||||||
|
*/
|
||||||
|
public CharacterEntity() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the unique identifier of this character.
|
||||||
|
*/
|
||||||
|
public UUID getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the unique identifier of this character.
|
||||||
|
*/
|
||||||
|
public void setId(final UUID id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the display name of this character.
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the display name of this character.
|
||||||
|
*/
|
||||||
|
public void setName(final String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the narrative role of this character.
|
||||||
|
*/
|
||||||
|
public String getRole() {
|
||||||
|
return role;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the narrative role of this character.
|
||||||
|
*/
|
||||||
|
public void setRole(final String role) {
|
||||||
|
this.role = role;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the backstory text, or null if not set.
|
||||||
|
*/
|
||||||
|
public String getBackstory() {
|
||||||
|
return backstory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the backstory text.
|
||||||
|
*/
|
||||||
|
public void setBackstory(final String backstory) {
|
||||||
|
this.backstory = backstory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of personality trait strings; never null.
|
||||||
|
*/
|
||||||
|
public List<String> getPersonalityTraits() {
|
||||||
|
return personalityTraits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the list of personality trait strings.
|
||||||
|
*/
|
||||||
|
public void setPersonalityTraits(final List<String> personalityTraits) {
|
||||||
|
this.personalityTraits = personalityTraits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the speaking style description, or null if not set.
|
||||||
|
*/
|
||||||
|
public String getSpeakingStyle() {
|
||||||
|
return speakingStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the speaking style description.
|
||||||
|
*/
|
||||||
|
public void setSpeakingStyle(final String speakingStyle) {
|
||||||
|
this.speakingStyle = speakingStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of goal strings; never null.
|
||||||
|
*/
|
||||||
|
public List<String> getGoals() {
|
||||||
|
return goals;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the list of goal strings.
|
||||||
|
*/
|
||||||
|
public void setGoals(final List<String> goals) {
|
||||||
|
this.goals = goals;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
package de.neitzel.roleplay.data;
|
||||||
|
|
||||||
|
import io.quarkus.hibernate.orm.panache.PanacheRepository;
|
||||||
|
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Panache repository for {@link CharacterEntity}. Provides list-all and find-by-id access.
|
||||||
|
*/
|
||||||
|
@ApplicationScoped
|
||||||
|
public class CharacterRepository implements PanacheRepository<CharacterEntity> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all characters ordered by name.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<CharacterEntity> listAll() {
|
||||||
|
return list("ORDER BY name");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a character by its UUID.
|
||||||
|
*
|
||||||
|
* @param id the character id
|
||||||
|
* @return the entity or null if not found
|
||||||
|
*/
|
||||||
|
public CharacterEntity findByIdOptional(final UUID id) {
|
||||||
|
return find("id", id).firstResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
package de.neitzel.roleplay.data;
|
||||||
|
|
||||||
|
import jakarta.persistence.AttributeConverter;
|
||||||
|
import jakarta.persistence.Converter;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JPA converter that persists a {@link List} of {@link String} as JSON in a CLOB column.
|
||||||
|
*/
|
||||||
|
@Converter
|
||||||
|
public class JsonListStringConverter implements AttributeConverter<List<String>, String> {
|
||||||
|
|
||||||
|
private static final ObjectMapper MAPPER = new ObjectMapper();
|
||||||
|
private static final TypeReference<List<String>> LIST_TYPE = new TypeReference<>() {};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String convertToDatabaseColumn(final List<String> attribute) {
|
||||||
|
if (attribute == null || attribute.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return MAPPER.writeValueAsString(attribute);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new IllegalArgumentException("Failed to serialize string list to JSON", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> convertToEntityAttribute(final String dbData) {
|
||||||
|
if (dbData == null || dbData.isBlank()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return MAPPER.readValue(dbData, LIST_TYPE);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new IllegalArgumentException("Failed to deserialize JSON to string list", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,115 @@
|
|||||||
|
package de.neitzel.roleplay.data;
|
||||||
|
|
||||||
|
import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
|
||||||
|
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.FetchType;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.JoinColumn;
|
||||||
|
import jakarta.persistence.ManyToOne;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Join entity linking a scenario to a character with role (user vs AI) and ordering.
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name = "scenario_character")
|
||||||
|
public class ScenarioCharacterEntity extends PanacheEntityBase {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column(name = "id", length = 36, nullable = false, updatable = false)
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY, optional = false)
|
||||||
|
@JoinColumn(name = "scenario_id", nullable = false)
|
||||||
|
private ScenarioEntity scenario;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY, optional = false)
|
||||||
|
@JoinColumn(name = "character_id", nullable = false)
|
||||||
|
private CharacterEntity character;
|
||||||
|
|
||||||
|
@Column(name = "is_user_character", nullable = false)
|
||||||
|
private boolean userCharacter;
|
||||||
|
|
||||||
|
@Column(name = "position", nullable = false)
|
||||||
|
private int position;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor for JPA.
|
||||||
|
*/
|
||||||
|
public ScenarioCharacterEntity() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the unique identifier of this link.
|
||||||
|
*/
|
||||||
|
public UUID getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the unique identifier of this link.
|
||||||
|
*/
|
||||||
|
public void setId(final UUID id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the scenario this link belongs to.
|
||||||
|
*/
|
||||||
|
public ScenarioEntity getScenario() {
|
||||||
|
return scenario;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the scenario this link belongs to.
|
||||||
|
*/
|
||||||
|
public void setScenario(final ScenarioEntity scenario) {
|
||||||
|
this.scenario = scenario;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the character referenced by this link.
|
||||||
|
*/
|
||||||
|
public CharacterEntity getCharacter() {
|
||||||
|
return character;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the character referenced by this link.
|
||||||
|
*/
|
||||||
|
public void setCharacter(final CharacterEntity character) {
|
||||||
|
this.character = character;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this slot is the user-controlled character.
|
||||||
|
*/
|
||||||
|
public boolean isUserCharacter() {
|
||||||
|
return userCharacter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether this slot is the user-controlled character.
|
||||||
|
*/
|
||||||
|
public void setUserCharacter(final boolean userCharacter) {
|
||||||
|
this.userCharacter = userCharacter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the position for ordering (e.g. AI characters).
|
||||||
|
*/
|
||||||
|
public int getPosition() {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the position for ordering.
|
||||||
|
*/
|
||||||
|
public void setPosition(final int position) {
|
||||||
|
this.position = position;
|
||||||
|
}
|
||||||
|
}
|
||||||
116
src/main/java/de/neitzel/roleplay/data/ScenarioEntity.java
Normal file
116
src/main/java/de/neitzel/roleplay/data/ScenarioEntity.java
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
package de.neitzel.roleplay.data;
|
||||||
|
|
||||||
|
import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
|
||||||
|
|
||||||
|
import jakarta.persistence.CascadeType;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.OneToMany;
|
||||||
|
import jakarta.persistence.OrderBy;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JPA entity for a scenario template stored in {@code scenario}.
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name = "scenario")
|
||||||
|
public class ScenarioEntity extends PanacheEntityBase {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column(name = "id", length = 36, nullable = false, updatable = false)
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
@Column(name = "name", nullable = false, length = 255)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Column(name = "setting", columnDefinition = "clob")
|
||||||
|
private String setting;
|
||||||
|
|
||||||
|
@Column(name = "initial_conflict", columnDefinition = "clob")
|
||||||
|
private String initialConflict;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "scenario", cascade = CascadeType.ALL, orphanRemoval = true)
|
||||||
|
@OrderBy("isUserCharacter DESC, position ASC")
|
||||||
|
private List<ScenarioCharacterEntity> scenarioCharacters = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor for JPA.
|
||||||
|
*/
|
||||||
|
public ScenarioEntity() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the unique identifier of this scenario.
|
||||||
|
*/
|
||||||
|
public UUID getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the unique identifier of this scenario.
|
||||||
|
*/
|
||||||
|
public void setId(final UUID id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the human-readable name of this scenario.
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the human-readable name of this scenario.
|
||||||
|
*/
|
||||||
|
public void setName(final String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the setting description (place, time, atmosphere), or null if not set.
|
||||||
|
*/
|
||||||
|
public String getSetting() {
|
||||||
|
return setting;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the setting description.
|
||||||
|
*/
|
||||||
|
public void setSetting(final String setting) {
|
||||||
|
this.setting = setting;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the initial conflict text, or null if not set.
|
||||||
|
*/
|
||||||
|
public String getInitialConflict() {
|
||||||
|
return initialConflict;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the initial conflict text.
|
||||||
|
*/
|
||||||
|
public void setInitialConflict(final String initialConflict) {
|
||||||
|
this.initialConflict = initialConflict;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of scenario–character links (user character first, then AI by position).
|
||||||
|
*/
|
||||||
|
public List<ScenarioCharacterEntity> getScenarioCharacters() {
|
||||||
|
return scenarioCharacters;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the list of scenario–character links.
|
||||||
|
*/
|
||||||
|
public void setScenarioCharacters(final List<ScenarioCharacterEntity> scenarioCharacters) {
|
||||||
|
this.scenarioCharacters = scenarioCharacters;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
package de.neitzel.roleplay.data;
|
||||||
|
|
||||||
|
import io.quarkus.hibernate.orm.panache.PanacheRepository;
|
||||||
|
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Panache repository for {@link ScenarioEntity}. Provides list-all and find-by-id with characters loaded.
|
||||||
|
*/
|
||||||
|
@ApplicationScoped
|
||||||
|
public class ScenarioRepository implements PanacheRepository<ScenarioEntity> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a scenario by its UUID and loads its scenario-character links and linked characters.
|
||||||
|
*
|
||||||
|
* @param id the scenario id
|
||||||
|
* @return the entity or null if not found
|
||||||
|
*/
|
||||||
|
public ScenarioEntity findByIdWithCharacters(final UUID id) {
|
||||||
|
ScenarioEntity scenario = find("id", id).firstResult();
|
||||||
|
if (scenario != null) {
|
||||||
|
scenario.getScenarioCharacters().size();
|
||||||
|
scenario.getScenarioCharacters().forEach(sc -> sc.getCharacter().getName());
|
||||||
|
}
|
||||||
|
return scenario;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all scenarios ordered by name.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<ScenarioEntity> listAll() {
|
||||||
|
return list("ORDER BY name");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
package de.neitzel.roleplay.fascade;
|
||||||
|
|
||||||
|
import de.neitzel.roleplay.business.CharacterService;
|
||||||
|
import de.neitzel.roleplay.fascade.model.CharacterDefinition;
|
||||||
|
import de.neitzel.roleplay.fascade.model.CharacterListResponse;
|
||||||
|
import de.neitzel.roleplay.generated.api.CharactersApi;
|
||||||
|
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import jakarta.ws.rs.NotFoundException;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JAX-RS resource that implements the {@link CharactersApi} interface generated from the OpenAPI spec.
|
||||||
|
*/
|
||||||
|
@ApplicationScoped
|
||||||
|
public class CharactersResource implements CharactersApi {
|
||||||
|
|
||||||
|
private final CharacterService characterService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public CharactersResource(final CharacterService characterService) {
|
||||||
|
this.characterService = characterService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharacterListResponse listCharacters() {
|
||||||
|
CharacterListResponse response = new CharacterListResponse();
|
||||||
|
response.setCharacters(characterService.listCharacters());
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharacterDefinition getCharacter(final UUID characterId) {
|
||||||
|
return characterService.getCharacter(characterId)
|
||||||
|
.orElseThrow(() -> new NotFoundException("No character found with id: " + characterId));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
package de.neitzel.roleplay.fascade;
|
||||||
|
|
||||||
|
import de.neitzel.roleplay.business.ScenarioService;
|
||||||
|
import de.neitzel.roleplay.fascade.model.ScenarioListResponse;
|
||||||
|
import de.neitzel.roleplay.fascade.model.ScenarioSetup;
|
||||||
|
import de.neitzel.roleplay.generated.api.ScenariosApi;
|
||||||
|
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import jakarta.ws.rs.NotFoundException;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JAX-RS resource that implements the {@link ScenariosApi} interface generated from the OpenAPI spec.
|
||||||
|
*/
|
||||||
|
@ApplicationScoped
|
||||||
|
public class ScenariosResource implements ScenariosApi {
|
||||||
|
|
||||||
|
private final ScenarioService scenarioService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public ScenariosResource(final ScenarioService scenarioService) {
|
||||||
|
this.scenarioService = scenarioService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ScenarioListResponse listScenarios() {
|
||||||
|
ScenarioListResponse response = new ScenarioListResponse();
|
||||||
|
response.setScenarios(scenarioService.listScenarios());
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ScenarioSetup getScenario(final UUID scenarioId) {
|
||||||
|
return scenarioService.getScenarioAsSetup(scenarioId)
|
||||||
|
.orElseThrow(() -> new NotFoundException("No scenario found with id: " + scenarioId));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -12,6 +12,9 @@ quarkus:
|
|||||||
url: jdbc:h2:mem:roleplay;DB_CLOSE_DELAY=-1
|
url: jdbc:h2:mem:roleplay;DB_CLOSE_DELAY=-1
|
||||||
username: sa
|
username: sa
|
||||||
password: ""
|
password: ""
|
||||||
|
hibernate-orm:
|
||||||
|
database:
|
||||||
|
generation: none
|
||||||
liquibase:
|
liquibase:
|
||||||
change-log: db/migration/changelog.xml
|
change-log: db/migration/changelog.xml
|
||||||
migrate-at-start: true
|
migrate-at-start: true
|
||||||
|
|||||||
@ -4,5 +4,7 @@
|
|||||||
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
|
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
|
||||||
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.24.xsd">
|
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.24.xsd">
|
||||||
|
|
||||||
|
<include file="db/migration/v001__scenarios_and_characters.xml"/>
|
||||||
</databaseChangeLog>
|
</databaseChangeLog>
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,103 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<databaseChangeLog
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||||
|
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
|
||||||
|
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.24.xsd">
|
||||||
|
|
||||||
|
<changeSet id="001-1-create-character-table" author="roleplay">
|
||||||
|
<createTable tableName="rp_character">
|
||||||
|
<column name="id" type="uuid">
|
||||||
|
<constraints primaryKey="true" nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="name" type="varchar(255)">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="role" type="varchar(255)">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="backstory" type="clob"/>
|
||||||
|
<column name="personality_traits" type="clob"/>
|
||||||
|
<column name="speaking_style" type="varchar(1000)"/>
|
||||||
|
<column name="goals" type="clob"/>
|
||||||
|
</createTable>
|
||||||
|
<comment>Stores reusable character definitions. personality_traits and goals stored as JSON text.</comment>
|
||||||
|
</changeSet>
|
||||||
|
|
||||||
|
<changeSet id="001-2-create-scenario-table" author="roleplay">
|
||||||
|
<createTable tableName="scenario">
|
||||||
|
<column name="id" type="uuid">
|
||||||
|
<constraints primaryKey="true" nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="name" type="varchar(255)">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="setting" type="clob"/>
|
||||||
|
<column name="initial_conflict" type="clob"/>
|
||||||
|
</createTable>
|
||||||
|
<comment>Stores scenario templates (setting and initial conflict).</comment>
|
||||||
|
</changeSet>
|
||||||
|
|
||||||
|
<changeSet id="001-3-create-scenario-character-table" author="roleplay">
|
||||||
|
<createTable tableName="scenario_character">
|
||||||
|
<column name="id" type="uuid">
|
||||||
|
<constraints primaryKey="true" nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="scenario_id" type="uuid">
|
||||||
|
<constraints nullable="false" foreignKeyName="fk_scenario_character_scenario"
|
||||||
|
references="scenario(id)"/>
|
||||||
|
</column>
|
||||||
|
<column name="character_id" type="uuid">
|
||||||
|
<constraints nullable="false" foreignKeyName="fk_scenario_character_character"
|
||||||
|
references="rp_character(id)"/>
|
||||||
|
</column>
|
||||||
|
<column name="is_user_character" type="boolean">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="position" type="int">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
</createTable>
|
||||||
|
<comment>Links scenarios to characters; position orders AI characters.</comment>
|
||||||
|
</changeSet>
|
||||||
|
|
||||||
|
<changeSet id="001-4-seed-example-scenario" author="roleplay">
|
||||||
|
<insert tableName="rp_character">
|
||||||
|
<column name="id" value="11111111-1111-1111-1111-111111111101"/>
|
||||||
|
<column name="name" value="The Detective"/>
|
||||||
|
<column name="role" value="rookie detective"/>
|
||||||
|
<column name="backstory" value="Recently joined the force, eager to prove themselves."/>
|
||||||
|
<column name="personality_traits" value="["curious", "determined"]"/>
|
||||||
|
<column name="goals" value="["Solve the case", "Earn respect"]"/>
|
||||||
|
</insert>
|
||||||
|
<insert tableName="rp_character">
|
||||||
|
<column name="id" value="11111111-1111-1111-1111-111111111102"/>
|
||||||
|
<column name="name" value="Captain Morgan"/>
|
||||||
|
<column name="role" value="ship captain"/>
|
||||||
|
<column name="backstory" value="Veteran of many voyages; hides a secret."/>
|
||||||
|
<column name="personality_traits" value="["gruff", "wary"]"/>
|
||||||
|
<column name="goals" value="["Protect the crew", "Keep the past buried"]"/>
|
||||||
|
</insert>
|
||||||
|
<insert tableName="scenario">
|
||||||
|
<column name="id" value="22222222-2222-2222-2222-222222222201"/>
|
||||||
|
<column name="name" value="Harbour mystery"/>
|
||||||
|
<column name="setting" value="A fog-covered harbour at dawn, 1923"/>
|
||||||
|
<column name="initial_conflict" value="Strange noises from the cargo hold"/>
|
||||||
|
</insert>
|
||||||
|
<insert tableName="scenario_character">
|
||||||
|
<column name="id" value="33333333-3333-3333-3333-333333333301"/>
|
||||||
|
<column name="scenario_id" value="22222222-2222-2222-2222-222222222201"/>
|
||||||
|
<column name="character_id" value="11111111-1111-1111-1111-111111111101"/>
|
||||||
|
<column name="is_user_character" valueBoolean="true"/>
|
||||||
|
<column name="position" valueNumeric="0"/>
|
||||||
|
</insert>
|
||||||
|
<insert tableName="scenario_character">
|
||||||
|
<column name="id" value="33333333-3333-3333-3333-333333333302"/>
|
||||||
|
<column name="scenario_id" value="22222222-2222-2222-2222-222222222201"/>
|
||||||
|
<column name="character_id" value="11111111-1111-1111-1111-111111111102"/>
|
||||||
|
<column name="is_user_character" valueBoolean="false"/>
|
||||||
|
<column name="position" valueNumeric="1"/>
|
||||||
|
</insert>
|
||||||
|
</changeSet>
|
||||||
|
|
||||||
|
</databaseChangeLog>
|
||||||
@ -19,6 +19,10 @@ tags:
|
|||||||
description: Manage role-play sessions
|
description: Manage role-play sessions
|
||||||
- name: turns
|
- name: turns
|
||||||
description: Submit user actions within a session
|
description: Submit user actions within a session
|
||||||
|
- name: scenarios
|
||||||
|
description: List and retrieve saved scenario templates
|
||||||
|
- name: characters
|
||||||
|
description: List and retrieve saved character templates
|
||||||
|
|
||||||
paths:
|
paths:
|
||||||
|
|
||||||
@ -43,6 +47,82 @@ paths:
|
|||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/ErrorResponse'
|
$ref: '#/components/schemas/ErrorResponse'
|
||||||
|
|
||||||
|
/scenarios:
|
||||||
|
get:
|
||||||
|
operationId: listScenarios
|
||||||
|
summary: List saved scenarios
|
||||||
|
description: Returns all stored scenario templates for selection when starting a session.
|
||||||
|
tags:
|
||||||
|
- scenarios
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: List of scenario summaries.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ScenarioListResponse'
|
||||||
|
|
||||||
|
/scenarios/{scenarioId}:
|
||||||
|
get:
|
||||||
|
operationId: getScenario
|
||||||
|
summary: Get a scenario by id
|
||||||
|
description: Returns the full scenario setup (setting, conflict, characters) for the given id.
|
||||||
|
tags:
|
||||||
|
- scenarios
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/components/parameters/ScenarioId'
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: Scenario found and returned.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ScenarioSetup'
|
||||||
|
"404":
|
||||||
|
description: Scenario not found.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ErrorResponse'
|
||||||
|
|
||||||
|
/characters:
|
||||||
|
get:
|
||||||
|
operationId: listCharacters
|
||||||
|
summary: List saved characters
|
||||||
|
description: Returns all stored character templates for selection when building a scenario.
|
||||||
|
tags:
|
||||||
|
- characters
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: List of character definitions.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/CharacterListResponse'
|
||||||
|
|
||||||
|
/characters/{characterId}:
|
||||||
|
get:
|
||||||
|
operationId: getCharacter
|
||||||
|
summary: Get a character by id
|
||||||
|
description: Returns the full character definition for the given id.
|
||||||
|
tags:
|
||||||
|
- characters
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/components/parameters/CharacterId'
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: Character found and returned.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/CharacterDefinition'
|
||||||
|
"404":
|
||||||
|
description: Character not found.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ErrorResponse'
|
||||||
|
|
||||||
/sessions:
|
/sessions:
|
||||||
post:
|
post:
|
||||||
operationId: createSession
|
operationId: createSession
|
||||||
@ -191,6 +271,22 @@ components:
|
|||||||
description: Unique identifier of the role-play session.
|
description: Unique identifier of the role-play session.
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
|
ScenarioId:
|
||||||
|
name: scenarioId
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
description: Unique identifier of the scenario (UUID).
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
CharacterId:
|
||||||
|
name: characterId
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
description: Unique identifier of the character (UUID).
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
|
||||||
schemas:
|
schemas:
|
||||||
|
|
||||||
@ -255,9 +351,56 @@ components:
|
|||||||
default: standard
|
default: standard
|
||||||
scenario:
|
scenario:
|
||||||
$ref: '#/components/schemas/ScenarioSetup'
|
$ref: '#/components/schemas/ScenarioSetup'
|
||||||
|
scenarioId:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
description: If set, the backend loads this scenario from the database and uses it instead of an inline scenario.
|
||||||
required:
|
required:
|
||||||
- model
|
- model
|
||||||
|
|
||||||
|
ScenarioSummary:
|
||||||
|
type: object
|
||||||
|
description: Summary of a stored scenario for list views.
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
description: Unique identifier of the scenario.
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: Human-readable scenario name.
|
||||||
|
setting:
|
||||||
|
type: string
|
||||||
|
description: Place, time, and atmosphere (optional in list).
|
||||||
|
initialConflict:
|
||||||
|
type: string
|
||||||
|
description: The hook or starting conflict (optional in list).
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- name
|
||||||
|
|
||||||
|
ScenarioListResponse:
|
||||||
|
type: object
|
||||||
|
description: Response containing all stored scenarios.
|
||||||
|
properties:
|
||||||
|
scenarios:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/ScenarioSummary'
|
||||||
|
required:
|
||||||
|
- scenarios
|
||||||
|
|
||||||
|
CharacterListResponse:
|
||||||
|
type: object
|
||||||
|
description: Response containing all stored characters.
|
||||||
|
properties:
|
||||||
|
characters:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/CharacterDefinition'
|
||||||
|
required:
|
||||||
|
- characters
|
||||||
|
|
||||||
ScenarioSetup:
|
ScenarioSetup:
|
||||||
type: object
|
type: object
|
||||||
description: |
|
description: |
|
||||||
|
|||||||
@ -0,0 +1,14 @@
|
|||||||
|
{{#required}}
|
||||||
|
{{^isReadOnly}}
|
||||||
|
@NotNull
|
||||||
|
{{/isReadOnly}}
|
||||||
|
{{/required}}
|
||||||
|
{{#isContainer}}
|
||||||
|
{{! Do not add @Valid on container; we use type-argument @Valid in the pojo (List<@Valid T>) to fix HV000271 }}
|
||||||
|
{{/isContainer}}
|
||||||
|
{{^isContainer}}
|
||||||
|
{{^isPrimitiveType}}
|
||||||
|
@Valid
|
||||||
|
{{/isPrimitiveType}}
|
||||||
|
{{/isContainer}}
|
||||||
|
{{>beanValidationCore}}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
{{#required}}
|
||||||
|
{{^isReadOnly}}
|
||||||
|
@NotNull
|
||||||
|
{{/isReadOnly}}
|
||||||
|
{{/required}}
|
||||||
|
{{#isContainer}}
|
||||||
|
{{! Do not add @Valid on container; we use type-argument @Valid in the pojo (List<@Valid T>) to fix HV000271 }}
|
||||||
|
{{/isContainer}}
|
||||||
|
{{^isContainer}}
|
||||||
|
{{^isPrimitiveType}}
|
||||||
|
@Valid
|
||||||
|
{{/isPrimitiveType}}
|
||||||
|
{{/isContainer}}
|
||||||
|
{{>beanValidationCore}}
|
||||||
146
src/main/resources/openapi-templates/JavaJaxRS/pojo.mustache
Normal file
146
src/main/resources/openapi-templates/JavaJaxRS/pojo.mustache
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
/**
|
||||||
|
* {{description}}{{^description}}{{classname}}{{/description}}
|
||||||
|
*/{{#description}}
|
||||||
|
@ApiModel(description = "{{{.}}}"){{/description}}
|
||||||
|
{{#jackson}}
|
||||||
|
@JsonPropertyOrder({
|
||||||
|
{{#vars}}
|
||||||
|
{{classname}}.JSON_PROPERTY_{{nameInSnakeCase}}{{^-last}},{{/-last}}
|
||||||
|
{{/vars}}
|
||||||
|
})
|
||||||
|
{{/jackson}}
|
||||||
|
{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}
|
||||||
|
{{#vendorExtensions.x-class-extra-annotation}}
|
||||||
|
{{{vendorExtensions.x-class-extra-annotation}}}
|
||||||
|
{{/vendorExtensions.x-class-extra-annotation}}
|
||||||
|
public class {{classname}} {{#parent}}extends {{{.}}}{{/parent}} {{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.x-implements}} {
|
||||||
|
{{#vars}}
|
||||||
|
{{#isEnum}}
|
||||||
|
{{^isContainer}}
|
||||||
|
{{>enumClass}}
|
||||||
|
|
||||||
|
{{/isContainer}}
|
||||||
|
{{#isContainer}}
|
||||||
|
{{#mostInnerItems}}
|
||||||
|
{{>enumClass}}
|
||||||
|
|
||||||
|
{{/mostInnerItems}}
|
||||||
|
{{/isContainer}}
|
||||||
|
{{/isEnum}}
|
||||||
|
{{#jackson}}
|
||||||
|
public static final String JSON_PROPERTY_{{nameInSnakeCase}} = "{{baseName}}";
|
||||||
|
@JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}})
|
||||||
|
{{/jackson}}
|
||||||
|
{{#gson}}
|
||||||
|
public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}";
|
||||||
|
@SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}})
|
||||||
|
{{/gson}}
|
||||||
|
{{#vendorExtensions.x-field-extra-annotation}}
|
||||||
|
{{{.}}}
|
||||||
|
{{/vendorExtensions.x-field-extra-annotation}}
|
||||||
|
private {{>propertyType}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
|
||||||
|
|
||||||
|
{{/vars}}
|
||||||
|
{{#vars}}
|
||||||
|
public {{classname}} {{name}}({{>propertyType}} {{name}}) {
|
||||||
|
this.{{name}} = {{name}};
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
{{#isArray}}
|
||||||
|
|
||||||
|
public {{classname}} add{{nameInPascalCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) {
|
||||||
|
if (this.{{name}} == null) {
|
||||||
|
this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new {{#uniqueItems}}LinkedHashSet{{/uniqueItems}}{{^uniqueItems}}ArrayList{{/uniqueItems}}<>(){{/defaultValue}};
|
||||||
|
}
|
||||||
|
this.{{name}}.add({{name}}Item);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
{{/isArray}}
|
||||||
|
{{#isMap}}
|
||||||
|
|
||||||
|
public {{classname}} put{{nameInPascalCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) {
|
||||||
|
if (this.{{name}} == null) {
|
||||||
|
this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new HashMap<>(){{/defaultValue}};
|
||||||
|
}
|
||||||
|
this.{{name}}.put(key, {{name}}Item);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
{{/isMap}}
|
||||||
|
|
||||||
|
/**
|
||||||
|
{{#description}}
|
||||||
|
* {{.}}
|
||||||
|
{{/description}}
|
||||||
|
{{^description}}
|
||||||
|
* Get {{name}}
|
||||||
|
{{/description}}
|
||||||
|
{{#minimum}}
|
||||||
|
* minimum: {{.}}
|
||||||
|
{{/minimum}}
|
||||||
|
{{#maximum}}
|
||||||
|
* maximum: {{.}}
|
||||||
|
{{/maximum}}
|
||||||
|
* @return {{name}}
|
||||||
|
**/
|
||||||
|
{{#vendorExtensions.x-extra-annotation}}
|
||||||
|
{{{vendorExtensions.x-extra-annotation}}}
|
||||||
|
{{/vendorExtensions.x-extra-annotation}}
|
||||||
|
{{#jackson}}
|
||||||
|
@JsonProperty(value = "{{baseName}}"{{#isReadOnly}}, access = JsonProperty.Access.READ_ONLY{{/isReadOnly}}{{#isWriteOnly}}, access = JsonProperty.Access.WRITE_ONLY{{/isWriteOnly}})
|
||||||
|
{{/jackson}}
|
||||||
|
@ApiModelProperty({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}")
|
||||||
|
{{#useBeanValidation}}{{#required}}{{^isReadOnly}}
|
||||||
|
@NotNull
|
||||||
|
{{/isReadOnly}}{{/required}}{{#isContainer}}{{! No @Valid on container; type has List<@Valid T> (HV000271) }}{{/isContainer}}{{^isContainer}}{{^isPrimitiveType}}
|
||||||
|
@Valid
|
||||||
|
{{/isPrimitiveType}}{{/isContainer}}{{>beanValidationCore}}{{/useBeanValidation}}
|
||||||
|
public {{>propertyType}} {{getter}}() {
|
||||||
|
return {{name}};
|
||||||
|
}
|
||||||
|
|
||||||
|
{{#vendorExtensions.x-setter-extra-annotation}}{{{vendorExtensions.x-setter-extra-annotation}}}
|
||||||
|
{{/vendorExtensions.x-setter-extra-annotation}}public void {{setter}}({{>propertyType}} {{name}}) {
|
||||||
|
this.{{name}} = {{name}};
|
||||||
|
}
|
||||||
|
|
||||||
|
{{/vars}}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
{{classname}} {{classVarName}} = ({{classname}}) o;{{#hasVars}}
|
||||||
|
return {{#parent}}super.equals(o) && {{/parent}}{{#vars}}Objects.equals(this.{{name}}, {{classVarName}}.{{name}}){{^-last}} &&
|
||||||
|
{{/-last}}{{#-last}};{{/-last}}{{/vars}}{{/hasVars}}{{^hasVars}}{{#parent}}return super.equals(o);{{/parent}}{{^parent}}return true;{{/parent}}{{/hasVars}}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return {{^hasVars}}{{#parent}}super.hashCode(){{/parent}}{{^parent}}1{{/parent}}{{/hasVars}}{{#hasVars}}Objects.hash({{#vars}}{{#parent}}super.hashCode(), {{/parent}}{{name}}{{^-last}}, {{/-last}}{{/vars}}){{/hasVars}};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("class {{classname}} {\n");
|
||||||
|
{{#parent}}sb.append(" ").append(toIndentedString(super.toString())).append("\n");{{/parent}}
|
||||||
|
{{#vars}}sb.append(" {{name}}: ").append({{#isPassword}}"*"{{/isPassword}}{{^isPassword}}toIndentedString({{name}}){{/isPassword}}).append("\n");
|
||||||
|
{{/vars}}sb.append("}");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given object to string with each line indented by 4 spaces
|
||||||
|
* (except the first line).
|
||||||
|
*/
|
||||||
|
private String toIndentedString(Object o) {
|
||||||
|
if (o == null) {
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
return o.toString().replace("\n", "\n ");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
{{! Type with @Valid on type argument for containers (HV000271 fix). }}{{#isContainer}}{{#isArray}}{{#items.isPrimitiveType}}{{{datatypeWithEnum}}}{{/items.isPrimitiveType}}{{^items.isPrimitiveType}}{{#items.isEnum}}{{{datatypeWithEnum}}}{{/items.isEnum}}{{^items.isEnum}}List<@Valid {{{items.datatypeWithEnum}}}>{{/items.isEnum}}{{/items.isPrimitiveType}}{{/isArray}}{{^isArray}}{{#isMap}}{{#items.isPrimitiveType}}{{{datatypeWithEnum}}}{{/items.isPrimitiveType}}{{^items.isPrimitiveType}}{{#items.isEnum}}{{{datatypeWithEnum}}}{{/items.isEnum}}{{^items.isEnum}}Map<String, @Valid {{{items.datatypeWithEnum}}}>{{/items.isEnum}}{{/items.isPrimitiveType}}{{/isMap}}{{^isMap}}{{{datatypeWithEnum}}}{{/isMap}}{{/isMap}}{{/isArray}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}{{/isContainer}}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
{{#required}}{{^isReadOnly}}@NotNull {{/isReadOnly}}{{/required}}{{#isContainer}}{{! Do not add @Valid on container; use type-argument @Valid (HV000271) }}{{/isContainer}}{{^isContainer}}{{^isPrimitiveType}}{{^isDate}}{{^isDateTime}}{{^isString}}{{^isFile}}{{^isEnumOrRef}}@Valid {{/isEnumOrRef}}{{/isFile}}{{/isString}}{{/isDateTime}}{{/isDate}}{{/isPrimitiveType}}{{/isContainer}}{{>beanValidationCore}}
|
||||||
@ -0,0 +1,289 @@
|
|||||||
|
{{#useSwaggerAnnotations}}
|
||||||
|
import io.swagger.annotations.*;
|
||||||
|
{{/useSwaggerAnnotations}}
|
||||||
|
{{#useSwaggerV3Annotations}}
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
{{/useSwaggerV3Annotations}}
|
||||||
|
import java.util.Objects;
|
||||||
|
{{#jackson}}
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||||
|
{{#additionalProperties}}
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonAnySetter;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonAnyGetter;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
{{/additionalProperties}}
|
||||||
|
{{/jackson}}
|
||||||
|
{{#openApiNullable}}
|
||||||
|
import org.openapitools.jackson.nullable.JsonNullable;
|
||||||
|
{{/openApiNullable}}
|
||||||
|
{{#withXml}}
|
||||||
|
import {{javaxPackage}}.xml.bind.annotation.XmlElement;
|
||||||
|
import {{javaxPackage}}.xml.bind.annotation.XmlRootElement;
|
||||||
|
import {{javaxPackage}}.xml.bind.annotation.XmlAccessType;
|
||||||
|
import {{javaxPackage}}.xml.bind.annotation.XmlAccessorType;
|
||||||
|
import {{javaxPackage}}.xml.bind.annotation.XmlType;
|
||||||
|
import {{javaxPackage}}.xml.bind.annotation.XmlEnum;
|
||||||
|
import {{javaxPackage}}.xml.bind.annotation.XmlEnumValue;
|
||||||
|
{{/withXml}}
|
||||||
|
|
||||||
|
{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{#description}}/**
|
||||||
|
* {{.}}
|
||||||
|
**/{{/description}}
|
||||||
|
{{#useSwaggerAnnotations}}{{#description}}@ApiModel(description = "{{{.}}}"){{/description}}{{/useSwaggerAnnotations}}{{#useSwaggerV3Annotations}}
|
||||||
|
@Schema({{#title}}title="{{{.}}}", {{/title}}{{#description}}description="{{{.}}}"{{/description}}{{^description}}description=""{{/description}}){{/useSwaggerV3Annotations}}{{#useMicroProfileOpenAPIAnnotations}}
|
||||||
|
@org.eclipse.microprofile.openapi.annotations.media.Schema({{#title}}title="{{{.}}}", {{/title}}{{#description}}description="{{{.}}}"{{/description}}{{^description}}description=""{{/description}}){{/useMicroProfileOpenAPIAnnotations}}
|
||||||
|
{{#jackson}}
|
||||||
|
@JsonTypeName("{{name}}")
|
||||||
|
{{#additionalProperties}}
|
||||||
|
@JsonFormat(shape=JsonFormat.Shape.OBJECT)
|
||||||
|
{{/additionalProperties}}
|
||||||
|
{{/jackson}}
|
||||||
|
{{>generatedAnnotation}}{{>additionalModelTypeAnnotations}}{{>xmlPojoAnnotation}}
|
||||||
|
{{#vendorExtensions.x-class-extra-annotation}}
|
||||||
|
{{{vendorExtensions.x-class-extra-annotation}}}
|
||||||
|
{{/vendorExtensions.x-class-extra-annotation}}
|
||||||
|
public class {{classname}} {{#parent}}extends {{{.}}}{{/parent}} {{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.x-implements}} {
|
||||||
|
{{#vars}}
|
||||||
|
{{#isEnum}}
|
||||||
|
{{^isContainer}}
|
||||||
|
{{>enumClass}}{{! prevent indent}}
|
||||||
|
{{/isContainer}}
|
||||||
|
{{#isContainer}}
|
||||||
|
{{#mostInnerItems}}
|
||||||
|
{{>enumClass}}{{! prevent indent}}
|
||||||
|
{{/mostInnerItems}}
|
||||||
|
{{/isContainer}}
|
||||||
|
{{/isEnum}}
|
||||||
|
{{#vendorExtensions.x-field-extra-annotation}}
|
||||||
|
{{{.}}}
|
||||||
|
{{/vendorExtensions.x-field-extra-annotation}}
|
||||||
|
{{#vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
{{#isContainer}}
|
||||||
|
private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined();
|
||||||
|
{{/isContainer}}
|
||||||
|
{{^isContainer}}
|
||||||
|
private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}};
|
||||||
|
{{/isContainer}}
|
||||||
|
{{/vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
{{^vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
private {{#useBeanValidation}}{{>beanValidatedType}}{{/useBeanValidation}}{{^useBeanValidation}}{{{datatypeWithEnum}}}{{/useBeanValidation}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
|
||||||
|
{{/vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
{{/vars}}
|
||||||
|
|
||||||
|
{{#generateBuilders}}
|
||||||
|
{{^additionalProperties}}
|
||||||
|
protected {{classname}}({{classname}}Builder b) {
|
||||||
|
{{#parent}}
|
||||||
|
super(b);
|
||||||
|
{{/parent}}
|
||||||
|
{{#vars}}
|
||||||
|
this.{{name}} = b.{{name}};
|
||||||
|
{{/vars}}
|
||||||
|
}
|
||||||
|
|
||||||
|
{{/additionalProperties}}
|
||||||
|
{{/generateBuilders}}
|
||||||
|
public {{classname}}() {
|
||||||
|
}
|
||||||
|
|
||||||
|
{{#jackson}}
|
||||||
|
{{#generateJsonCreator}}
|
||||||
|
{{#hasRequired}}
|
||||||
|
@JsonCreator
|
||||||
|
public {{classname}}(
|
||||||
|
{{#requiredVars}}
|
||||||
|
@JsonProperty(required = {{required}}, value = "{{baseName}}") {{>beanValidatedType}} {{name}}{{^-last}},{{/-last}}
|
||||||
|
{{/requiredVars}}
|
||||||
|
) {
|
||||||
|
{{#parent}}
|
||||||
|
super(
|
||||||
|
{{#parentRequiredVars}}
|
||||||
|
{{name}}{{^-last}},{{/-last}}
|
||||||
|
{{/parentRequiredVars}}
|
||||||
|
);
|
||||||
|
{{/parent}}
|
||||||
|
{{#vars}}
|
||||||
|
{{#required}}
|
||||||
|
this.{{name}} = {{name}};
|
||||||
|
{{/required}}
|
||||||
|
{{/vars}}
|
||||||
|
}
|
||||||
|
|
||||||
|
{{/hasRequired}}
|
||||||
|
{{/generateJsonCreator}}
|
||||||
|
{{/jackson}}
|
||||||
|
{{#vars}}
|
||||||
|
/**
|
||||||
|
{{#description}}
|
||||||
|
* {{.}}
|
||||||
|
{{/description}}
|
||||||
|
{{#minimum}}
|
||||||
|
* minimum: {{.}}
|
||||||
|
{{/minimum}}
|
||||||
|
{{#maximum}}
|
||||||
|
* maximum: {{.}}
|
||||||
|
{{/maximum}}
|
||||||
|
**/
|
||||||
|
public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) {
|
||||||
|
{{#vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});
|
||||||
|
{{/vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
{{^vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
this.{{name}} = {{name}};
|
||||||
|
{{/vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
{{#withXml}}
|
||||||
|
@XmlElement(name="{{baseName}}"{{#required}}, required = {{required}}{{/required}})
|
||||||
|
{{/withXml}}
|
||||||
|
{{#vendorExtensions.x-extra-annotation}}{{{vendorExtensions.x-extra-annotation}}}{{/vendorExtensions.x-extra-annotation}}{{#useSwaggerAnnotations}}
|
||||||
|
@ApiModelProperty({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}"){{/useSwaggerAnnotations}}{{#useSwaggerV3Annotations}}
|
||||||
|
@Schema({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}description = "{{{description}}}"){{/useSwaggerV3Annotations}}{{#useMicroProfileOpenAPIAnnotations}}
|
||||||
|
@org.eclipse.microprofile.openapi.annotations.media.Schema({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}description = "{{{description}}}"){{/useMicroProfileOpenAPIAnnotations}}
|
||||||
|
{{#jackson}}@JsonProperty({{#required}}required = {{required}}, value = {{/required}}"{{baseName}}"){{/jackson}}
|
||||||
|
{{#vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
public JsonNullable<{{{datatypeWithEnum}}}> {{getter}}() {
|
||||||
|
return {{name}};
|
||||||
|
}
|
||||||
|
{{/vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
{{^vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}}public {{>beanValidatedType}} {{getter}}() {
|
||||||
|
return {{name}};
|
||||||
|
}
|
||||||
|
{{/vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
|
||||||
|
{{#jackson}}
|
||||||
|
@JsonProperty({{#required}}required = {{required}}, value = {{/required}}"{{baseName}}")
|
||||||
|
{{/jackson}}
|
||||||
|
{{#vendorExtensions.x-setter-extra-annotation}}{{{vendorExtensions.x-setter-extra-annotation}}}
|
||||||
|
{{/vendorExtensions.x-setter-extra-annotation}}public void {{setter}}({{{datatypeWithEnum}}} {{name}}) {
|
||||||
|
{{#vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});
|
||||||
|
{{/vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
{{^vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
this.{{name}} = {{name}};
|
||||||
|
{{/vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
}
|
||||||
|
|
||||||
|
{{#isArray}}
|
||||||
|
public {{classname}} add{{nameInPascalCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) {
|
||||||
|
if (this.{{name}} == null) {
|
||||||
|
this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new {{#uniqueItems}}LinkedHashSet{{/uniqueItems}}{{^uniqueItems}}ArrayList{{/uniqueItems}}<>(){{/defaultValue}};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.{{name}}.add({{name}}Item);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public {{classname}} remove{{nameInPascalCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) {
|
||||||
|
if ({{name}}Item != null && this.{{name}} != null) {
|
||||||
|
this.{{name}}.remove({{name}}Item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
{{/isArray}}
|
||||||
|
{{#isMap}}
|
||||||
|
public {{classname}} put{{nameInPascalCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) {
|
||||||
|
if (this.{{name}} == null) {
|
||||||
|
this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new HashMap<>(){{/defaultValue}};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.{{name}}.put(key, {{name}}Item);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public {{classname}} remove{{nameInPascalCase}}Item(String key) {
|
||||||
|
if (this.{{name}} != null) {
|
||||||
|
this.{{name}}.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
{{/isMap}}
|
||||||
|
{{/vars}}
|
||||||
|
{{>additional_properties}}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}{{#hasVars}}
|
||||||
|
{{classname}} {{classVarName}} = ({{classname}}) o;
|
||||||
|
return {{#vars}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{^-last}} &&
|
||||||
|
{{/-last}}{{/vars}}{{#parent}} &&
|
||||||
|
super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}}
|
||||||
|
return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash({{#vars}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("class {{classname}} {\n");
|
||||||
|
{{#parent}}sb.append(" ").append(toIndentedString(super.toString())).append("\n");{{/parent}}
|
||||||
|
{{#vars}}sb.append(" {{name}}: ").append({{#isPassword}}"*"{{/isPassword}}{{^isPassword}}toIndentedString({{name}}){{/isPassword}}).append("\n");
|
||||||
|
{{/vars}}sb.append("}");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given object to string with each line indented by 4 spaces
|
||||||
|
* (except the first line).
|
||||||
|
*/
|
||||||
|
private String toIndentedString(Object o) {
|
||||||
|
if (o == null) {
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
return o.toString().replace("\n", "\n ");
|
||||||
|
}
|
||||||
|
|
||||||
|
{{#generateBuilders}}{{^additionalProperties}}
|
||||||
|
public static {{classname}}Builder builder() {
|
||||||
|
return new {{classname}}BuilderImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class {{classname}}BuilderImpl extends {{classname}}Builder<{{classname}}, {{classname}}BuilderImpl> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected {{classname}}BuilderImpl self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public {{classname}} build() {
|
||||||
|
return new {{classname}}(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static abstract class {{classname}}Builder > {{#parent}}extends {{{.}}}Builder {{/parent}} {
|
||||||
|
{{#vars}}
|
||||||
|
private {{#removeAnnotations}}{{{datatypeWithEnum}}}{{/removeAnnotations}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
|
||||||
|
{{/vars}}
|
||||||
|
{{^parent}}
|
||||||
|
protected abstract B self();
|
||||||
|
|
||||||
|
public abstract C build();
|
||||||
|
{{/parent}}
|
||||||
|
|
||||||
|
{{#vars}}
|
||||||
|
public B {{name}}({{#removeAnnotations}}{{{datatypeWithEnum}}}{{/removeAnnotations}} {{name}}) {
|
||||||
|
this.{{name}} = {{name}};
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
{{/vars}}
|
||||||
|
}{{/additionalProperties}}{{/generateBuilders}}
|
||||||
|
}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
{{#additionalEnumTypeAnnotations}}{{{.}}}
|
||||||
|
{{/additionalEnumTypeAnnotations}}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
{{#additionalModelTypeAnnotations}}{{{.}}}
|
||||||
|
{{/additionalModelTypeAnnotations}}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
{{#additionalProperties}}
|
||||||
|
/**
|
||||||
|
* Set the additional (undeclared) property with the specified name and value.
|
||||||
|
* Creates the property if it does not already exist, otherwise replaces it.
|
||||||
|
* @param key the name of the property
|
||||||
|
* @param value the value of the property
|
||||||
|
* @return self reference
|
||||||
|
*/
|
||||||
|
@JsonAnySetter
|
||||||
|
public {{classname}} putAdditionalProperty(String key, {{{datatypeWithEnum}}} value) {
|
||||||
|
this.put(key, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the additional (undeclared) properties.
|
||||||
|
* @return the additional (undeclared) properties
|
||||||
|
*/
|
||||||
|
@JsonAnyGetter
|
||||||
|
public Map getAdditionalProperties() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the additional (undeclared) property with the specified name.
|
||||||
|
* @param key the name of the property
|
||||||
|
* @return the additional (undeclared) property with the specified name
|
||||||
|
*/
|
||||||
|
public {{{datatypeWithEnum}}} getAdditionalProperty(String key) {
|
||||||
|
return this.get(key);
|
||||||
|
}
|
||||||
|
{{/additionalProperties}}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
{{#isArray}}{{baseType}}<{{#items}}{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}}{{>beanValidatedType}}{{/items}}>{{/isArray}}{{^isArray}}{{{datatypeWithEnum}}}{{/isArray}}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
{{#required}}{{^isReadOnly}}@NotNull {{/isReadOnly}}{{/required}}{{#isContainer}}{{! No @Valid on container (HV000271) }}{{/isContainer}}{{^isContainer}}{{^isPrimitiveType}}{{^isDate}}{{^isDateTime}}{{^isString}}{{^isFile}}{{^isEnumOrRef}}@Valid {{/isEnumOrRef}}{{/isFile}}{{/isString}}{{/isDateTime}}{{/isDate}}{{/isPrimitiveType}}{{/isContainer}}{{>beanValidationCore}}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
{{#pattern}} @Pattern(regexp="{{{.}}}"){{/pattern}}{{!
|
||||||
|
minLength && maxLength set
|
||||||
|
}}{{#minLength}}{{#maxLength}} @Size(min={{minLength}},max={{maxLength}}){{/maxLength}}{{/minLength}}{{!
|
||||||
|
minLength set, maxLength not
|
||||||
|
}}{{#minLength}}{{^maxLength}} @Size(min={{minLength}}){{/maxLength}}{{/minLength}}{{!
|
||||||
|
minLength not set, maxLength set
|
||||||
|
}}{{^minLength}}{{#maxLength}} @Size(max={{.}}){{/maxLength}}{{/minLength}}{{!
|
||||||
|
@Size: minItems && maxItems set
|
||||||
|
}}{{#minItems}}{{#maxItems}} @Size(min={{minItems}},max={{maxItems}}){{/maxItems}}{{/minItems}}{{!
|
||||||
|
@Size: minItems set, maxItems not
|
||||||
|
}}{{#minItems}}{{^maxItems}} @Size(min={{minItems}}){{/maxItems}}{{/minItems}}{{!
|
||||||
|
@Size: minItems not set && maxItems set
|
||||||
|
}}{{^minItems}}{{#maxItems}} @Size(max={{.}}){{/maxItems}}{{/minItems}}{{!
|
||||||
|
check for integer or long / all others=decimal type with @Decimal*
|
||||||
|
isInteger set
|
||||||
|
}}{{#isInteger}}{{#minimum}} @Min({{.}}){{/minimum}}{{#maximum}} @Max({{.}}){{/maximum}}{{/isInteger}}{{!
|
||||||
|
isLong set
|
||||||
|
}}{{#isLong}}{{#minimum}} @Min({{.}}L){{/minimum}}{{#maximum}} @Max({{.}}L){{/maximum}}{{/isLong}}{{!
|
||||||
|
Not Integer, not Long => we have a decimal value!
|
||||||
|
}}{{^isInteger}}{{^isLong}}{{#minimum}} @DecimalMin({{#exclusiveMinimum}}value={{/exclusiveMinimum}}"{{minimum}}"{{#exclusiveMinimum}},inclusive=false{{/exclusiveMinimum}}){{/minimum}}{{#maximum}} @DecimalMax({{#exclusiveMaximum}}value={{/exclusiveMaximum}}"{{maximum}}"{{#exclusiveMaximum}},inclusive=false{{/exclusiveMaximum}}){{/maximum}}{{/isLong}}{{/isInteger}}
|
||||||
56
src/main/resources/openapi-templates/enumClass.mustache
Normal file
56
src/main/resources/openapi-templates/enumClass.mustache
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
{{#withXml}}
|
||||||
|
@XmlType(name="{{datatypeWithEnum}}")
|
||||||
|
@XmlEnum({{dataType}}.class)
|
||||||
|
{{/withXml}}
|
||||||
|
{{>additionalEnumTypeAnnotations}}public enum {{datatypeWithEnum}} {
|
||||||
|
|
||||||
|
{{#allowableValues}}
|
||||||
|
{{#enumVars}}{{#withXml}}@XmlEnumValue({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}){{/withXml}}{{name}}({{dataType}}.valueOf({{{value}}})){{^-last}}, {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}
|
||||||
|
{{/allowableValues}}
|
||||||
|
|
||||||
|
|
||||||
|
private {{dataType}} value;
|
||||||
|
|
||||||
|
{{datatypeWithEnum}} ({{dataType}} v) {
|
||||||
|
value = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
public {{dataType}} value() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
{{#jackson}}
|
||||||
|
@JsonValue
|
||||||
|
{{/jackson}}
|
||||||
|
public String toString() {
|
||||||
|
return String.valueOf(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a String into {{dataType}}, as specified in the
|
||||||
|
* See JAX RS 2.0 Specification, section 3.2, p. 12
|
||||||
|
*/
|
||||||
|
public static {{datatypeWithEnum}} fromString(String s) {
|
||||||
|
for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) {
|
||||||
|
// using Objects.toString() to be safe if value type non-object type
|
||||||
|
// because types like 'int' etc. will be auto-boxed
|
||||||
|
if (java.util.Objects.toString(b.value).equals(s)) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{{#isNullable}}return null;{{/isNullable}}{{^isNullable}}throw new IllegalArgumentException("Unexpected string value '" + s + "'");{{/isNullable}}
|
||||||
|
}
|
||||||
|
|
||||||
|
{{#jackson}}
|
||||||
|
@JsonCreator
|
||||||
|
public static {{datatypeWithEnum}} fromValue({{dataType}} value) {
|
||||||
|
for ({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) {
|
||||||
|
if (b.value.{{^isString}}equals{{/isString}}{{#isString}}{{#useEnumCaseInsensitive}}equalsIgnoreCase{{/useEnumCaseInsensitive}}{{^useEnumCaseInsensitive}}equals{{/useEnumCaseInsensitive}}{{/isString}}(value)) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{{#isNullable}}return null;{{/isNullable}}{{^isNullable}}{{#enumUnknownDefaultCase}}{{#allowableValues}}{{#enumVars}}{{#-last}}return {{{name}}};{{/-last}}{{/enumVars}}{{/allowableValues}}{{/enumUnknownDefaultCase}}{{^enumUnknownDefaultCase}}throw new IllegalArgumentException("Unexpected value '" + value + "'");{{/enumUnknownDefaultCase}}{{/isNullable}}
|
||||||
|
}
|
||||||
|
{{/jackson}}
|
||||||
|
}
|
||||||
64
src/main/resources/openapi-templates/enumOuterClass.mustache
Normal file
64
src/main/resources/openapi-templates/enumOuterClass.mustache
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
{{#jackson}}
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
{{/jackson}}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {{description}}{{^description}}Gets or Sets {{{name}}}{{/description}}
|
||||||
|
*/
|
||||||
|
{{>generatedAnnotation}}
|
||||||
|
|
||||||
|
{{>additionalEnumTypeAnnotations}}public enum {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} {
|
||||||
|
{{#gson}}
|
||||||
|
{{#allowableValues}}{{#enumVars}}
|
||||||
|
@SerializedName({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}})
|
||||||
|
{{{name}}}({{{value}}}){{^-last}},
|
||||||
|
{{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}}
|
||||||
|
{{/gson}}
|
||||||
|
{{^gson}}
|
||||||
|
{{#allowableValues}}{{#enumVars}}
|
||||||
|
{{{name}}}({{{value}}}){{^-last}},
|
||||||
|
{{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}}
|
||||||
|
{{/gson}}
|
||||||
|
|
||||||
|
private {{{dataType}}} value;
|
||||||
|
|
||||||
|
{{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}({{{dataType}}} value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a String into {{dataType}}, as specified in the
|
||||||
|
* See JAX RS 2.0 Specification, section 3.2, p. 12
|
||||||
|
*/
|
||||||
|
public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromString(String s) {
|
||||||
|
for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) {
|
||||||
|
// using Objects.toString() to be safe if value type non-object type
|
||||||
|
// because types like 'int' etc. will be auto-boxed
|
||||||
|
if (java.util.Objects.toString(b.value).equals(s)) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{{#isNullable}}return null;{{/isNullable}}{{^isNullable}}throw new IllegalArgumentException("Unexpected string value '" + s + "'");{{/isNullable}}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
{{#jackson}}
|
||||||
|
@JsonValue
|
||||||
|
{{/jackson}}
|
||||||
|
public String toString() {
|
||||||
|
return String.valueOf(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
{{#jackson}}
|
||||||
|
@JsonCreator
|
||||||
|
public static {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue({{{dataType}}} value) {
|
||||||
|
for ({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) {
|
||||||
|
if (b.value.{{^isString}}equals{{/isString}}{{#isString}}{{#useEnumCaseInsensitive}}equalsIgnoreCase{{/useEnumCaseInsensitive}}{{^useEnumCaseInsensitive}}equals{{/useEnumCaseInsensitive}}{{/isString}}(value)) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{{#isNullable}}return null;{{/isNullable}}{{^isNullable}}{{#enumUnknownDefaultCase}}{{#allowableValues}}{{#enumVars}}{{#-last}}return {{{name}}};{{/-last}}{{/enumVars}}{{/allowableValues}}{{/enumUnknownDefaultCase}}{{^enumUnknownDefaultCase}}throw new IllegalArgumentException("Unexpected value '" + value + "'");{{/enumUnknownDefaultCase}}{{/isNullable}}
|
||||||
|
}
|
||||||
|
{{/jackson}}
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
@{{javaxPackage}}.annotation.Generated(value = "{{generatorClass}}"{{^hideGenerationTimestamp}}, date = "{{generatedDate}}"{{/hideGenerationTimestamp}}, comments = "Generator version: {{generatorVersion}}")
|
||||||
21
src/main/resources/openapi-templates/model.mustache
Normal file
21
src/main/resources/openapi-templates/model.mustache
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package {{package}};
|
||||||
|
|
||||||
|
{{#imports}}import {{import}};
|
||||||
|
{{/imports}}
|
||||||
|
{{#serializableModel}}
|
||||||
|
import java.io.Serializable;
|
||||||
|
{{/serializableModel}}
|
||||||
|
{{#useBeanValidation}}
|
||||||
|
import {{javaxPackage}}.validation.constraints.*;
|
||||||
|
import {{javaxPackage}}.validation.Valid;
|
||||||
|
{{/useBeanValidation}}
|
||||||
|
|
||||||
|
{{#models}}
|
||||||
|
{{#model}}
|
||||||
|
{{#isEnum}}
|
||||||
|
{{>enumOuterClass}}
|
||||||
|
|
||||||
|
{{/isEnum}}
|
||||||
|
{{^isEnum}}{{>pojo}}{{/isEnum}}
|
||||||
|
{{/model}}
|
||||||
|
{{/models}}
|
||||||
289
src/main/resources/openapi-templates/pojo.mustache
Normal file
289
src/main/resources/openapi-templates/pojo.mustache
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
{{#useSwaggerAnnotations}}
|
||||||
|
import io.swagger.annotations.*;
|
||||||
|
{{/useSwaggerAnnotations}}
|
||||||
|
{{#useSwaggerV3Annotations}}
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
{{/useSwaggerV3Annotations}}
|
||||||
|
import java.util.Objects;
|
||||||
|
{{#jackson}}
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||||
|
{{#additionalProperties}}
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonAnySetter;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonAnyGetter;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
{{/additionalProperties}}
|
||||||
|
{{/jackson}}
|
||||||
|
{{#openApiNullable}}
|
||||||
|
import org.openapitools.jackson.nullable.JsonNullable;
|
||||||
|
{{/openApiNullable}}
|
||||||
|
{{#withXml}}
|
||||||
|
import {{javaxPackage}}.xml.bind.annotation.XmlElement;
|
||||||
|
import {{javaxPackage}}.xml.bind.annotation.XmlRootElement;
|
||||||
|
import {{javaxPackage}}.xml.bind.annotation.XmlAccessType;
|
||||||
|
import {{javaxPackage}}.xml.bind.annotation.XmlAccessorType;
|
||||||
|
import {{javaxPackage}}.xml.bind.annotation.XmlType;
|
||||||
|
import {{javaxPackage}}.xml.bind.annotation.XmlEnum;
|
||||||
|
import {{javaxPackage}}.xml.bind.annotation.XmlEnumValue;
|
||||||
|
{{/withXml}}
|
||||||
|
|
||||||
|
{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{#description}}/**
|
||||||
|
* {{.}}
|
||||||
|
**/{{/description}}
|
||||||
|
{{#useSwaggerAnnotations}}{{#description}}@ApiModel(description = "{{{.}}}"){{/description}}{{/useSwaggerAnnotations}}{{#useSwaggerV3Annotations}}
|
||||||
|
@Schema({{#title}}title="{{{.}}}", {{/title}}{{#description}}description="{{{.}}}"{{/description}}{{^description}}description=""{{/description}}){{/useSwaggerV3Annotations}}{{#useMicroProfileOpenAPIAnnotations}}
|
||||||
|
@org.eclipse.microprofile.openapi.annotations.media.Schema({{#title}}title="{{{.}}}", {{/title}}{{#description}}description="{{{.}}}"{{/description}}{{^description}}description=""{{/description}}){{/useMicroProfileOpenAPIAnnotations}}
|
||||||
|
{{#jackson}}
|
||||||
|
@JsonTypeName("{{name}}")
|
||||||
|
{{#additionalProperties}}
|
||||||
|
@JsonFormat(shape=JsonFormat.Shape.OBJECT)
|
||||||
|
{{/additionalProperties}}
|
||||||
|
{{/jackson}}
|
||||||
|
{{>generatedAnnotation}}{{>additionalModelTypeAnnotations}}{{>xmlPojoAnnotation}}
|
||||||
|
{{#vendorExtensions.x-class-extra-annotation}}
|
||||||
|
{{{vendorExtensions.x-class-extra-annotation}}}
|
||||||
|
{{/vendorExtensions.x-class-extra-annotation}}
|
||||||
|
public class {{classname}} {{#parent}}extends {{{.}}}{{/parent}} {{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.x-implements}} {
|
||||||
|
{{#vars}}
|
||||||
|
{{#isEnum}}
|
||||||
|
{{^isContainer}}
|
||||||
|
{{>enumClass}}{{! prevent indent}}
|
||||||
|
{{/isContainer}}
|
||||||
|
{{#isContainer}}
|
||||||
|
{{#mostInnerItems}}
|
||||||
|
{{>enumClass}}{{! prevent indent}}
|
||||||
|
{{/mostInnerItems}}
|
||||||
|
{{/isContainer}}
|
||||||
|
{{/isEnum}}
|
||||||
|
{{#vendorExtensions.x-field-extra-annotation}}
|
||||||
|
{{{.}}}
|
||||||
|
{{/vendorExtensions.x-field-extra-annotation}}
|
||||||
|
{{#vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
{{#isContainer}}
|
||||||
|
private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined();
|
||||||
|
{{/isContainer}}
|
||||||
|
{{^isContainer}}
|
||||||
|
private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}};
|
||||||
|
{{/isContainer}}
|
||||||
|
{{/vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
{{^vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
private {{#useBeanValidation}}{{>beanValidatedType}}{{/useBeanValidation}}{{^useBeanValidation}}{{{datatypeWithEnum}}}{{/useBeanValidation}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
|
||||||
|
{{/vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
{{/vars}}
|
||||||
|
|
||||||
|
{{#generateBuilders}}
|
||||||
|
{{^additionalProperties}}
|
||||||
|
protected {{classname}}({{classname}}Builder b) {
|
||||||
|
{{#parent}}
|
||||||
|
super(b);
|
||||||
|
{{/parent}}
|
||||||
|
{{#vars}}
|
||||||
|
this.{{name}} = b.{{name}};
|
||||||
|
{{/vars}}
|
||||||
|
}
|
||||||
|
|
||||||
|
{{/additionalProperties}}
|
||||||
|
{{/generateBuilders}}
|
||||||
|
public {{classname}}() {
|
||||||
|
}
|
||||||
|
|
||||||
|
{{#jackson}}
|
||||||
|
{{#generateJsonCreator}}
|
||||||
|
{{#hasRequired}}
|
||||||
|
@JsonCreator
|
||||||
|
public {{classname}}(
|
||||||
|
{{#requiredVars}}
|
||||||
|
@JsonProperty(required = {{required}}, value = "{{baseName}}") {{>beanValidatedType}} {{name}}{{^-last}},{{/-last}}
|
||||||
|
{{/requiredVars}}
|
||||||
|
) {
|
||||||
|
{{#parent}}
|
||||||
|
super(
|
||||||
|
{{#parentRequiredVars}}
|
||||||
|
{{name}}{{^-last}},{{/-last}}
|
||||||
|
{{/parentRequiredVars}}
|
||||||
|
);
|
||||||
|
{{/parent}}
|
||||||
|
{{#vars}}
|
||||||
|
{{#required}}
|
||||||
|
this.{{name}} = {{name}};
|
||||||
|
{{/required}}
|
||||||
|
{{/vars}}
|
||||||
|
}
|
||||||
|
|
||||||
|
{{/hasRequired}}
|
||||||
|
{{/generateJsonCreator}}
|
||||||
|
{{/jackson}}
|
||||||
|
{{#vars}}
|
||||||
|
/**
|
||||||
|
{{#description}}
|
||||||
|
* {{.}}
|
||||||
|
{{/description}}
|
||||||
|
{{#minimum}}
|
||||||
|
* minimum: {{.}}
|
||||||
|
{{/minimum}}
|
||||||
|
{{#maximum}}
|
||||||
|
* maximum: {{.}}
|
||||||
|
{{/maximum}}
|
||||||
|
**/
|
||||||
|
public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) {
|
||||||
|
{{#vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});
|
||||||
|
{{/vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
{{^vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
this.{{name}} = {{name}};
|
||||||
|
{{/vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
{{#withXml}}
|
||||||
|
@XmlElement(name="{{baseName}}"{{#required}}, required = {{required}}{{/required}})
|
||||||
|
{{/withXml}}
|
||||||
|
{{#vendorExtensions.x-extra-annotation}}{{{vendorExtensions.x-extra-annotation}}}{{/vendorExtensions.x-extra-annotation}}{{#useSwaggerAnnotations}}
|
||||||
|
@ApiModelProperty({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}"){{/useSwaggerAnnotations}}{{#useSwaggerV3Annotations}}
|
||||||
|
@Schema({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}description = "{{{description}}}"){{/useSwaggerV3Annotations}}{{#useMicroProfileOpenAPIAnnotations}}
|
||||||
|
@org.eclipse.microprofile.openapi.annotations.media.Schema({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}description = "{{{description}}}"){{/useMicroProfileOpenAPIAnnotations}}
|
||||||
|
{{#jackson}}@JsonProperty({{#required}}required = {{required}}, value = {{/required}}"{{baseName}}"){{/jackson}}
|
||||||
|
{{#vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
public JsonNullable<{{{datatypeWithEnum}}}> {{getter}}() {
|
||||||
|
return {{name}};
|
||||||
|
}
|
||||||
|
{{/vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
{{^vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}}public {{>beanValidatedType}} {{getter}}() {
|
||||||
|
return {{name}};
|
||||||
|
}
|
||||||
|
{{/vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
|
||||||
|
{{#jackson}}
|
||||||
|
@JsonProperty({{#required}}required = {{required}}, value = {{/required}}"{{baseName}}")
|
||||||
|
{{/jackson}}
|
||||||
|
{{#vendorExtensions.x-setter-extra-annotation}}{{{vendorExtensions.x-setter-extra-annotation}}}
|
||||||
|
{{/vendorExtensions.x-setter-extra-annotation}}public void {{setter}}({{{datatypeWithEnum}}} {{name}}) {
|
||||||
|
{{#vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});
|
||||||
|
{{/vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
{{^vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
this.{{name}} = {{name}};
|
||||||
|
{{/vendorExtensions.x-is-jackson-optional-nullable}}
|
||||||
|
}
|
||||||
|
|
||||||
|
{{#isArray}}
|
||||||
|
public {{classname}} add{{nameInPascalCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) {
|
||||||
|
if (this.{{name}} == null) {
|
||||||
|
this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new {{#uniqueItems}}LinkedHashSet{{/uniqueItems}}{{^uniqueItems}}ArrayList{{/uniqueItems}}<>(){{/defaultValue}};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.{{name}}.add({{name}}Item);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public {{classname}} remove{{nameInPascalCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) {
|
||||||
|
if ({{name}}Item != null && this.{{name}} != null) {
|
||||||
|
this.{{name}}.remove({{name}}Item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
{{/isArray}}
|
||||||
|
{{#isMap}}
|
||||||
|
public {{classname}} put{{nameInPascalCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) {
|
||||||
|
if (this.{{name}} == null) {
|
||||||
|
this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new HashMap<>(){{/defaultValue}};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.{{name}}.put(key, {{name}}Item);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public {{classname}} remove{{nameInPascalCase}}Item(String key) {
|
||||||
|
if (this.{{name}} != null) {
|
||||||
|
this.{{name}}.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
{{/isMap}}
|
||||||
|
{{/vars}}
|
||||||
|
{{>additional_properties}}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}{{#hasVars}}
|
||||||
|
{{classname}} {{classVarName}} = ({{classname}}) o;
|
||||||
|
return {{#vars}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{^-last}} &&
|
||||||
|
{{/-last}}{{/vars}}{{#parent}} &&
|
||||||
|
super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}}
|
||||||
|
return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash({{#vars}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("class {{classname}} {\n");
|
||||||
|
{{#parent}}sb.append(" ").append(toIndentedString(super.toString())).append("\n");{{/parent}}
|
||||||
|
{{#vars}}sb.append(" {{name}}: ").append({{#isPassword}}"*"{{/isPassword}}{{^isPassword}}toIndentedString({{name}}){{/isPassword}}).append("\n");
|
||||||
|
{{/vars}}sb.append("}");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given object to string with each line indented by 4 spaces
|
||||||
|
* (except the first line).
|
||||||
|
*/
|
||||||
|
private String toIndentedString(Object o) {
|
||||||
|
if (o == null) {
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
return o.toString().replace("\n", "\n ");
|
||||||
|
}
|
||||||
|
|
||||||
|
{{#generateBuilders}}{{^additionalProperties}}
|
||||||
|
public static {{classname}}Builder builder() {
|
||||||
|
return new {{classname}}BuilderImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class {{classname}}BuilderImpl extends {{classname}}Builder<{{classname}}, {{classname}}BuilderImpl> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected {{classname}}BuilderImpl self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public {{classname}} build() {
|
||||||
|
return new {{classname}}(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static abstract class {{classname}}Builder > {{#parent}}extends {{{.}}}Builder {{/parent}} {
|
||||||
|
{{#vars}}
|
||||||
|
private {{#removeAnnotations}}{{{datatypeWithEnum}}}{{/removeAnnotations}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
|
||||||
|
{{/vars}}
|
||||||
|
{{^parent}}
|
||||||
|
protected abstract B self();
|
||||||
|
|
||||||
|
public abstract C build();
|
||||||
|
{{/parent}}
|
||||||
|
|
||||||
|
{{#vars}}
|
||||||
|
public B {{name}}({{#removeAnnotations}}{{{datatypeWithEnum}}}{{/removeAnnotations}} {{name}}) {
|
||||||
|
this.{{name}} = {{name}};
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
{{/vars}}
|
||||||
|
}{{/additionalProperties}}{{/generateBuilders}}
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
{{#jackson}}
|
||||||
|
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "{{{discriminator.propertyBaseName}}}", visible = true)
|
||||||
|
@JsonSubTypes({
|
||||||
|
{{#discriminator.mappedModels}}
|
||||||
|
@JsonSubTypes.Type(value = {{modelName}}.class, name = "{{^vendorExtensions.x-discriminator-value}}{{mappingName}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}"),
|
||||||
|
{{/discriminator.mappedModels}}
|
||||||
|
})
|
||||||
|
{{/jackson}}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
{{#withXml}}
|
||||||
|
@XmlAccessorType(XmlAccessType.FIELD)
|
||||||
|
{{#hasVars}} @XmlType(name = "{{classname}}", propOrder =
|
||||||
|
{ {{#vars}}"{{name}}"{{^-last}}, {{/-last}}{{/vars}}
|
||||||
|
}){{/hasVars}}
|
||||||
|
{{^hasVars}}@XmlType(name = "{{classname}}"){{/hasVars}}
|
||||||
|
{{^parent}}@XmlRootElement(name="{{classname}}"){{/parent}}
|
||||||
|
{{/withXml}}
|
||||||
@ -36,11 +36,13 @@ import type {
|
|||||||
CreateSessionRequest,
|
CreateSessionRequest,
|
||||||
ModelInfo,
|
ModelInfo,
|
||||||
ScenarioSetup,
|
ScenarioSetup,
|
||||||
|
ScenarioSummary,
|
||||||
} from '../api/generated/index'
|
} from '../api/generated/index'
|
||||||
import {
|
import {
|
||||||
Configuration,
|
Configuration,
|
||||||
CreateSessionRequestSafetyLevelEnum,
|
CreateSessionRequestSafetyLevelEnum,
|
||||||
ModelsApi,
|
ModelsApi,
|
||||||
|
ScenariosApi,
|
||||||
SessionsApi,
|
SessionsApi,
|
||||||
} from '../api/generated/index'
|
} from '../api/generated/index'
|
||||||
|
|
||||||
@ -49,6 +51,7 @@ const API_BASE = '/api/v1'
|
|||||||
|
|
||||||
const modelsApi = new ModelsApi(new Configuration({basePath: API_BASE}))
|
const modelsApi = new ModelsApi(new Configuration({basePath: API_BASE}))
|
||||||
const sessionsApi = new SessionsApi(new Configuration({basePath: API_BASE}))
|
const sessionsApi = new SessionsApi(new Configuration({basePath: API_BASE}))
|
||||||
|
const scenariosApi = new ScenariosApi(new Configuration({basePath: API_BASE}))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Landing page where the user selects an Ollama model and optional settings
|
* Landing page where the user selects an Ollama model and optional settings
|
||||||
@ -64,6 +67,9 @@ export default function StartPage() {
|
|||||||
const [starting, setStarting] = useState<boolean>(false)
|
const [starting, setStarting] = useState<boolean>(false)
|
||||||
const [error, setError] = useState<string | null>(null)
|
const [error, setError] = useState<string | null>(null)
|
||||||
|
|
||||||
|
/** Saved scenarios from API; selectedScenarioId is '' for custom or a UUID. */
|
||||||
|
const [scenarios, setScenarios] = useState<ScenarioSummary[]>([])
|
||||||
|
const [selectedScenarioId, setSelectedScenarioId] = useState<string>('')
|
||||||
/** Optional scenario (collapsible). */
|
/** Optional scenario (collapsible). */
|
||||||
const [scenarioExpanded, setScenarioExpanded] = useState<boolean>(false)
|
const [scenarioExpanded, setScenarioExpanded] = useState<boolean>(false)
|
||||||
const [setting, setSetting] = useState<string>('')
|
const [setting, setSetting] = useState<string>('')
|
||||||
@ -77,14 +83,18 @@ export default function StartPage() {
|
|||||||
draft: CharacterDefinition
|
draft: CharacterDefinition
|
||||||
} | null>(null)
|
} | null>(null)
|
||||||
|
|
||||||
/** Load available models on mount. */
|
/** Load available models and saved scenarios on mount. */
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
modelsApi.listModels()
|
Promise.all([
|
||||||
.then((resp) => {
|
modelsApi.listModels(),
|
||||||
setModels(resp.models ?? [])
|
scenariosApi.listScenarios().catch(() => ({scenarios: []})),
|
||||||
if (resp.models && resp.models.length > 0) {
|
])
|
||||||
setSelectedModel(resp.models[0].name)
|
.then(([modelsResp, scenariosResp]) => {
|
||||||
|
setModels(modelsResp.models ?? [])
|
||||||
|
if (modelsResp.models && modelsResp.models.length > 0) {
|
||||||
|
setSelectedModel(modelsResp.models[0].name)
|
||||||
}
|
}
|
||||||
|
setScenarios(scenariosResp.scenarios ?? [])
|
||||||
})
|
})
|
||||||
.catch(() => setError('Could not load models. Is the Quarkus server running?'))
|
.catch(() => setError('Could not load models. Is the Quarkus server running?'))
|
||||||
.finally(() => setLoading(false))
|
.finally(() => setLoading(false))
|
||||||
@ -94,6 +104,22 @@ export default function StartPage() {
|
|||||||
setSelectedModel(event.target.value)
|
setSelectedModel(event.target.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** When user selects a saved scenario, load its full setup and prefill the form. */
|
||||||
|
const handleScenarioSelect = async (event: SelectChangeEvent<string>) => {
|
||||||
|
const id = event.target.value
|
||||||
|
setSelectedScenarioId(id)
|
||||||
|
if (!id) return
|
||||||
|
try {
|
||||||
|
const setup = await scenariosApi.getScenario({scenarioId: id})
|
||||||
|
setSetting(setup.setting ?? '')
|
||||||
|
setInitialConflict(setup.initialConflict ?? '')
|
||||||
|
setUserCharacter(setup.userCharacter ?? null)
|
||||||
|
setAiCharacters(setup.aiCharacters ?? [])
|
||||||
|
} catch {
|
||||||
|
setError('Could not load scenario.')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Build scenario from form state if any field is filled. */
|
/** Build scenario from form state if any field is filled. */
|
||||||
const buildScenario = (): ScenarioSetup | undefined => {
|
const buildScenario = (): ScenarioSetup | undefined => {
|
||||||
const hasSetting = setting.trim() !== ''
|
const hasSetting = setting.trim() !== ''
|
||||||
@ -166,7 +192,8 @@ export default function StartPage() {
|
|||||||
model: selectedModel,
|
model: selectedModel,
|
||||||
language,
|
language,
|
||||||
safetyLevel: CreateSessionRequestSafetyLevelEnum.standard,
|
safetyLevel: CreateSessionRequestSafetyLevelEnum.standard,
|
||||||
scenario: buildScenario(),
|
scenarioId: selectedScenarioId || undefined,
|
||||||
|
scenario: selectedScenarioId ? undefined : buildScenario(),
|
||||||
}
|
}
|
||||||
const session = await sessionsApi.createSession({createSessionRequest: request})
|
const session = await sessionsApi.createSession({createSessionRequest: request})
|
||||||
navigate(`/session/${session.sessionId}`)
|
navigate(`/session/${session.sessionId}`)
|
||||||
@ -229,6 +256,25 @@ export default function StartPage() {
|
|||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<FormControl fullWidth disabled={starting} sx={{mb: 1}}>
|
||||||
|
<InputLabel id="scenario-label">Saved scenario</InputLabel>
|
||||||
|
<Select
|
||||||
|
labelId="scenario-label"
|
||||||
|
value={selectedScenarioId}
|
||||||
|
label="Saved scenario"
|
||||||
|
onChange={handleScenarioSelect}
|
||||||
|
>
|
||||||
|
<MenuItem value="">
|
||||||
|
<em>Custom (none)</em>
|
||||||
|
</MenuItem>
|
||||||
|
{scenarios.map((s) => (
|
||||||
|
<MenuItem key={s.id} value={s.id}>
|
||||||
|
{s.name}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
<Accordion
|
<Accordion
|
||||||
expanded={scenarioExpanded}
|
expanded={scenarioExpanded}
|
||||||
onChange={() => setScenarioExpanded((b) => !b)}
|
onChange={() => setScenarioExpanded((b) => !b)}
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
@ -39,18 +40,21 @@ class InMemorySessionServiceTest {
|
|||||||
@Mock
|
@Mock
|
||||||
private OllamaClient ollamaClient;
|
private OllamaClient ollamaClient;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private ScenarioService scenarioService;
|
||||||
|
|
||||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
private InMemorySessionService sessionService;
|
private InMemorySessionService sessionService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a fresh service instance with mocked Ollama client before each test.
|
* Creates a fresh service instance with mocked Ollama client and scenario service before each test.
|
||||||
* By default, Ollama is stubbed to return a short narrative and an empty
|
* By default, Ollama is stubbed to return a short narrative and an empty
|
||||||
* state update so that createSession (with scenario) and submitTurn complete.
|
* state update so that createSession (with scenario) and submitTurn complete.
|
||||||
*/
|
*/
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setUp() {
|
void setUp() {
|
||||||
sessionService = new InMemorySessionService(ollamaClient, objectMapper);
|
sessionService = new InMemorySessionService(ollamaClient, objectMapper, scenarioService);
|
||||||
StateUpdateResponse emptyUpdate = StateUpdateResponse.builder()
|
StateUpdateResponse emptyUpdate = StateUpdateResponse.builder()
|
||||||
.responses(null)
|
.responses(null)
|
||||||
.updatedSituation(null)
|
.updatedSituation(null)
|
||||||
@ -238,6 +242,42 @@ class InMemorySessionServiceTest {
|
|||||||
assertEquals("Old Sage", aiState.getName());
|
assertEquals("Old Sage", aiState.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that creating a session with scenarioId uses the scenario loaded from the database.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void createSessionWithScenarioIdUsesScenarioFromDatabase() {
|
||||||
|
UUID scenarioId = UUID.fromString("22222222-2222-2222-2222-222222222201");
|
||||||
|
CharacterDefinition userChar = new CharacterDefinition("db_user", "DB User", "protagonist");
|
||||||
|
CharacterDefinition aiChar = new CharacterDefinition("db_ai", "DB NPC", "antagonist");
|
||||||
|
ScenarioSetup loadedScenario = new ScenarioSetup();
|
||||||
|
loadedScenario.setSetting("Database setting");
|
||||||
|
loadedScenario.setInitialConflict("Database conflict");
|
||||||
|
loadedScenario.setUserCharacter(userChar);
|
||||||
|
loadedScenario.setAiCharacters(List.of(aiChar));
|
||||||
|
when(scenarioService.getScenarioAsSetup(scenarioId)).thenReturn(Optional.of(loadedScenario));
|
||||||
|
|
||||||
|
CreateSessionRequest request = new CreateSessionRequest("llama3:latest");
|
||||||
|
request.setScenarioId(scenarioId);
|
||||||
|
request.setScenario(null);
|
||||||
|
|
||||||
|
SessionResponse response = sessionService.createSession(request);
|
||||||
|
|
||||||
|
assertNotNull(response.getSituation());
|
||||||
|
assertEquals("Database setting", response.getSituation().getSetting());
|
||||||
|
assertNotNull(response.getCharacters());
|
||||||
|
assertEquals(2, response.getCharacters().size());
|
||||||
|
CharacterState userState = response.getCharacters().stream()
|
||||||
|
.filter(c -> Boolean.TRUE.equals(c.getIsUserCharacter()))
|
||||||
|
.findFirst().orElseThrow();
|
||||||
|
assertEquals("db_user", userState.getId());
|
||||||
|
assertEquals("DB User", userState.getName());
|
||||||
|
CharacterState aiState = response.getCharacters().stream()
|
||||||
|
.filter(c -> Boolean.FALSE.equals(c.getIsUserCharacter()))
|
||||||
|
.findFirst().orElseThrow();
|
||||||
|
assertEquals("db_ai", aiState.getId());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verifies that updateSession updates situation and characters when provided.
|
* Verifies that updateSession updates situation and characters when provided.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -0,0 +1,127 @@
|
|||||||
|
package de.neitzel.roleplay.business;
|
||||||
|
|
||||||
|
import de.neitzel.roleplay.data.CharacterEntity;
|
||||||
|
import de.neitzel.roleplay.data.ScenarioCharacterEntity;
|
||||||
|
import de.neitzel.roleplay.data.ScenarioEntity;
|
||||||
|
import de.neitzel.roleplay.data.ScenarioRepository;
|
||||||
|
import de.neitzel.roleplay.fascade.model.ScenarioSetup;
|
||||||
|
import de.neitzel.roleplay.fascade.model.ScenarioSummary;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for {@link ScenarioService}.
|
||||||
|
*/
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
class ScenarioServiceTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private ScenarioRepository scenarioRepository;
|
||||||
|
|
||||||
|
private ScenarioService scenarioService;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
scenarioService = new ScenarioService(scenarioRepository);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void listScenariosReturnsMappedSummaries() {
|
||||||
|
ScenarioEntity entity = new ScenarioEntity();
|
||||||
|
entity.setId(UUID.fromString("22222222-2222-2222-2222-222222222201"));
|
||||||
|
entity.setName("Harbour mystery");
|
||||||
|
entity.setSetting("A fog-covered harbour");
|
||||||
|
entity.setInitialConflict("Strange noises");
|
||||||
|
when(scenarioRepository.listAll()).thenReturn(List.of(entity));
|
||||||
|
|
||||||
|
List<ScenarioSummary> result = scenarioService.listScenarios();
|
||||||
|
|
||||||
|
assertEquals(1, result.size());
|
||||||
|
ScenarioSummary summary = result.get(0);
|
||||||
|
assertEquals(UUID.fromString("22222222-2222-2222-2222-222222222201"), summary.getId());
|
||||||
|
assertEquals("Harbour mystery", summary.getName());
|
||||||
|
assertEquals("A fog-covered harbour", summary.getSetting());
|
||||||
|
assertEquals("Strange noises", summary.getInitialConflict());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void listScenariosReturnsEmptyWhenNoneStored() {
|
||||||
|
when(scenarioRepository.listAll()).thenReturn(List.of());
|
||||||
|
|
||||||
|
List<ScenarioSummary> result = scenarioService.listScenarios();
|
||||||
|
|
||||||
|
assertTrue(result.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getScenarioAsSetupReturnsEmptyWhenNotFound() {
|
||||||
|
UUID id = UUID.randomUUID();
|
||||||
|
when(scenarioRepository.findByIdWithCharacters(id)).thenReturn(null);
|
||||||
|
|
||||||
|
Optional<ScenarioSetup> result = scenarioService.getScenarioAsSetup(id);
|
||||||
|
|
||||||
|
assertTrue(result.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getScenarioAsSetupReturnsSetupWithUserAndAiCharacters() {
|
||||||
|
UUID scenarioId = UUID.fromString("22222222-2222-2222-2222-222222222201");
|
||||||
|
UUID userCharId = UUID.fromString("11111111-1111-1111-1111-111111111101");
|
||||||
|
UUID aiCharId = UUID.fromString("11111111-1111-1111-1111-111111111102");
|
||||||
|
|
||||||
|
CharacterEntity userCharEntity = new CharacterEntity();
|
||||||
|
userCharEntity.setId(userCharId);
|
||||||
|
userCharEntity.setName("The Detective");
|
||||||
|
userCharEntity.setRole("detective");
|
||||||
|
|
||||||
|
CharacterEntity aiCharEntity = new CharacterEntity();
|
||||||
|
aiCharEntity.setId(aiCharId);
|
||||||
|
aiCharEntity.setName("Captain Morgan");
|
||||||
|
aiCharEntity.setRole("captain");
|
||||||
|
|
||||||
|
ScenarioCharacterEntity userLink = new ScenarioCharacterEntity();
|
||||||
|
userLink.setUserCharacter(true);
|
||||||
|
userLink.setPosition(0);
|
||||||
|
userLink.setCharacter(userCharEntity);
|
||||||
|
|
||||||
|
ScenarioCharacterEntity aiLink = new ScenarioCharacterEntity();
|
||||||
|
aiLink.setUserCharacter(false);
|
||||||
|
aiLink.setPosition(1);
|
||||||
|
aiLink.setCharacter(aiCharEntity);
|
||||||
|
|
||||||
|
ScenarioEntity scenarioEntity = new ScenarioEntity();
|
||||||
|
scenarioEntity.setId(scenarioId);
|
||||||
|
scenarioEntity.setName("Harbour mystery");
|
||||||
|
scenarioEntity.setSetting("A fog-covered harbour at dawn");
|
||||||
|
scenarioEntity.setInitialConflict("Strange noises from the cargo hold");
|
||||||
|
scenarioEntity.setScenarioCharacters(List.of(userLink, aiLink));
|
||||||
|
|
||||||
|
when(scenarioRepository.findByIdWithCharacters(scenarioId)).thenReturn(scenarioEntity);
|
||||||
|
|
||||||
|
Optional<ScenarioSetup> result = scenarioService.getScenarioAsSetup(scenarioId);
|
||||||
|
|
||||||
|
assertTrue(result.isPresent());
|
||||||
|
ScenarioSetup setup = result.get();
|
||||||
|
assertEquals("A fog-covered harbour at dawn", setup.getSetting());
|
||||||
|
assertEquals("Strange noises from the cargo hold", setup.getInitialConflict());
|
||||||
|
assertNotNull(setup.getUserCharacter());
|
||||||
|
assertEquals("The Detective", setup.getUserCharacter().getName());
|
||||||
|
assertEquals("detective", setup.getUserCharacter().getRole());
|
||||||
|
assertNotNull(setup.getAiCharacters());
|
||||||
|
assertEquals(1, setup.getAiCharacters().size());
|
||||||
|
assertEquals("Captain Morgan", setup.getAiCharacters().get(0).getName());
|
||||||
|
assertEquals("captain", setup.getAiCharacters().get(0).getRole());
|
||||||
|
}
|
||||||
|
}
|
||||||
216
tree.txt
Normal file
216
tree.txt
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
[INFO] Scanning for projects...
|
||||||
|
[INFO]
|
||||||
|
[INFO] ------------------------< de.neitzel:roleplay >-------------------------
|
||||||
|
[INFO] Building roleplay 0.1.0-SNAPSHOT
|
||||||
|
[INFO] from pom.xml
|
||||||
|
[INFO] --------------------------------[ jar ]---------------------------------
|
||||||
|
[INFO]
|
||||||
|
[INFO] --- dependency:3.7.0:tree (default-cli) @ roleplay ---
|
||||||
|
[INFO] de.neitzel:roleplay:jar:0.1.0-SNAPSHOT
|
||||||
|
[INFO] +- io.quarkus:quarkus-arc:jar:3.31.1:compile
|
||||||
|
[INFO] | +- io.quarkus.arc:arc:jar:3.31.1:compile
|
||||||
|
[INFO] | | +- jakarta.enterprise:jakarta.enterprise.cdi-api:jar:4.1.0:compile
|
||||||
|
[INFO] | | | +- jakarta.enterprise:jakarta.enterprise.lang-model:jar:4.1.0:compile
|
||||||
|
[INFO] | | | \- jakarta.interceptor:jakarta.interceptor-api:jar:2.2.0:compile
|
||||||
|
[INFO] | | +- jakarta.annotation:jakarta.annotation-api:jar:3.0.0:compile
|
||||||
|
[INFO] | | +- jakarta.transaction:jakarta.transaction-api:jar:2.0.1:compile
|
||||||
|
[INFO] | | +- io.smallrye.reactive:mutiny:jar:3.1.0:compile
|
||||||
|
[INFO] | | | +- io.smallrye.common:smallrye-common-annotation:jar:2.15.0:compile
|
||||||
|
[INFO] | | | \- org.jctools:jctools-core:jar:4.0.5:compile
|
||||||
|
[INFO] | | \- org.jboss.logging:jboss-logging:jar:3.6.2.Final:compile
|
||||||
|
[INFO] | +- io.quarkus:quarkus-core:jar:3.31.1:compile
|
||||||
|
[INFO] | | +- jakarta.inject:jakarta.inject-api:jar:2.0.1:compile
|
||||||
|
[INFO] | | +- io.smallrye.common:smallrye-common-os:jar:2.15.0:compile
|
||||||
|
[INFO] | | +- io.quarkus:quarkus-ide-launcher:jar:3.31.1:compile
|
||||||
|
[INFO] | | +- io.quarkus:quarkus-development-mode-spi:jar:3.31.1:compile
|
||||||
|
[INFO] | | +- io.smallrye.config:smallrye-config:jar:3.15.1:compile
|
||||||
|
[INFO] | | | \- io.smallrye.config:smallrye-config-core:jar:3.15.1:compile
|
||||||
|
[INFO] | | +- org.jboss.logmanager:jboss-logmanager:jar:3.2.0.Final:compile
|
||||||
|
[INFO] | | | +- io.smallrye.common:smallrye-common-cpu:jar:2.15.0:compile
|
||||||
|
[INFO] | | | +- io.smallrye.common:smallrye-common-expression:jar:2.15.0:compile
|
||||||
|
[INFO] | | | +- io.smallrye.common:smallrye-common-net:jar:2.15.0:compile
|
||||||
|
[INFO] | | | +- io.smallrye.common:smallrye-common-ref:jar:2.15.0:compile
|
||||||
|
[INFO] | | | \- jakarta.json:jakarta.json-api:jar:2.1.3:compile
|
||||||
|
[INFO] | | +- org.jboss.threads:jboss-threads:jar:3.9.2:compile
|
||||||
|
[INFO] | | | \- io.smallrye.common:smallrye-common-function:jar:2.15.0:compile
|
||||||
|
[INFO] | | +- org.slf4j:slf4j-api:jar:2.0.17:compile
|
||||||
|
[INFO] | | +- org.jboss.slf4j:slf4j-jboss-logmanager:jar:2.0.2.Final:compile
|
||||||
|
[INFO] | | +- org.wildfly.common:wildfly-common:jar:2.0.1:compile
|
||||||
|
[INFO] | | +- io.quarkus:quarkus-registry:jar:3.31.1:compile
|
||||||
|
[INFO] | | +- io.quarkus:quarkus-bootstrap-runner:jar:3.31.1:compile
|
||||||
|
[INFO] | | | +- io.quarkus:quarkus-classloader-commons:jar:3.31.1:compile
|
||||||
|
[INFO] | | | \- io.smallrye.common:smallrye-common-io:jar:2.15.0:compile
|
||||||
|
[INFO] | | \- io.quarkus:quarkus-fs-util:jar:1.3.0:compile
|
||||||
|
[INFO] | \- org.eclipse.microprofile.context-propagation:microprofile-context-propagation-api:jar:1.3:compile
|
||||||
|
[INFO] +- io.quarkus:quarkus-rest:jar:3.31.1:compile
|
||||||
|
[INFO] | +- io.quarkus:quarkus-rest-common:jar:3.31.1:compile
|
||||||
|
[INFO] | | +- io.quarkus.resteasy.reactive:resteasy-reactive-common:jar:3.31.1:compile
|
||||||
|
[INFO] | | | +- io.quarkus.resteasy.reactive:resteasy-reactive-common-types:jar:3.31.1:compile
|
||||||
|
[INFO] | | | \- org.reactivestreams:reactive-streams:jar:1.0.4:compile
|
||||||
|
[INFO] | | +- io.quarkus:quarkus-mutiny:jar:3.31.1:compile
|
||||||
|
[INFO] | | | +- io.quarkus:quarkus-smallrye-context-propagation:jar:3.31.1:compile
|
||||||
|
[INFO] | | | | \- io.smallrye:smallrye-context-propagation:jar:2.3.0:compile
|
||||||
|
[INFO] | | | | +- io.smallrye:smallrye-context-propagation-api:jar:2.3.0:compile
|
||||||
|
[INFO] | | | | \- io.smallrye:smallrye-context-propagation-storage:jar:2.3.0:compile
|
||||||
|
[INFO] | | | \- io.smallrye.reactive:mutiny-smallrye-context-propagation:jar:3.1.0:compile
|
||||||
|
[INFO] | | \- io.quarkus:quarkus-vertx:jar:3.31.1:compile
|
||||||
|
[INFO] | | +- io.quarkus:quarkus-netty:jar:3.31.1:compile
|
||||||
|
[INFO] | | | \- io.netty:netty-codec:jar:4.1.130.Final:compile
|
||||||
|
[INFO] | | +- io.netty:netty-codec-haproxy:jar:4.1.130.Final:compile
|
||||||
|
[INFO] | | +- io.quarkus:quarkus-vertx-latebound-mdc-provider:jar:3.31.1:compile
|
||||||
|
[INFO] | | \- io.smallrye:smallrye-fault-tolerance-vertx:jar:6.10.0:compile
|
||||||
|
[INFO] | +- io.quarkus.resteasy.reactive:resteasy-reactive-vertx:jar:3.31.1:compile
|
||||||
|
[INFO] | | +- io.vertx:vertx-web:jar:4.5.24:compile
|
||||||
|
[INFO] | | | +- io.vertx:vertx-web-common:jar:4.5.24:compile
|
||||||
|
[INFO] | | | +- io.vertx:vertx-auth-common:jar:4.5.24:compile
|
||||||
|
[INFO] | | | \- io.vertx:vertx-bridge-common:jar:4.5.24:compile
|
||||||
|
[INFO] | | +- io.smallrye.reactive:smallrye-mutiny-vertx-core:jar:3.21.4:compile
|
||||||
|
[INFO] | | | +- io.smallrye.reactive:smallrye-mutiny-vertx-runtime:jar:3.21.4:compile
|
||||||
|
[INFO] | | | \- io.smallrye.reactive:vertx-mutiny-generator:jar:3.21.4:compile
|
||||||
|
[INFO] | | | \- io.vertx:vertx-codegen:jar:4.5.24:compile
|
||||||
|
[INFO] | | +- io.quarkus.resteasy.reactive:resteasy-reactive:jar:3.31.1:compile
|
||||||
|
[INFO] | | +- io.quarkus.vertx.utils:quarkus-vertx-utils:jar:3.31.1:compile
|
||||||
|
[INFO] | | +- org.jboss.logging:commons-logging-jboss-logging:jar:1.0.0.Final:compile
|
||||||
|
[INFO] | | \- jakarta.xml.bind:jakarta.xml.bind-api:jar:4.0.4:compile
|
||||||
|
[INFO] | | \- jakarta.activation:jakarta.activation-api:jar:2.1.4:compile
|
||||||
|
[INFO] | +- io.quarkus:quarkus-vertx-http:jar:3.31.1:compile
|
||||||
|
[INFO] | | +- io.quarkus:quarkus-security-runtime-spi:jar:3.31.1:compile
|
||||||
|
[INFO] | | +- io.quarkus:quarkus-tls-registry:jar:3.31.1:compile
|
||||||
|
[INFO] | | | +- io.quarkus:quarkus-tls-registry-spi:jar:3.31.1:compile
|
||||||
|
[INFO] | | | \- io.smallrye.certs:smallrye-private-key-pem-parser:jar:0.9.2:compile
|
||||||
|
[INFO] | | +- io.quarkus:quarkus-credentials:jar:3.31.1:compile
|
||||||
|
[INFO] | | +- io.smallrye.common:smallrye-common-vertx-context:jar:2.15.0:compile
|
||||||
|
[INFO] | | +- io.quarkus.security:quarkus-security:jar:2.3.2:compile
|
||||||
|
[INFO] | | +- io.smallrye.reactive:smallrye-mutiny-vertx-web:jar:3.21.4:compile
|
||||||
|
[INFO] | | | +- io.smallrye.reactive:smallrye-mutiny-vertx-web-common:jar:3.21.4:compile
|
||||||
|
[INFO] | | | +- io.smallrye.reactive:smallrye-mutiny-vertx-auth-common:jar:3.21.4:compile
|
||||||
|
[INFO] | | | +- io.smallrye.reactive:smallrye-mutiny-vertx-bridge-common:jar:3.21.4:compile
|
||||||
|
[INFO] | | | \- io.smallrye.reactive:smallrye-mutiny-vertx-uri-template:jar:3.21.4:compile
|
||||||
|
[INFO] | | | \- io.vertx:vertx-uri-template:jar:4.5.24:compile
|
||||||
|
[INFO] | | +- org.crac:crac:jar:1.5.0:compile
|
||||||
|
[INFO] | | \- com.aayushatharva.brotli4j:brotli4j:jar:1.16.0:compile
|
||||||
|
[INFO] | | +- com.aayushatharva.brotli4j:service:jar:1.16.0:compile
|
||||||
|
[INFO] | | \- com.aayushatharva.brotli4j:native-osx-aarch64:jar:1.16.0:compile
|
||||||
|
[INFO] | +- io.quarkus:quarkus-jsonp:jar:3.31.1:compile
|
||||||
|
[INFO] | | \- org.eclipse.parsson:parsson:jar:1.1.7:compile
|
||||||
|
[INFO] | \- io.quarkus:quarkus-virtual-threads:jar:3.31.1:compile
|
||||||
|
[INFO] | \- io.vertx:vertx-core:jar:4.5.24:compile
|
||||||
|
[INFO] | +- io.netty:netty-common:jar:4.1.130.Final:compile
|
||||||
|
[INFO] | +- io.netty:netty-buffer:jar:4.1.130.Final:compile
|
||||||
|
[INFO] | +- io.netty:netty-transport:jar:4.1.130.Final:compile
|
||||||
|
[INFO] | +- io.netty:netty-handler:jar:4.1.130.Final:compile
|
||||||
|
[INFO] | | \- io.netty:netty-transport-native-unix-common:jar:4.1.130.Final:compile
|
||||||
|
[INFO] | +- io.netty:netty-handler-proxy:jar:4.1.130.Final:compile
|
||||||
|
[INFO] | | \- io.netty:netty-codec-socks:jar:4.1.130.Final:compile
|
||||||
|
[INFO] | +- io.netty:netty-codec-http:jar:4.1.130.Final:compile
|
||||||
|
[INFO] | +- io.netty:netty-codec-http2:jar:4.1.130.Final:compile
|
||||||
|
[INFO] | +- io.netty:netty-resolver:jar:4.1.130.Final:compile
|
||||||
|
[INFO] | +- io.netty:netty-resolver-dns:jar:4.1.130.Final:compile
|
||||||
|
[INFO] | | \- io.netty:netty-codec-dns:jar:4.1.130.Final:compile
|
||||||
|
[INFO] | \- com.fasterxml.jackson.core:jackson-core:jar:2.20.1:compile
|
||||||
|
[INFO] +- io.quarkus:quarkus-rest-jackson:jar:3.31.1:compile
|
||||||
|
[INFO] | \- io.quarkus:quarkus-rest-jackson-common:jar:3.31.1:compile
|
||||||
|
[INFO] | \- io.quarkus:quarkus-jackson:jar:3.31.1:compile
|
||||||
|
[INFO] | +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.20.1:compile
|
||||||
|
[INFO] | +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.20.1:compile
|
||||||
|
[INFO] | \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.20.1:compile
|
||||||
|
[INFO] +- io.quarkus:quarkus-hibernate-validator:jar:3.31.1:compile
|
||||||
|
[INFO] | +- org.hibernate.validator:hibernate-validator:jar:9.1.0.Final:compile
|
||||||
|
[INFO] | | +- jakarta.validation:jakarta.validation-api:jar:3.1.1:compile
|
||||||
|
[INFO] | | \- com.fasterxml:classmate:jar:1.7.1:compile
|
||||||
|
[INFO] | +- org.glassfish.expressly:expressly:jar:6.0.0:compile
|
||||||
|
[INFO] | | \- jakarta.el:jakarta.el-api:jar:6.0.1:compile
|
||||||
|
[INFO] | +- io.smallrye.config:smallrye-config-validator:jar:3.15.1:compile
|
||||||
|
[INFO] | \- jakarta.ws.rs:jakarta.ws.rs-api:jar:3.1.0:compile
|
||||||
|
[INFO] +- io.quarkus:quarkus-config-yaml:jar:3.31.1:compile
|
||||||
|
[INFO] | +- io.smallrye.config:smallrye-config-source-yaml:jar:3.15.1:compile
|
||||||
|
[INFO] | | +- io.smallrye.config:smallrye-config-common:jar:3.15.1:compile
|
||||||
|
[INFO] | | | \- io.smallrye.common:smallrye-common-classloader:jar:2.15.0:compile
|
||||||
|
[INFO] | | \- io.smallrye.common:smallrye-common-constraint:jar:2.15.0:compile
|
||||||
|
[INFO] | \- org.eclipse.microprofile.config:microprofile-config-api:jar:3.1:compile
|
||||||
|
[INFO] +- io.quarkus:quarkus-jdbc-h2:jar:3.31.1:compile
|
||||||
|
[INFO] | +- com.h2database:h2:jar:2.4.240:compile
|
||||||
|
[INFO] | \- org.locationtech.jts:jts-core:jar:1.19.0:compile
|
||||||
|
[INFO] +- io.quarkus:quarkus-liquibase:jar:3.31.1:compile
|
||||||
|
[INFO] | +- io.quarkus:quarkus-liquibase-common:jar:3.31.1:compile
|
||||||
|
[INFO] | +- org.liquibase:liquibase-core:jar:4.33.0:compile
|
||||||
|
[INFO] | | +- com.opencsv:opencsv:jar:5.11.2:compile
|
||||||
|
[INFO] | | +- org.apache.commons:commons-collections4:jar:4.5.0:compile
|
||||||
|
[INFO] | | +- org.apache.commons:commons-text:jar:1.15.0:compile
|
||||||
|
[INFO] | | +- org.apache.commons:commons-lang3:jar:3.20.0:compile
|
||||||
|
[INFO] | | \- commons-io:commons-io:jar:2.21.0:compile
|
||||||
|
[INFO] | +- org.osgi:osgi.core:jar:6.0.0:compile
|
||||||
|
[INFO] | +- org.yaml:snakeyaml:jar:2.5:compile
|
||||||
|
[INFO] | +- io.quarkus:quarkus-jaxb:jar:3.31.1:compile
|
||||||
|
[INFO] | | +- io.quarkus:quarkus-jaxp:jar:3.31.1:compile
|
||||||
|
[INFO] | | \- org.glassfish.jaxb:jaxb-runtime:jar:4.0.6:compile
|
||||||
|
[INFO] | | \- org.glassfish.jaxb:jaxb-core:jar:4.0.6:compile
|
||||||
|
[INFO] | | +- org.eclipse.angus:angus-activation:jar:2.0.3:runtime
|
||||||
|
[INFO] | | +- org.glassfish.jaxb:txw2:jar:4.0.6:compile
|
||||||
|
[INFO] | | \- com.sun.istack:istack-commons-runtime:jar:4.1.2:compile
|
||||||
|
[INFO] | +- io.quarkus:quarkus-agroal:jar:3.31.1:compile
|
||||||
|
[INFO] | | +- io.quarkus:quarkus-datasource:jar:3.31.1:compile
|
||||||
|
[INFO] | | +- io.agroal:agroal-api:jar:2.8:compile
|
||||||
|
[INFO] | | +- io.agroal:agroal-narayana:jar:2.8:compile
|
||||||
|
[INFO] | | | \- org.jboss:jboss-transaction-spi:jar:8.0.0.Final:compile
|
||||||
|
[INFO] | | \- io.agroal:agroal-pool:jar:2.8:compile
|
||||||
|
[INFO] | +- io.quarkus:quarkus-datasource-common:jar:3.31.1:compile
|
||||||
|
[INFO] | \- io.quarkus:quarkus-narayana-jta:jar:3.31.1:compile
|
||||||
|
[INFO] | +- io.quarkus:quarkus-transaction-annotations:jar:3.31.1:compile
|
||||||
|
[INFO] | +- io.smallrye:smallrye-context-propagation-jta:jar:2.3.0:compile
|
||||||
|
[INFO] | +- io.smallrye.reactive:smallrye-reactive-converter-api:jar:3.0.3:compile
|
||||||
|
[INFO] | +- io.smallrye.reactive:smallrye-reactive-converter-mutiny:jar:3.0.3:compile
|
||||||
|
[INFO] | +- io.smallrye.reactive:mutiny-zero-flow-adapters:jar:1.1.1:compile
|
||||||
|
[INFO] | +- org.jboss.narayana.jta:narayana-jta:jar:7.3.3.Final:compile
|
||||||
|
[INFO] | | +- jakarta.resource:jakarta.resource-api:jar:2.1.0:compile
|
||||||
|
[INFO] | | +- org.jboss.invocation:jboss-invocation:jar:2.0.0.Final:compile
|
||||||
|
[INFO] | | \- org.eclipse.microprofile.reactive-streams-operators:microprofile-reactive-streams-operators-api:jar:3.0.1:compile
|
||||||
|
[INFO] | \- org.jboss.narayana.jts:narayana-jts-integration:jar:7.3.3.Final:compile
|
||||||
|
[INFO] +- io.quarkus:quarkus-hibernate-orm-panache:jar:3.31.1:compile
|
||||||
|
[INFO] | +- io.quarkus:quarkus-hibernate-orm:jar:3.31.1:compile
|
||||||
|
[INFO] | | +- org.hibernate.orm:hibernate-core:jar:7.2.1.Final:compile
|
||||||
|
[INFO] | | | +- org.hibernate.models:hibernate-models:jar:1.0.1:runtime
|
||||||
|
[INFO] | | | \- org.antlr:antlr4-runtime:jar:4.13.2:compile
|
||||||
|
[INFO] | | +- net.bytebuddy:byte-buddy:jar:1.17.8:compile
|
||||||
|
[INFO] | | +- org.hibernate.orm:hibernate-graalvm:jar:7.2.1.Final:compile
|
||||||
|
[INFO] | | +- jakarta.persistence:jakarta.persistence-api:jar:3.2.0:compile
|
||||||
|
[INFO] | | +- org.hibernate.local-cache:quarkus-local-cache:jar:0.5.0:compile
|
||||||
|
[INFO] | | \- io.quarkus:quarkus-caffeine:jar:3.31.1:compile
|
||||||
|
[INFO] | | \- com.github.ben-manes.caffeine:caffeine:jar:3.2.3:compile
|
||||||
|
[INFO] | | \- com.google.errorprone:error_prone_annotations:jar:2.46.0:compile
|
||||||
|
[INFO] | +- io.quarkus:quarkus-hibernate-orm-panache-common:jar:3.31.1:compile
|
||||||
|
[INFO] | | \- io.quarkus:quarkus-panache-hibernate-common:jar:3.31.1:compile
|
||||||
|
[INFO] | \- io.quarkus:quarkus-panache-common:jar:3.31.1:compile
|
||||||
|
[INFO] +- io.quarkus:quarkus-rest-client-config:jar:3.31.1:compile
|
||||||
|
[INFO] | +- io.quarkus:quarkus-proxy-registry:jar:3.31.1:compile
|
||||||
|
[INFO] | +- org.eclipse.microprofile.rest.client:microprofile-rest-client-api:jar:4.0:compile
|
||||||
|
[INFO] | \- io.smallrye:jandex:jar:3.5.3:compile
|
||||||
|
[INFO] +- io.quarkus:quarkus-rest-client-jackson:jar:3.31.1:compile
|
||||||
|
[INFO] | +- io.quarkus.resteasy.reactive:resteasy-reactive-jackson:jar:3.31.1:compile
|
||||||
|
[INFO] | | \- com.fasterxml.jackson.core:jackson-databind:jar:2.20.1:compile
|
||||||
|
[INFO] | | \- com.fasterxml.jackson.core:jackson-annotations:jar:2.20:compile
|
||||||
|
[INFO] | \- io.quarkus:quarkus-rest-client:jar:3.31.1:compile
|
||||||
|
[INFO] | \- io.quarkus:quarkus-rest-client-jaxrs:jar:3.31.1:compile
|
||||||
|
[INFO] | \- io.quarkus.resteasy.reactive:resteasy-reactive-client:jar:3.31.1:compile
|
||||||
|
[INFO] | +- io.smallrye.stork:stork-api:jar:2.7.3:compile
|
||||||
|
[INFO] | \- io.vertx:vertx-web-client:jar:4.5.24:compile
|
||||||
|
[INFO] +- org.projectlombok:lombok:jar:1.18.42:provided
|
||||||
|
[INFO] +- org.junit.jupiter:junit-jupiter:jar:5.10.3:test
|
||||||
|
[INFO] | +- org.junit.jupiter:junit-jupiter-api:jar:6.0.2:test
|
||||||
|
[INFO] | | +- org.opentest4j:opentest4j:jar:1.3.0:test
|
||||||
|
[INFO] | | +- org.junit.platform:junit-platform-commons:jar:6.0.2:test
|
||||||
|
[INFO] | | +- org.apiguardian:apiguardian-api:jar:1.1.2:test
|
||||||
|
[INFO] | | \- org.jspecify:jspecify:jar:1.0.0:compile
|
||||||
|
[INFO] | +- org.junit.jupiter:junit-jupiter-params:jar:6.0.2:test
|
||||||
|
[INFO] | \- org.junit.jupiter:junit-jupiter-engine:jar:6.0.2:test
|
||||||
|
[INFO] | \- org.junit.platform:junit-platform-engine:jar:6.0.2:test
|
||||||
|
[INFO] \- org.mockito:mockito-junit-jupiter:jar:5.12.0:test
|
||||||
|
[INFO] \- org.mockito:mockito-core:jar:5.21.0:test
|
||||||
|
[INFO] +- net.bytebuddy:byte-buddy-agent:jar:1.17.8:test
|
||||||
|
[INFO] \- org.objenesis:objenesis:jar:3.3:test
|
||||||
|
[INFO] ------------------------------------------------------------------------
|
||||||
|
[INFO] BUILD SUCCESS
|
||||||
|
[INFO] ------------------------------------------------------------------------
|
||||||
|
[INFO] Total time: 1.062 s
|
||||||
|
[INFO] Finished at: 2026-02-21T19:02:53+01:00
|
||||||
|
[INFO] ------------------------------------------------------------------------
|
||||||
Loading…
x
Reference in New Issue
Block a user