diff --git a/.gitignore b/.gitignore index 7a2f8e4..1931931 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,5 @@ couchdb-password.txt kontor-robyn/kontor.db kontor-robyn.bak kontor-robyn.bak2 +kontor-data/.gradle +kontor-data/build/ diff --git a/integration/build.gradle b/integration/build.gradle index 4b596ef..2c4f20c 100755 --- a/integration/build.gradle +++ b/integration/build.gradle @@ -2,6 +2,7 @@ plugins { id 'java' id 'org.springframework.boot' version '4.0.7' id 'io.spring.dependency-management' version '1.1.7' + alias(libs.plugins.lombok) } group = 'de.thpeetz.kontor' @@ -15,14 +16,31 @@ java { repositories { mavenCentral() + maven { setUrl("https://repo.spring.io/milestone") } +} + +dependencyManagement { + imports { + mavenBom libs.camel.bom.get().toString() + } } dependencies { implementation 'org.springframework.boot:spring-boot-starter-actuator' implementation 'org.springframework.boot:spring-boot-starter-artemis' implementation 'org.springframework.boot:spring-boot-starter-webmvc' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.apache.camel.springboot:camel-spring-boot-starter:4.20.0' + implementation 'org.apache.camel.springboot:camel-jms-starter' + implementation 'io.micrometer:micrometer-registry-prometheus' + implementation 'org.apache.activemq:artemis-jakarta-client' + implementation 'org.postgresql:postgresql' + implementation libs.jackson + implementation libs.gson runtimeOnly 'io.micrometer:micrometer-registry-prometheus' + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.apache.camel:camel-test-spring-junit5' testImplementation 'org.springframework.boot:spring-boot-starter-artemis-test' testImplementation 'org.springframework.boot:spring-boot-starter-webmvc-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' diff --git a/integration/gradle/libs.versions.toml b/integration/gradle/libs.versions.toml new file mode 100644 index 0000000..1f68ea3 --- /dev/null +++ b/integration/gradle/libs.versions.toml @@ -0,0 +1,72 @@ +[versions] +gradle = "8.6" +args4j = "2.33" +commonscli = "1.5.0" +junit = "5.8.2" +logback = "1.1.2" +mockito = "1.9.5" +picoli = "4.7.0" +slf4j = "1.7.22" +hsqldb = "2.7.1" +sqlite = "3.25.2" +spotbugs = "6.0.7" +asciidoctor = "4.0.2" +rouge = "3.15.0" +#diagram = "2.2.2" +diagram = "2.3.1" +sonarqube = "3.3" +cimtConventions = "1.0.0-SNAPSHOT" +springboot = "3.2.5" +springdependencies = "1.1.4" +vaadin = "24.3.8" +camel = "4.10.6" +artemis = "2.41.0" +lombok = "8.6" +gson = "2.9.0" +jackson = "2.16.1" +json_simple = "1.1.1" +mail = "1.6.2" +hypersistence = "3.9.10" + +[libraries] +args4j = { module = "args4j:args4j", version.ref = "args4j" } +commonscli = { module = "commons-cli:commons-cli", version.ref = "commonscli" } +junit = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" } +logbackCore = { module = "ch.qos.logback:logback-core", version.ref = "logback" } +logbackClassic = { module = "ch.qos.logback:logback-classic", version.ref = "logback" } +mockito = { module = "org.mockito:mockito-all", version.ref = "mockito" } +picocli = { module = "info.picocli:picocli", version.ref = "picoli" } +slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" } +hsqldb = { module = "org.hsqldb:hsqldb", version.ref = "hsqldb" } +gson = { module = "com.google.code.gson:gson", version.ref = "gson" } +jackson = { module = "com.fasterxml.jackson.core:jackson-databind", version.ref = "jackson" } +json = { module = "com.googlecode.json-simple:json-simple", version.ref ="json_simple" } +mail = { module = "com.sun.mail:javax.mail", version.ref ="mail" } +sqlite-jdbc = { module = "org.xerial:sqlite-jdbc", version.ref = "sqlite" } +hypersistence = { module = "io.hypersistence:hypersistence-utils-hibernate-63", version.ref = "hypersistence" } +vaadin-bom = { module = "com.vaadin:vaadin-bom", version.ref = "vaadin" } +camel-bom = { module = "org.apache.camel.springboot:camel-spring-boot-bom", version.ref = "camel"} +artemis = { module = "org.apache.activemq:artemis-jms-server", version.ref = "artemis" } +asciidoctorGradleJvmGems = { module = "org.asciidoctor:asciidoctor-gradle-jvm-gems", version.ref= "asciidoctor" } +asciidoctorGradleJvm = { module = "org.asciidoctor:asciidoctor-gradle-jvm", version.ref= "asciidoctor" } +asciidoctorGradleJvmPdf = { module = "org.asciidoctor:asciidoctor-gradle-jvm-pdf", version.ref= "asciidoctor" } +rouge = { module = "rubygems:rouge", version.ref = "rouge" } +diagram = { module = "rubygems:asciidoctor-diagram", version.ref = "diagram" } + +[bundles] +logback = ["logbackCore", "logbackClassic"] + +[plugins] +spotbugs = { id = "com.github.spotbugs", version.ref = "spotbugs" } +sonarqube = { id = "org.sonarqube", version.ref = "sonarqube" } +asciidoctorPdf = { id = "org.asciidoctor.jvm.pdf", version.ref = "asciidoctor" } +asciidoctorConvert = { id = "org.asciidoctor.jvm.convert", version.ref = "asciidoctor" } +asciidoctorGems = { id = "org.asciidoctor.jvm.gems", version.ref = "asciidoctor" } +javaConvention = { id = "de.cimt.java-conventions", version.ref = "cimtConventions" } +applicationConvention = { id = "de.cimt.application-conventions", version.ref = "cimtConventions" } +libraryConvention = { id = "de.cimt.library-conventions", version.ref = "cimtConventions" } +asciidoctorConvention = { id = "de.cimt.asciidoctor-conventions", version.ref = "cimtConventions" } +spring-boot = { id = "org.springframework.boot", version.ref = "springboot"} +spring-dependencies = { id = "io.spring.dependency-management", version.ref = "springdependencies" } +vaadin = { id = "com.vaadin", version.ref = "vaadin" } +lombok = { id = "io.freefair.lombok", version.ref = "lombok" } diff --git a/integration/src/main/java/de/thpeetz/kontor/integration/routes/AddLinkFromQueue.java b/integration/src/main/java/de/thpeetz/kontor/integration/routes/AddLinkFromQueue.java new file mode 100644 index 0000000..15af258 --- /dev/null +++ b/integration/src/main/java/de/thpeetz/kontor/integration/routes/AddLinkFromQueue.java @@ -0,0 +1,28 @@ +package de.thpeetz.kontor.integration.routes; + +import de.thpeetz.kontor.integration.services.AddLinkProcessor; +import de.thpeetz.kontor.media.services.MediaFileService; +import org.apache.camel.builder.RouteBuilder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class AddLinkFromQueue extends RouteBuilder { + + @Autowired + private final MediaFileService mediaFileService; + + @Autowired + public AddLinkFromQueue(MediaFileService mediaFileService) { + this.mediaFileService = mediaFileService; + } + + @Override + public void configure() throws Exception { + from("jms:queue:add_link_file") + .routeId("read-queue-add-link_file") + .log("${body}") + .process(new AddLinkProcessor(mediaFileService)) + .to("jms:queue:update_title"); + } +} diff --git a/integration/src/main/java/de/thpeetz/kontor/integration/routes/QueueMediaLinkAdd.java b/integration/src/main/java/de/thpeetz/kontor/integration/routes/QueueMediaLinkAdd.java new file mode 100644 index 0000000..7ec886a --- /dev/null +++ b/integration/src/main/java/de/thpeetz/kontor/integration/routes/QueueMediaLinkAdd.java @@ -0,0 +1,25 @@ +package de.thpeetz.kontor.integration.routes; +import de.thpeetz.kontor.media.services.MediaFileService; +import org.apache.camel.builder.RouteBuilder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class QueueMediaLinkAdd extends RouteBuilder { + + @Autowired + private final MediaFileService mediaFileService; + + @Autowired + public QueueMediaLinkAdd(MediaFileService mediaFileService) { + this.mediaFileService = mediaFileService; + } + + @Override + public void configure() throws Exception { + from("jms:queue:media.link.add") + .routeId("read-queue-media-link-add") + .log("${body}") + .to("jms:queue:media.link.add.processed"); + } +} diff --git a/integration/src/main/java/de/thpeetz/kontor/integration/routes/QueueMediaLoFiAdd.java b/integration/src/main/java/de/thpeetz/kontor/integration/routes/QueueMediaLoFiAdd.java new file mode 100644 index 0000000..3ea86ac --- /dev/null +++ b/integration/src/main/java/de/thpeetz/kontor/integration/routes/QueueMediaLoFiAdd.java @@ -0,0 +1,26 @@ +package de.thpeetz.kontor.integration.routes; + +import org.apache.camel.builder.RouteBuilder; +import de.thpeetz.kontor.media.services.MediaFileService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class QueueMediaLoFiAdd extends RouteBuilder { + + @Autowired + private final MediaFileService mediaFileService; + + @Autowired + public QueueMediaLoFiAdd(MediaFileService mediaFileService) { + this.mediaFileService = mediaFileService; + } + + @Override + public void configure() throws Exception { + from("jms:queue:media.lofi.add") + .routeId("read-queue-media-lofi-add") + .log("${body}") + .to("jms:queue:media.lofi.add.processed"); + } +} diff --git a/integration/src/main/java/de/thpeetz/kontor/integration/routes/QueueMediaVideoAdd.java b/integration/src/main/java/de/thpeetz/kontor/integration/routes/QueueMediaVideoAdd.java new file mode 100644 index 0000000..8e104d7 --- /dev/null +++ b/integration/src/main/java/de/thpeetz/kontor/integration/routes/QueueMediaVideoAdd.java @@ -0,0 +1,26 @@ +package de.thpeetz.kontor.integration.routes; + +import org.apache.camel.builder.RouteBuilder; +import de.thpeetz.kontor.media.services.MediaFileService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class QueueMediaVideoAdd extends RouteBuilder { + + @Autowired + private final MediaFileService mediaFileService; + + @Autowired + public QueueMediaVideoAdd(MediaFileService mediaFileService) { + this.mediaFileService = mediaFileService; + } + + @Override + public void configure() throws Exception { + from("jms:queue:media.video.add") + .routeId("read-queue-media-video-add") + .log("${body}") + .to("jms:queue:media.video.add.processed"); + } +} diff --git a/integration/src/main/java/de/thpeetz/kontor/integration/routes/ReadQueueRoute.java b/integration/src/main/java/de/thpeetz/kontor/integration/routes/ReadQueueRoute.java new file mode 100644 index 0000000..115fef1 --- /dev/null +++ b/integration/src/main/java/de/thpeetz/kontor/integration/routes/ReadQueueRoute.java @@ -0,0 +1,16 @@ +package de.thpeetz.kontor.integration.routes; + +import org.apache.camel.builder.RouteBuilder; +import org.springframework.stereotype.Component; + +@Component +public class ReadQueueRoute extends RouteBuilder { + + @Override + public void configure() throws Exception { + from("jms:queue:KontorMediaFile") + .routeId("add-link-from-queue") + .trace(true) + .log(">>> ${body}"); + } +} diff --git a/integration/src/main/java/de/thpeetz/kontor/integration/services/AddLinkProcessor.java b/integration/src/main/java/de/thpeetz/kontor/integration/services/AddLinkProcessor.java new file mode 100644 index 0000000..6f326a4 --- /dev/null +++ b/integration/src/main/java/de/thpeetz/kontor/integration/services/AddLinkProcessor.java @@ -0,0 +1,53 @@ +package de.thpeetz.kontor.integration.services; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import de.thpeetz.kontor.media.data.MediaFile; +import de.thpeetz.kontor.media.services.MediaFileService; +import lombok.extern.slf4j.Slf4j; +import org.apache.camel.Exchange; +import org.apache.camel.Processor; + +import java.util.HashMap; +import java.util.Map; + +@Slf4j +public class AddLinkProcessor implements Processor { + + private final MediaFileService mediaFileService; + + public AddLinkProcessor(MediaFileService mediaFileService) { + this.mediaFileService = mediaFileService; + } + + @Override + public void process(Exchange exchange) throws Exception { + ObjectMapper objectMapper = new ObjectMapper(); + HashMap myMap = objectMapper.readValue(exchange.getIn().getBody().toString(), + new TypeReference>() { + }); + String url = myMap.get("url"); + log.info("found url: {}", url); + MediaFile mediaFile = mediaFileService.findAllMediaFilesByUrl(url); + if (mediaFile == null) { + log.info("URL not found, create MediaFile"); + mediaFile = new MediaFile(); + mediaFile.setUrl(url); + mediaFile.setPath(""); + mediaFile.setCloudLink(""); + mediaFile.setFileName(""); + mediaFile.setTitle(""); + mediaFile.setReview(true); + mediaFile.setShouldDownload(true); + MediaFile mediaFileResult = mediaFileService.saveMediaFile(mediaFile); + log.info("created MediaFile with {}", mediaFileResult.getId()); + exchange.getMessage().getHeaders().put("mediafile_id", mediaFileResult.getId()); + } else { + log.info("found MediaFile with {}", mediaFile.getId()); + exchange.getMessage().getHeaders().put("mediafile_id", mediaFile.getId()); + } + log.info("found MediaFile: {}", mediaFile); + Map map = exchange.getMessage().getHeaders(); + log.info("Headers: {}", map); + } +} diff --git a/integration/src/main/java/de/thpeetz/kontor/integration/services/AddLinkService.java b/integration/src/main/java/de/thpeetz/kontor/integration/services/AddLinkService.java new file mode 100644 index 0000000..93698e3 --- /dev/null +++ b/integration/src/main/java/de/thpeetz/kontor/integration/services/AddLinkService.java @@ -0,0 +1,22 @@ +package de.thpeetz.kontor.integration.services; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.HashMap; + +@Service +@Slf4j +public class AddLinkService { + + public void fromQueue(String messageBody) throws JsonProcessingException { + log.info("get body: {}", messageBody); + ObjectMapper objectMapper = new ObjectMapper(); + HashMap myMap = objectMapper.readValue(messageBody, new TypeReference>() {}); + String url = myMap.get("url"); + log.info("found url: {}", url); + } +} diff --git a/kontor-data/build.gradle b/kontor-data/build.gradle new file mode 100644 index 0000000..9028938 --- /dev/null +++ b/kontor-data/build.gradle @@ -0,0 +1,39 @@ +plugins { + id 'java' + id 'java-library' + id 'maven-publish' + id 'jacoco' + id 'test-report-aggregation' + id 'jacoco-report-aggregation' + alias(libs.plugins.lombok) +} + +repositories { + //maven { setUrl("https://nexus.thpeetz.de/repository/maven-central") } + mavenCentral() + maven { setUrl("https://repo.spring.io/milestone") } +} + +java { + sourceCompatibility = JavaVersion.VERSION_21 +} + +configurations { + developmentOnly + runtimeClasspath { + extendsFrom developmentOnly + } +} + +dependencies { + //implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + //implementation 'org.postgresql:postgresql' + //implementation 'org.hibernate.orm:hibernate-community-dialects' + compileOnly libs.spring.data + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' +} + +wrapper { + gradleVersion = "8.6" +} diff --git a/kontor-data/gradle/libs.versions.toml b/kontor-data/gradle/libs.versions.toml new file mode 100644 index 0000000..2112db6 --- /dev/null +++ b/kontor-data/gradle/libs.versions.toml @@ -0,0 +1,73 @@ +[versions] +gradle = "8.6" +args4j = "2.33" +commonscli = "1.5.0" +junit = "5.8.2" +logback = "1.1.2" +mockito = "1.9.5" +picoli = "4.7.0" +slf4j = "1.7.22" +hsqldb = "2.7.1" +sqlite = "3.25.2" +spotbugs = "6.0.7" +asciidoctor = "4.0.2" +rouge = "3.15.0" +#diagram = "2.2.2" +diagram = "2.3.1" +sonarqube = "3.3" +cimtConventions = "1.0.0-SNAPSHOT" +springboot = "3.2.5" +springdependencies = "1.1.4" +vaadin = "24.3.8" +camel = "4.10.6" +artemis = "2.41.0" +lombok = "8.6" +gson = "2.9.0" +jackson = "2.16.1" +json_simple = "1.1.1" +mail = "1.6.2" +hypersistence = "3.9.10" + +[libraries] +args4j = { module = "args4j:args4j", version.ref = "args4j" } +commonscli = { module = "commons-cli:commons-cli", version.ref = "commonscli" } +junit = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" } +logbackCore = { module = "ch.qos.logback:logback-core", version.ref = "logback" } +logbackClassic = { module = "ch.qos.logback:logback-classic", version.ref = "logback" } +mockito = { module = "org.mockito:mockito-all", version.ref = "mockito" } +picocli = { module = "info.picocli:picocli", version.ref = "picoli" } +slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" } +hsqldb = { module = "org.hsqldb:hsqldb", version.ref = "hsqldb" } +gson = { module = "com.google.code.gson:gson", version.ref = "gson" } +jackson = { module = "com.fasterxml.jackson.core:jackson-databind", version.ref = "jackson" } +json = { module = "com.googlecode.json-simple:json-simple", version.ref ="json_simple" } +mail = { module = "com.sun.mail:javax.mail", version.ref ="mail" } +sqlite-jdbc = { module = "org.xerial:sqlite-jdbc", version.ref = "sqlite" } +hypersistence = { module = "io.hypersistence:hypersistence-utils-hibernate-63", version.ref = "hypersistence" } +vaadin-bom = { module = "com.vaadin:vaadin-bom", version.ref = "vaadin" } +camel-bom = { module = "org.apache.camel.springboot:camel-spring-boot-bom", version.ref = "camel"} +spring-data = { module = "org.springframework.data:spring-data-jpa", version.ref = "springboot" } +artemis = { module = "org.apache.activemq:artemis-jms-server", version.ref = "artemis" } +asciidoctorGradleJvmGems = { module = "org.asciidoctor:asciidoctor-gradle-jvm-gems", version.ref= "asciidoctor" } +asciidoctorGradleJvm = { module = "org.asciidoctor:asciidoctor-gradle-jvm", version.ref= "asciidoctor" } +asciidoctorGradleJvmPdf = { module = "org.asciidoctor:asciidoctor-gradle-jvm-pdf", version.ref= "asciidoctor" } +rouge = { module = "rubygems:rouge", version.ref = "rouge" } +diagram = { module = "rubygems:asciidoctor-diagram", version.ref = "diagram" } + +[bundles] +logback = ["logbackCore", "logbackClassic"] + +[plugins] +spotbugs = { id = "com.github.spotbugs", version.ref = "spotbugs" } +sonarqube = { id = "org.sonarqube", version.ref = "sonarqube" } +asciidoctorPdf = { id = "org.asciidoctor.jvm.pdf", version.ref = "asciidoctor" } +asciidoctorConvert = { id = "org.asciidoctor.jvm.convert", version.ref = "asciidoctor" } +asciidoctorGems = { id = "org.asciidoctor.jvm.gems", version.ref = "asciidoctor" } +javaConvention = { id = "de.cimt.java-conventions", version.ref = "cimtConventions" } +applicationConvention = { id = "de.cimt.application-conventions", version.ref = "cimtConventions" } +libraryConvention = { id = "de.cimt.library-conventions", version.ref = "cimtConventions" } +asciidoctorConvention = { id = "de.cimt.asciidoctor-conventions", version.ref = "cimtConventions" } +spring-boot = { id = "org.springframework.boot", version.ref = "springboot"} +spring-dependencies = { id = "io.spring.dependency-management", version.ref = "springdependencies" } +vaadin = { id = "com.vaadin", version.ref = "vaadin" } +lombok = { id = "io.freefair.lombok", version.ref = "lombok" } diff --git a/kontor-data/gradle/wrapper/gradle-wrapper.jar b/kontor-data/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..b1b8ef5 Binary files /dev/null and b/kontor-data/gradle/wrapper/gradle-wrapper.jar differ diff --git a/kontor-data/gradle/wrapper/gradle-wrapper.properties b/kontor-data/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..a80b22c --- /dev/null +++ b/kontor-data/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/kontor-data/gradlew b/kontor-data/gradlew new file mode 100755 index 0000000..b9bb139 --- /dev/null +++ b/kontor-data/gradlew @@ -0,0 +1,248 @@ +#!/bin/sh + +# +# Copyright © 2015 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/kontor-data/gradlew.bat b/kontor-data/gradlew.bat new file mode 100755 index 0000000..aa5f10b --- /dev/null +++ b/kontor-data/gradlew.bat @@ -0,0 +1,82 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables, and ensure extensions are enabled +setlocal EnableExtensions + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +"%COMSPEC%" /c exit 1 + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +"%COMSPEC%" /c exit 1 + +:execute +@rem Setup the command line + + + +@rem Execute Gradle +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel + +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% diff --git a/kontor-data/settings.gradle b/kontor-data/settings.gradle new file mode 100644 index 0000000..f559dac --- /dev/null +++ b/kontor-data/settings.gradle @@ -0,0 +1,24 @@ +pluginManagement { + resolutionStrategy { + eachPlugin { + if (requested.id.id == 'org.springframework.boot') { + useModule("org.springframework.boot:spring-boot-gradle-plugin:${requested.version}") + } + if (requested.id.id == 'org.gradle.toolchains.foojay-resolver') { + useModule("org.gradle.toolchains.foojay-resolver-convention:0.4.0") + } + } + } + repositories { + gradlePluginPortal() + mavenCentral() + maven { setUrl("https://maven.vaadin.com/vaadin-prereleases") } + maven { setUrl("https://repo.spring.io/milestone") } + maven { url 'https://plugins.gradle.org/m2/' } + } +// plugins { +// id 'com.vaadin' version "${vaadinVersion}" +// } +} + +rootProject.name = 'kontor-spring' diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/admin/data/Assignment.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/admin/data/Assignment.java new file mode 100644 index 0000000..0f1f3ab --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/admin/data/Assignment.java @@ -0,0 +1,34 @@ +package de.thpeetz.kontor.admin.data; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Entity +public class Assignment extends AbstractEntity { + + @ManyToOne + @JoinColumn(name = "profile_id") + @NotNull + private Profile profile; + + @ManyToOne + @JoinColumn(name = "permission_id") + @NotNull + private Permission permission; + + @Override + public String toString() { + final StringBuffer sb = new StringBuffer("Assignment{"); + sb.append("profile=").append(profile.getUserName()); + sb.append(", permission=").append(permission.getName()); + sb.append('}'); + return sb.toString(); + } +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/admin/data/Permission.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/admin/data/Permission.java new file mode 100644 index 0000000..d5d27a0 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/admin/data/Permission.java @@ -0,0 +1,29 @@ +package de.thpeetz.kontor.admin.data; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.OneToMany; +import jakarta.validation.constraints.NotEmpty; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; + +import javax.annotation.Nullable; +import java.util.List; + +@Slf4j +@Getter +@Setter +@ToString +@Entity +public class Permission extends AbstractEntity { + + @NotEmpty + private String name; + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "permission") + @Nullable + private List assignments; +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/admin/data/Profile.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/admin/data/Profile.java new file mode 100644 index 0000000..8773fb5 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/admin/data/Profile.java @@ -0,0 +1,57 @@ +package de.thpeetz.kontor.admin.data; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.persistence.*; +import jakarta.validation.constraints.NotEmpty; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; + +import javax.annotation.Nullable; +import java.util.LinkedList; +import java.util.List; + +@Slf4j +@Getter +@Setter +@ToString +@Entity +@Table(indexes = @Index(columnList = "userName"), uniqueConstraints = @UniqueConstraint(columnNames = {"userName"})) +public class Profile extends AbstractEntity { + + private String firstName; + + private String lastName; + + @NotEmpty + private String userName; + + private String email; + + private String password; + + private boolean enabled; + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "profile") + @Nullable + private List assignments = new LinkedList<>(); + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "profile") + @Nullable + private List tokens = new LinkedList<>(); + + public String getFullName() { + StringBuilder fullNameBuilder = new StringBuilder(); + if (firstName != null) { + fullNameBuilder.append(firstName); + } + if (lastName != null) { + if (!fullNameBuilder.isEmpty()) { + fullNameBuilder.append(" "); + } + fullNameBuilder.append(lastName); + } + return fullNameBuilder.toString(); + } +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/admin/data/Token.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/admin/data/Token.java new file mode 100644 index 0000000..afd4167 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/admin/data/Token.java @@ -0,0 +1,37 @@ +package de.thpeetz.kontor.admin.data; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.persistence.Entity; +import jakarta.persistence.Index; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; +import java.util.Date; + +@Slf4j +@Getter +@Setter +@ToString +@Entity +@Table(indexes = @Index(columnList = "token"), uniqueConstraints = @UniqueConstraint(columnNames = {"token"})) +public class Token extends AbstractEntity { + + private String token; + + private String name; + + private Date lastUsedDate; + + private boolean enabled; + + @ManyToOne + @JoinColumn(name="profile_id") + @NotNull + private Profile profile; +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/admin/repository/AssignmentRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/admin/repository/AssignmentRepository.java new file mode 100644 index 0000000..eb20059 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/admin/repository/AssignmentRepository.java @@ -0,0 +1,13 @@ +package de.thpeetz.kontor.admin.repository; + +import de.thpeetz.kontor.admin.data.*; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface AssignmentRepository extends JpaRepository { + + List findByProfile(Profile profile); + + List findByPermission(Permission permission); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/admin/repository/MailAccountRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/admin/repository/MailAccountRepository.java new file mode 100644 index 0000000..1cd3885 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/admin/repository/MailAccountRepository.java @@ -0,0 +1,8 @@ +package de.thpeetz.kontor.admin.repository; + +import de.thpeetz.kontor.mailclient.data.MailAccount; +import org.springframework.data.jpa.repository.JpaRepository; + + +public interface MailAccountRepository extends JpaRepository { +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/admin/repository/PermissionRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/admin/repository/PermissionRepository.java new file mode 100644 index 0000000..9e6e863 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/admin/repository/PermissionRepository.java @@ -0,0 +1,19 @@ +package de.thpeetz.kontor.admin.repository; + +import de.thpeetz.kontor.admin.data.Permission; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +public interface PermissionRepository extends JpaRepository { + + @Query("select p from Permission p " + + "where lower(p.name) like lower(concat('%', :searchTerm, '%')) ") + List search(@Param("searchTerm") String searchTerm); + + @Query("select p from Permission p " + + "where lower(p.name) like lower(:name) ") + Permission findByName(@Param("name") String name); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/admin/repository/ProfileRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/admin/repository/ProfileRepository.java new file mode 100644 index 0000000..1238abb --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/admin/repository/ProfileRepository.java @@ -0,0 +1,17 @@ +package de.thpeetz.kontor.admin.repository; + +import de.thpeetz.kontor.admin.data.Profile; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +public interface ProfileRepository extends JpaRepository { + + @Query("select p from Profile p " + + "where lower(p.lastName) like lower(concat('%', :searchTerm, '%')) ") + List search(@Param("searchTerm") String searchTerm); + + Profile findByUserName(String userName); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/Article.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/Article.java new file mode 100644 index 0000000..3ee6a16 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/Article.java @@ -0,0 +1,27 @@ +package de.thpeetz.kontor.bookshelf.data; + +import java.util.LinkedList; +import java.util.List; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.annotation.Nullable; +import jakarta.persistence.*; +import jakarta.validation.constraints.NotEmpty; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +@Entity +@Table(indexes = @Index(columnList = "title"), uniqueConstraints = @UniqueConstraint(columnNames = {"title"})) +public class Article extends AbstractEntity { + + @NotEmpty + private String title; + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "article") + @Nullable + private List authors = new LinkedList<>(); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/ArticleAuthor.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/ArticleAuthor.java new file mode 100644 index 0000000..c2b3851 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/ArticleAuthor.java @@ -0,0 +1,29 @@ +package de.thpeetz.kontor.bookshelf.data; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.persistence.Entity; +import jakarta.persistence.Index; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Entity +@Table(indexes = @Index(columnList = "author_id, article_id"), uniqueConstraints = @UniqueConstraint(columnNames = {"author_id", "article_id"})) +public class ArticleAuthor extends AbstractEntity { + + @ManyToOne + @JoinColumn(name = "author_id") + @NotNull + private Author author; + + @ManyToOne + @JoinColumn(name = "article_id") + @NotNull + private Article article; +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/ArticleAuthorRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/ArticleAuthorRepository.java new file mode 100644 index 0000000..d7933de --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/ArticleAuthorRepository.java @@ -0,0 +1,12 @@ +package de.thpeetz.kontor.bookshelf.data; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ArticleAuthorRepository extends JpaRepository { + + List findByAuthor(Author author); + + List findByArticle(Article article); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/ArticleRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/ArticleRepository.java new file mode 100644 index 0000000..c6b2602 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/ArticleRepository.java @@ -0,0 +1,16 @@ +package de.thpeetz.kontor.bookshelf.data; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface ArticleRepository extends JpaRepository { + + @Query("select a from Article a " + + "where lower(a.title) like lower(concat('%', :searchTerm, '%'))") + List
search(@Param("searchTerm") String searchTerm); + + List
findByTitle(String title); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/Author.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/Author.java new file mode 100644 index 0000000..42d83e0 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/Author.java @@ -0,0 +1,44 @@ +package de.thpeetz.kontor.bookshelf.data; + +import java.util.LinkedList; +import java.util.List; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.annotation.Nullable; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Index; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import jakarta.validation.constraints.NotEmpty; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +@Entity +@Table(indexes = { + @Index(columnList = "firstName, lastName"), + @Index(columnList = "lastName, firstName") +}, uniqueConstraints = { + @UniqueConstraint(columnNames = { "firstName", "lastName" }) +}) +public class Author extends AbstractEntity { + + @NotEmpty + private String firstName; + + @NotEmpty + private String lastName; + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "author") + @Nullable + private List bookAuthors = new LinkedList<>(); + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "author") + @Nullable + private List articleAuthors = new LinkedList<>(); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/AuthorRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/AuthorRepository.java new file mode 100644 index 0000000..3e87334 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/AuthorRepository.java @@ -0,0 +1,18 @@ +package de.thpeetz.kontor.bookshelf.data; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface AuthorRepository extends JpaRepository { + + @Query("select a from Author a " + + "where lower(a.firstName) like lower(concat('%', :searchTerm, '%')) " + + "or lower(a.lastName) like lower(concat('%', :searchTerm, '%'))") + List search(@Param("searchTerm") String searchTerm); + + Author findByFirstNameAndLastName(String firstName, String lastName); + +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/Book.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/Book.java new file mode 100644 index 0000000..e0f6782 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/Book.java @@ -0,0 +1,42 @@ +package de.thpeetz.kontor.bookshelf.data; + +import java.util.LinkedList; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.annotation.Nullable; +import jakarta.persistence.*; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +@Entity +@Table(indexes = @Index(columnList = "title, isbn"), uniqueConstraints = @UniqueConstraint(columnNames = {"isbn"})) +public class Book extends AbstractEntity { + + @NotEmpty + private String title; + + @NotEmpty + private String isbn; + + @Nullable + private int year; + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "book") + @Nullable + private List authors = new LinkedList<>(); + + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "publisher_id") + @NotNull + @JsonIgnoreProperties({ "books" }) + private BookshelfPublisher publisher; +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/BookAuthor.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/BookAuthor.java new file mode 100644 index 0000000..86a0e10 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/BookAuthor.java @@ -0,0 +1,29 @@ +package de.thpeetz.kontor.bookshelf.data; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.persistence.Entity; +import jakarta.persistence.Index; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Entity +@Table(indexes = @Index(columnList = "author_id, book_id"), uniqueConstraints = @UniqueConstraint(columnNames = {"author_id", "book_id"})) +public class BookAuthor extends AbstractEntity { + + @ManyToOne + @JoinColumn(name = "author_id") + @NotNull + private Author author; + + @ManyToOne + @JoinColumn(name = "book_id") + @NotNull + private Book book; +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/BookAuthorRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/BookAuthorRepository.java new file mode 100644 index 0000000..a0cf650 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/BookAuthorRepository.java @@ -0,0 +1,12 @@ +package de.thpeetz.kontor.bookshelf.data; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface BookAuthorRepository extends JpaRepository { + + List findByAuthor(Author author); + + List findByBook(Book book); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/BookRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/BookRepository.java new file mode 100644 index 0000000..e6ee013 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/BookRepository.java @@ -0,0 +1,21 @@ +package de.thpeetz.kontor.bookshelf.data; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +public interface BookRepository extends JpaRepository { + + @Query("select b from Book b " + + "where lower(b.title) like lower(concat('%', :searchTerm, '%')) " + + "or lower(b.isbn) like lower(concat('%', :searchTerm, '%'))") + List search(@Param("searchTerm") String searchTerm); + + List findByTitle(String name); + + List findByTitleIgnoreCase(String name); + + List findByIsbn(String isbn); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/BookshelfPublisher.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/BookshelfPublisher.java new file mode 100644 index 0000000..da97d7a --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/BookshelfPublisher.java @@ -0,0 +1,32 @@ +package de.thpeetz.kontor.bookshelf.data; + +import java.util.LinkedList; +import java.util.List; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.annotation.Nullable; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Index; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import jakarta.validation.constraints.NotEmpty; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +@Entity +@Table(indexes = @Index(columnList = "name"), uniqueConstraints = @UniqueConstraint(columnNames = { "name" })) +public class BookshelfPublisher extends AbstractEntity { + + @NotEmpty + private String name; + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "publisher", orphanRemoval = true) + @Nullable + List books = new LinkedList<>(); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/BookshelfPublisherRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/BookshelfPublisherRepository.java new file mode 100644 index 0000000..b50ba84 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/bookshelf/data/BookshelfPublisherRepository.java @@ -0,0 +1,18 @@ +package de.thpeetz.kontor.bookshelf.data; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface BookshelfPublisherRepository extends JpaRepository { + + @Query("select p from BookshelfPublisher p " + + "where lower(p.name) like lower(concat('%', :searchTerm, '%')) ") + List search(@Param("searchTerm") String searchTerm); + + BookshelfPublisher findByName(String name); + + List findByNameIgnoreCase(String name); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/Artist.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/Artist.java new file mode 100644 index 0000000..8e14329 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/Artist.java @@ -0,0 +1,50 @@ +package de.thpeetz.kontor.comics.data; + +import java.util.LinkedList; +import java.util.List; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import io.micrometer.common.lang.Nullable; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.OneToMany; +import jakarta.validation.constraints.NotEmpty; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +/** + * Represents an artist in the system. + */ +@Getter +@Setter +@EqualsAndHashCode(callSuper = false) +@Slf4j +@Entity +public class Artist extends AbstractEntity { + + @NotEmpty + @Column(unique = true) + private String name; + + private String weblink; + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "artist", cascade = CascadeType.REFRESH, orphanRemoval = true) + @Nullable + List comicWorks = new LinkedList<>(); + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "artist", cascade = CascadeType.REFRESH, orphanRemoval = true) + @Nullable + List issueWorks = new LinkedList<>(); + + @Override + public String toString() { + final StringBuffer sb = new StringBuffer("Artist{"); + sb.append("name='").append(name).append('\''); + sb.append('}'); + return sb.toString(); + } +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/Comic.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/Comic.java new file mode 100644 index 0000000..d20ea37 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/Comic.java @@ -0,0 +1,83 @@ +package de.thpeetz.kontor.comics.data; + +import java.util.LinkedList; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.annotation.Nullable; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +/** + * Represents a comic entity. + */ +@Getter +@Setter +@EqualsAndHashCode(callSuper = false) +@Entity +public class Comic extends AbstractEntity { + + @NotEmpty + @Column(unique = true) + private String title; + + @ManyToOne + @JoinColumn(name = "publisher_id") + @NotNull + @JsonIgnoreProperties({ "comics" }) + private Publisher publisher; + + private Boolean currentOrder = false; + + private Boolean completed = false; + + @Nullable + private String weblink; + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "comic", cascade = CascadeType.REFRESH, orphanRemoval = true) + @Nullable + List comicWorks; + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "comic", cascade = CascadeType.REFRESH, orphanRemoval = true) + @Nullable + private List issues = new LinkedList<>(); + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "comic", cascade = CascadeType.REFRESH, orphanRemoval = true) + @Nullable + private List storyArcs = new LinkedList<>(); + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "comic", cascade = CascadeType.REFRESH, orphanRemoval = true) + @Nullable + private List tradePaperbacks = new LinkedList<>(); + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "comic", cascade = CascadeType.REFRESH, orphanRemoval = true) + @Nullable + private List volumes = new LinkedList<>(); + + @Override + public String toString() { + final StringBuffer sb = new StringBuffer("Comic{"); + sb.append("title='").append(title).append('\''); + sb.append(", publisher=").append(publisher); + sb.append(", currentOrder=").append(currentOrder); + sb.append(", completed=").append(completed); + sb.append('}'); + return sb.toString(); + } + + public String getPublisherName() { + return this.publisher.getName(); + } +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/ComicWork.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/ComicWork.java new file mode 100644 index 0000000..840f93c --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/ComicWork.java @@ -0,0 +1,48 @@ +package de.thpeetz.kontor.comics.data; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.persistence.Entity; +import jakarta.persistence.Index; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import jakarta.validation.constraints.NotNull; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@EqualsAndHashCode(callSuper = false) +@Entity +@Table(indexes = {@Index(columnList = "comic_id, artist_id, workType_id") }, + uniqueConstraints = @UniqueConstraint(columnNames = {"comic_id", "artist_id", "workType_id" }) +) +public class ComicWork extends AbstractEntity { + + @ManyToOne + @JoinColumn(name = "comic_id") + @NotNull + private Comic comic; + + @ManyToOne + @JoinColumn(name = "artist_id") + @NotNull + private Artist artist; + + @ManyToOne + @JoinColumn(name = "workType_id") + @NotNull + private Worktype workType; + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("ComicWork{"); + sb.append("comic=").append(comic); + sb.append(", artist=").append(artist); + sb.append(", workType=").append(workType); + sb.append('}'); + return sb.toString(); + } +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/Issue.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/Issue.java new file mode 100644 index 0000000..9d97320 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/Issue.java @@ -0,0 +1,108 @@ +package de.thpeetz.kontor.comics.data; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import de.thpeetz.kontor.common.data.*; +import io.hypersistence.utils.hibernate.type.basic.YearMonthDateType; +import jakarta.annotation.Nullable; +import jakarta.persistence.*; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.Type; + +import java.time.YearMonth; +import java.util.*; + +@Getter +@Setter +@EqualsAndHashCode(callSuper = false) +@Entity +public class Issue extends AbstractEntity { + + @ManyToOne + @JoinColumn(name = "comic_id") + @NotNull + @JsonIgnoreProperties({ "issues" }) + private Comic comic; + + @ManyToOne + @JoinColumn(name = "volume_id") + @JsonIgnoreProperties({ "issues" }) + @Nullable + private Volume volume; + + @ManyToOne + @JoinColumn(name = "storyArc_id") + @JsonIgnoreProperties({ "issues" }) + @Nullable + private StoryArc storyArc; + + @NotEmpty + private String issueNumber; + + @Nullable + private String title; + + @Nullable + @Type(YearMonthDateType.class) + @Column(name = "published_on", columnDefinition = "date") + private YearMonth publishedOn; + + private Boolean isRead; + + private Boolean inStock; + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "issue", cascade = CascadeType.REFRESH, orphanRemoval = true) + @Nullable + List issueWorks; + + public String getComicTitle() { + return comic.getTitle(); + } + + public String getVolumeName() { + if (volume != null) { + return volume.getName(); + } + return null; + } + + public String getFullTitle() { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(this.getComic().getTitle()); + stringBuilder.append(" #"); + stringBuilder.append(this.getIssueNumber()); + if (this.title !=null && !this.title.isEmpty()) { + stringBuilder.append(": "); + stringBuilder.append(this.title); + } + return stringBuilder.toString(); + } + + @Override + public String toString() { + StringBuilder result = new StringBuilder(); + result.append("Issue{"); + result.append("comic="); + result.append(comic); + result.append(", volume="); + result.append(volume); + result.append(", storyArc="); + result.append(storyArc); + result.append(", issueNumber='"); + result.append(issueNumber); + result.append(", title='"); + result.append(title); + result.append(", publishedOn="); + result.append(publishedOn); + result.append(", isRead="); + result.append(isRead); + result.append(", inStock="); + result.append(inStock); + result.append("}"); + return result.toString(); + } +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/IssueWork.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/IssueWork.java new file mode 100644 index 0000000..b9d545c --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/IssueWork.java @@ -0,0 +1,48 @@ +package de.thpeetz.kontor.comics.data; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.persistence.Entity; +import jakarta.persistence.Index; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import jakarta.validation.constraints.NotNull; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@EqualsAndHashCode(callSuper = false) +@Entity +@Table(indexes = {@Index(columnList = "issue_id, artist_id, workType_id") }, + uniqueConstraints = @UniqueConstraint(columnNames = {"issue_id", "artist_id", "workType_id" }) +) +public class IssueWork extends AbstractEntity { + + @ManyToOne + @JoinColumn(name = "issue_id") + @NotNull + private Issue issue; + + @ManyToOne + @JoinColumn(name = "artist_id") + @NotNull + private Artist artist; + + @ManyToOne + @JoinColumn(name = "workType_id") + @NotNull + private Worktype workType; + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("IssueWork{"); + sb.append("issue=").append(issue); + sb.append(", artist=").append(artist); + sb.append(", workType=").append(workType); + sb.append('}'); + return sb.toString(); + } +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/Publisher.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/Publisher.java new file mode 100644 index 0000000..cd27a43 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/Publisher.java @@ -0,0 +1,63 @@ +package de.thpeetz.kontor.comics.data; + +import java.util.LinkedList; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonBackReference; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.annotation.Nullable; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.Column; +import jakarta.persistence.OneToMany; +import jakarta.persistence.ManyToOne; +import jakarta.validation.constraints.*; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@EqualsAndHashCode(callSuper = false) +@Entity +public class Publisher extends AbstractEntity { + + @NotEmpty + @Column(unique = true) + private String name; + + private String weblink; + + @JsonBackReference + @ManyToOne + @JoinColumn(name = "parent_publisher_id") + @Nullable + @JsonIgnoreProperties({ "comics" }) + private Publisher parentCompany; + + @OneToMany(fetch = FetchType.LAZY, mappedBy = "parentCompany", cascade = CascadeType.ALL, orphanRemoval = true) + @Nullable + private List imprints = new LinkedList<>(); + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "publisher", cascade = CascadeType.ALL, orphanRemoval = true) + @Nullable + private List comics = new LinkedList<>(); + + public String getParentCompanyName() { + if (parentCompany != null) { + return parentCompany.name; + } + return null; + } + + @Override + public String toString() { + final StringBuffer sb = new StringBuffer("Publisher{"); + sb.append("name='").append(name).append('\''); + sb.append('}'); + return sb.toString(); + } +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/StoryArc.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/StoryArc.java new file mode 100644 index 0000000..11d328c --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/StoryArc.java @@ -0,0 +1,46 @@ +package de.thpeetz.kontor.comics.data; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import jakarta.annotation.Nullable; +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToMany; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +import java.util.*; + +@Getter +@Setter +@ToString +@EqualsAndHashCode(callSuper = false) +@Entity +public class StoryArc extends AbstractEntity { + + @NotEmpty + private String name; + + @ManyToOne + @JoinColumn(name = "comic_id") + @NotNull + @JsonIgnoreProperties({ "storyArcs" }) + private Comic comic; + + @ManyToOne + @JoinColumn(name = "volume_id") + @JsonIgnoreProperties({ "storyArcs" }) + @Nullable + private Volume volume; + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "storyArc", cascade = CascadeType.REMOVE, orphanRemoval = true) + @Nullable + private List issues = new LinkedList<>(); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/TradePaperback.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/TradePaperback.java new file mode 100644 index 0000000..07ee8d3 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/TradePaperback.java @@ -0,0 +1,32 @@ +package de.thpeetz.kontor.comics.data; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +@EqualsAndHashCode(callSuper = false) +@Entity +public class TradePaperback extends AbstractEntity { + + @NotEmpty + private String name; + + @ManyToOne + @JoinColumn(name = "comic_id") + @NotNull + private Comic comic; + + private Integer issueStart; + + private Integer issueEnd; +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/Volume.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/Volume.java new file mode 100644 index 0000000..60c3821 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/Volume.java @@ -0,0 +1,55 @@ +package de.thpeetz.kontor.comics.data; + +import java.util.LinkedList; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.annotation.*; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@EqualsAndHashCode(callSuper = false) +@Entity +public class Volume extends AbstractEntity { + + @NotEmpty + private String name; + + @ManyToOne + @JoinColumn(name = "comic_id") + @NotNull + @JsonIgnoreProperties({ "volumes" }) + private Comic comic; + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "volume", cascade = CascadeType.REMOVE, orphanRemoval = true) + @Nullable + private List storyArcs = new LinkedList<>(); + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "volume", cascade = CascadeType.REMOVE, orphanRemoval = true) + @Nullable + private List issues = new LinkedList<>(); + + @Override + public String toString() { + StringBuilder result = new StringBuilder("Volume{"); + result.append("name="); + result.append(name); + result.append("comic=Comic{title="); + result.append(comic.getTitle()); + result.append("}}"); + return result.toString(); + } +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/Worktype.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/Worktype.java new file mode 100644 index 0000000..0416641 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/data/Worktype.java @@ -0,0 +1,47 @@ +package de.thpeetz.kontor.comics.data; + +import java.util.LinkedList; +import java.util.List; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import io.micrometer.common.lang.Nullable; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.OneToMany; +import jakarta.validation.constraints.NotEmpty; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +/** + * Represents a work type in the application. + * This class extends the AbstractEntity class. + */ +@Getter +@Setter +@EqualsAndHashCode(callSuper = false) +@Entity +public class Worktype extends AbstractEntity { + + @NotEmpty + @Column(unique = true) + private String name; + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "workType", cascade = CascadeType.REFRESH, orphanRemoval = true) + @Nullable + List comicWorks = new LinkedList<>(); + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "workType", cascade = CascadeType.REFRESH, orphanRemoval = true) + @Nullable + List issueWorks = new LinkedList<>(); + + @Override + public String toString() { + final StringBuffer sb = new StringBuffer("Worktype{"); + sb.append("name='").append(name).append('\''); + sb.append('}'); + return sb.toString(); + } +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/ArtistRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/ArtistRepository.java new file mode 100644 index 0000000..feff0c0 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/ArtistRepository.java @@ -0,0 +1,18 @@ +package de.thpeetz.kontor.comics.repository; + +import java.util.List; + +import de.thpeetz.kontor.comics.data.*; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface ArtistRepository extends JpaRepository { + @Query("select a from Artist a " + + "where lower(a.name) like lower(concat('%', :searchTerm, '%')) ") + List search(@Param("searchTerm") String searchTerm); + + List findByNameIgnoreCase(String name); + + Artist findByName(String name); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/ComicRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/ComicRepository.java new file mode 100644 index 0000000..2da13e1 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/ComicRepository.java @@ -0,0 +1,39 @@ +package de.thpeetz.kontor.comics.repository; + +import java.util.List; + +import de.thpeetz.kontor.comics.data.*; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface ComicRepository extends JpaRepository { + @Query("select c from Comic c " + + "where lower(c.title) like lower(concat('%', :searchTerm, '%')) ") + List search(@Param("searchTerm") String searchTerm); + + @Query("select c from Comic c " + + "where lower(c.title) like lower(concat('%', :searchTerm, '%')) " + + "AND c.currentOrder=:currentOrder AND c.completed=:completed") + List search(@Param("searchTerm") String searchTerm, Boolean currentOrder, Boolean completed); + + Comic findByTitleAndPublisher(String title, Publisher publisher); + + List findByTitle(String title); + + List findByTitleIgnoreCase(String title); + + List findByCurrentOrderAndCompleted(Boolean currentOrder, Boolean completed); + + List findByCurrentOrder(Boolean currentOrder); + + List findByCompleted(Boolean completed); + + @Query("select c from Comic c " + + "where lower(c.title) like lower(concat('%', :searchTerm, '%')) AND c.currentOrder=:currentOrder") + List searchAndFilterByCurrentOrder(String searchTerm, Boolean currentOrder); + + @Query("select c from Comic c " + + "where lower(c.title) like lower(concat('%', :searchTerm, '%')) AND c.completed=:completed") + List searchAndFilterByCompleted(String searchTerm, Boolean completed); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/ComicWorkRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/ComicWorkRepository.java new file mode 100644 index 0000000..9eba50e --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/ComicWorkRepository.java @@ -0,0 +1,16 @@ +package de.thpeetz.kontor.comics.repository; + +import java.util.List; + +import de.thpeetz.kontor.comics.data.*; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +public interface ComicWorkRepository extends JpaRepository { + + @Query("SELECT c from ComicWork c where c.comic = ?1 and c.artist = ?2 and c.workType = ?3") + ComicWork findbyComicAndArtistAndWorktype(Comic comic, Artist artist, Worktype worktype); + + @Query("select c from ComicWork c where c.comic = ?1") + List findByComic(Comic comic); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/IssueRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/IssueRepository.java new file mode 100644 index 0000000..9719304 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/IssueRepository.java @@ -0,0 +1,18 @@ +package de.thpeetz.kontor.comics.repository; + +import java.util.List; + +import de.thpeetz.kontor.comics.data.*; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface IssueRepository extends JpaRepository { + @Query("select i from Issue i " + + "where lower(i.issueNumber) like lower(concat('%', :searchTerm, '%')) ") + List search(@Param("searchTerm") String searchTerm); + + List findByComic(Comic comic); + + Issue findByComicAndIssueNumber(Comic comic, String issueNumber); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/IssueWorkRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/IssueWorkRepository.java new file mode 100644 index 0000000..a2e0347 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/IssueWorkRepository.java @@ -0,0 +1,15 @@ +package de.thpeetz.kontor.comics.repository; + +import de.thpeetz.kontor.comics.data.*; +import org.springframework.data.jpa.repository.*; + +import java.util.*; + +public interface IssueWorkRepository extends JpaRepository { + + @Query("SELECT i from IssueWork i where i.issue = ?1 and i.artist = ?2 and i.workType = ?3") + IssueWork findbyIssueAndArtistAndWorktype(Issue issue, Artist artist, Worktype worktype); + + @Query("select i from IssueWork i where i.issue = ?1") + List findByIssue(Issue issue); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/PublisherRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/PublisherRepository.java new file mode 100644 index 0000000..076b32e --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/PublisherRepository.java @@ -0,0 +1,18 @@ +package de.thpeetz.kontor.comics.repository; + +import java.util.List; + +import de.thpeetz.kontor.comics.data.*; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface PublisherRepository extends JpaRepository { + @Query("select p from Publisher p " + + "where lower(p.name) like lower(concat('%', :searchTerm, '%')) ") + List search(@Param("searchTerm") String searchTerm); + + Publisher findByName(String name); + + List findByNameIgnoreCase(String name); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/StoryArcRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/StoryArcRepository.java new file mode 100644 index 0000000..23326fb --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/StoryArcRepository.java @@ -0,0 +1,18 @@ +package de.thpeetz.kontor.comics.repository; + +import java.util.List; + +import de.thpeetz.kontor.comics.data.*; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface StoryArcRepository extends JpaRepository { + @Query("select s from StoryArc s " + + "where lower(s.name) like lower(concat('%', :searchTerm, '%')) ") + List search(@Param("searchTerm") String searchTerm); + + StoryArc findByNameAndComic(String name, Comic comic); + + List findByComic(Comic comic); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/TradePaperbackRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/TradePaperbackRepository.java new file mode 100644 index 0000000..d8c5787 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/TradePaperbackRepository.java @@ -0,0 +1,21 @@ +package de.thpeetz.kontor.comics.repository; + +import java.util.List; + +import de.thpeetz.kontor.comics.data.*; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface TradePaperbackRepository extends JpaRepository { + @Query("select t from TradePaperback t " + + "where lower(t.name) like lower(concat('%', :searchTerm, '%')) ") + List search(@Param("searchTerm") String searchTerm); + + List findByComic(Comic comic); + + List findByNameAndComic(String name, Comic comic); + + @Query("select t from TradePaperback t where t.name = ?1 and t.comic = ?2 and t.issueStart = ?3 and t.issueEnd = ?4") + TradePaperback findByFields(String name, Comic comic, int start, int end); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/VolumeRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/VolumeRepository.java new file mode 100644 index 0000000..cf98406 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/VolumeRepository.java @@ -0,0 +1,14 @@ +package de.thpeetz.kontor.comics.repository; + +import java.util.List; + +import de.thpeetz.kontor.comics.data.*; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface VolumeRepository extends JpaRepository { + + List findByName(String name); + + List findByComic(Comic comic); + +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/WorktypeRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/WorktypeRepository.java new file mode 100644 index 0000000..12755c9 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/comics/repository/WorktypeRepository.java @@ -0,0 +1,19 @@ +package de.thpeetz.kontor.comics.repository; + +import java.util.List; + +import de.thpeetz.kontor.comics.data.*; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface WorktypeRepository extends JpaRepository { + @Query("select w from Worktype w " + + "where lower(w.name) like lower(concat('%', :searchTerm, '%')) ") + List search(@Param("searchTerm") String searchTerm); + + + Worktype findByName(String name); + + List findByNameIgnoreCase(String name); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/common/data/AbstractEntity.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/common/data/AbstractEntity.java new file mode 100644 index 0000000..182dd45 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/common/data/AbstractEntity.java @@ -0,0 +1,45 @@ +package de.thpeetz.kontor.common.data; + +import jakarta.persistence.*; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import java.util.Date; + +@Slf4j +@Getter +@Setter +@EqualsAndHashCode +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +public abstract class AbstractEntity { + + @Id + @GeneratedValue(strategy = GenerationType.UUID) + private String id; + + @Version + private int version; + + @CreatedDate + private Date createdDate; + + @LastModifiedDate + private Date lastModifiedDate; + + public void updateVersion(String value) { + if (value == null) { + log.info("value not given"); + return; + } + if (version != Integer.valueOf(value).intValue()) { + log.info("update version"); + version = Integer.valueOf(value).intValue(); + } + } +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/common/data/AbstractLinkEntity.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/common/data/AbstractLinkEntity.java new file mode 100644 index 0000000..7dfdf50 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/common/data/AbstractLinkEntity.java @@ -0,0 +1,55 @@ +package de.thpeetz.kontor.common.data; + +import jakarta.annotation.Nullable; +import jakarta.persistence.*; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import java.util.Date; + +@Slf4j +@Getter +@Setter +@EqualsAndHashCode +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +public abstract class AbstractLinkEntity { + + @Id + @GeneratedValue(strategy = GenerationType.UUID) + private String id; + + @Version + private int version; + + @CreatedDate + private Date createdDate; + + @LastModifiedDate + private Date lastModifiedDate; + + @Nullable + private String url; + + private boolean review; + + private boolean shouldDownload; + + @Nullable + private String title; + + @Nullable + private String cloudLink; + + @Nullable + private String fileName; + + @Nullable + private String path; + +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/mailclient/data/Mail.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/mailclient/data/Mail.java new file mode 100644 index 0000000..f3b80a8 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/mailclient/data/Mail.java @@ -0,0 +1,20 @@ +package de.thpeetz.kontor.mailclient.data; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.persistence.Entity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +@Data +@EqualsAndHashCode(callSuper=false) +@Entity +public class Mail extends AbstractEntity { + + private String folder; + private String subject; + private String body; + private Date sentDate; + private Date receivedDate; +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/mailclient/data/MailAccount.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/mailclient/data/MailAccount.java new file mode 100644 index 0000000..840d8da --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/mailclient/data/MailAccount.java @@ -0,0 +1,29 @@ +package de.thpeetz.kontor.mailclient.data; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.persistence.Entity; +import jakarta.validation.constraints.NotEmpty; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Getter +@Setter +@Entity +public class MailAccount extends AbstractEntity { + + @NotEmpty + private String host; + + private Integer port; + + @NotEmpty + private String protocol; + + private String userName; + + private String password; + + private Boolean startTls; +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/media/data/MediaActor.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/media/data/MediaActor.java new file mode 100644 index 0000000..e448080 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/media/data/MediaActor.java @@ -0,0 +1,32 @@ +package de.thpeetz.kontor.media.data; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.annotation.Nullable; +import jakarta.persistence.*; +import jakarta.validation.constraints.NotEmpty; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +import java.util.LinkedList; +import java.util.List; + +@Getter +@Setter +@EqualsAndHashCode(callSuper = false) +@Slf4j +@Entity +public class MediaActor extends AbstractEntity { + + @NotEmpty + private String name; + + @Nullable + @Column(unique = true) + private String url; + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "media_actor", cascade = CascadeType.REFRESH, orphanRemoval = true) + @Nullable + List mediaActorFiles = new LinkedList<>(); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/media/data/MediaActorFile.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/media/data/MediaActorFile.java new file mode 100644 index 0000000..0e24cd7 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/media/data/MediaActorFile.java @@ -0,0 +1,34 @@ +package de.thpeetz.kontor.media.data; + +import de.thpeetz.kontor.comics.data.Artist; +import de.thpeetz.kontor.comics.data.Comic; +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.persistence.*; +import jakarta.validation.constraints.NotNull; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@EqualsAndHashCode(callSuper = false) +@Entity +@Table(indexes = {@Index(columnList = "media_file_id, media_actor_id") }, + uniqueConstraints = @UniqueConstraint(columnNames = {"media_file_id", "media_actor_id" }) +) +public class MediaActorFile extends AbstractEntity { + + @ManyToOne + @JoinColumn(name = "media_file_id") + @NotNull + private MediaFile media_file; + + @ManyToOne + @JoinColumn(name = "media_actor_id") + @NotNull + private MediaActor media_actor; + + public String getTitle() { + return media_file.getTitle(); + } +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/media/data/MediaArticle.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/media/data/MediaArticle.java new file mode 100644 index 0000000..c664a3a --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/media/data/MediaArticle.java @@ -0,0 +1,29 @@ +package de.thpeetz.kontor.media.data; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.annotation.Nullable; +import jakarta.persistence.Entity; +import jakarta.persistence.Index; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import jakarta.validation.constraints.NotEmpty; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Getter +@Setter +@Entity +@Table(indexes = @Index(columnList = "url"), uniqueConstraints = @UniqueConstraint(columnNames = {"url"})) +public class MediaArticle extends AbstractEntity { + + @NotEmpty + private String url; + + private boolean review; + + @Nullable + private String title; +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/media/data/MediaFile.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/media/data/MediaFile.java new file mode 100644 index 0000000..2193690 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/media/data/MediaFile.java @@ -0,0 +1,43 @@ +package de.thpeetz.kontor.media.data; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.annotation.Nullable; +import jakarta.persistence.*; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +import java.util.LinkedList; +import java.util.List; + +@Slf4j +@Getter +@Setter +@EqualsAndHashCode(callSuper = false) +@Entity +public class MediaFile extends AbstractEntity { + + @Nullable + private String url; + + private boolean review; + + private boolean shouldDownload; + + @Nullable + private String title; + + @Nullable + private String cloudLink; + + @Nullable + private String fileName; + + @Nullable + private String path; + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "media_file", cascade = CascadeType.REFRESH, orphanRemoval = true) + @Nullable + List mediaActorFiles = new LinkedList<>(); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/media/data/MediaVideo.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/media/data/MediaVideo.java new file mode 100644 index 0000000..d093eb1 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/media/data/MediaVideo.java @@ -0,0 +1,40 @@ +package de.thpeetz.kontor.media.data; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.annotation.Nullable; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Getter +@Setter +@EqualsAndHashCode(callSuper = false) +@Entity +@Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "url" }) }) +public class MediaVideo extends AbstractEntity { + + @Nullable + private String url; + + private boolean review; + + private boolean shouldDownload; + + @Nullable + private String title; + + @Nullable + private String cloudLink; + + @Nullable + private String fileName; + + @Nullable + private String path; + +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/media/repository/MediaActorFileRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/media/repository/MediaActorFileRepository.java new file mode 100644 index 0000000..e680b32 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/media/repository/MediaActorFileRepository.java @@ -0,0 +1,8 @@ +package de.thpeetz.kontor.media.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import de.thpeetz.kontor.media.data.MediaActorFile; + +public interface MediaActorFileRepository extends JpaRepository { +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/media/repository/MediaActorRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/media/repository/MediaActorRepository.java new file mode 100644 index 0000000..1cd5ff0 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/media/repository/MediaActorRepository.java @@ -0,0 +1,19 @@ +package de.thpeetz.kontor.media.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import de.thpeetz.kontor.media.data.MediaActor; + +import java.util.List; + +public interface MediaActorRepository extends JpaRepository { + @Query("select m from MediaActor m " + + "where lower(m.name) like lower(concat('%', :searchTerm, '%')) ") + List search(@Param("searchTerm") String searchTerm); + + List findByNameIgnoreCase(String name); + + MediaActor findByName(String name); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/media/repository/MediaArticleRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/media/repository/MediaArticleRepository.java new file mode 100644 index 0000000..6486097 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/media/repository/MediaArticleRepository.java @@ -0,0 +1,15 @@ +package de.thpeetz.kontor.media.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import de.thpeetz.kontor.media.data.MediaArticle; + +import java.util.List; + +public interface MediaArticleRepository extends JpaRepository { + @Query("select m from MediaArticle m " + + "where lower(m.url) like lower(concat('%', :searchTerm, '%')) or lower(m.title) like lower(concat('%', :searchTerm, '%'))") + List search(@Param("searchTerm") String searchTerm); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/media/repository/MediaFileRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/media/repository/MediaFileRepository.java new file mode 100644 index 0000000..ac8274d --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/media/repository/MediaFileRepository.java @@ -0,0 +1,31 @@ +package de.thpeetz.kontor.media.repository; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import de.thpeetz.kontor.media.data.MediaFile; + +public interface MediaFileRepository extends JpaRepository { + @Query("select m from MediaFile m " + + "where lower(m.url) like lower(concat('%', :searchTerm, '%')) or lower(m.title) like lower(concat('%', :searchTerm, '%'))") + List search(@Param("searchTerm") String searchTerm); + + List findByShouldDownload(Boolean shouldDownload); + + List findByReview(Boolean review); + + List findByReviewAndShouldDownload(Boolean review, Boolean shouldDownload); + + MediaFile findByUrl(String url); + + @Query("select m from MediaFile m " + + "where lower(m.url) like lower(concat('%', :searchTerm, '%')) or lower(m.title) like lower(concat('%', :searchTerm, '%')) " + + "AND m.review=:review AND m.shouldDownload=:download") + List search( + @Param("searchTerm") String searchTerm, + @Param("review") boolean searchReview, + @Param("download") boolean searchDownload); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/media/repository/MediaVideoRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/media/repository/MediaVideoRepository.java new file mode 100644 index 0000000..25c72e8 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/media/repository/MediaVideoRepository.java @@ -0,0 +1,17 @@ +package de.thpeetz.kontor.media.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import de.thpeetz.kontor.media.data.MediaVideo; + +import java.util.List; + +public interface MediaVideoRepository extends JpaRepository { + + @Query("select m from MediaVideo m " + + "where lower(m.url) like lower(concat('%', :searchTerm, '%')) or lower(m.title) like lower(concat('%', :searchTerm, '%'))") + List search(@Param("searchTerm") String searchTerm); + +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/data/Card.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/data/Card.java new file mode 100644 index 0000000..8fa3486 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/data/Card.java @@ -0,0 +1,62 @@ +package de.thpeetz.kontor.tysc.data; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.persistence.Entity; +import jakarta.persistence.Index; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import jakarta.validation.constraints.NotNull; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +@EqualsAndHashCode(callSuper=false) +@Entity +@Table(indexes = {@Index(columnList = "cardNumber, year")}, + uniqueConstraints = {@UniqueConstraint(columnNames = { "cardNumber", "year", "vendor_id", "cardSet_id" })} +) +public class Card extends AbstractEntity { + + private int cardNumber; + + private int year; + + @ManyToOne + @JoinColumn(name = "vendor_id") + @NotNull + @JsonIgnoreProperties({ "cards" }) + private Vendor vendor; + + @ManyToOne + @JoinColumn(name = "cardSet_id") + @NotNull + @JsonIgnoreProperties({ "cards" }) + private CardSet cardSet; + + @ManyToOne + @JoinColumn(name = "rooster_id") + @NotNull + @JsonIgnoreProperties({ "cards" }) + private Rooster rooster; + + public String getVendorName() { + return this.vendor.getName(); + } + + public String getCardSetName() { + return this.cardSet.getName(); + } + + public String getPlayerName() { + return this.rooster.getPlayer().getFullName(); + } +} + diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/data/CardSet.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/data/CardSet.java new file mode 100644 index 0000000..8bd700d --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/data/CardSet.java @@ -0,0 +1,45 @@ +package de.thpeetz.kontor.tysc.data; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.persistence.Entity; +import jakarta.persistence.Index; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +@EqualsAndHashCode(callSuper=false) +@Entity +@Table(indexes = {@Index(columnList = "name, vendor_id")}, + uniqueConstraints = {@UniqueConstraint(columnNames = { "name", "vendor_id" })} +) +public class CardSet extends AbstractEntity { + + @NotEmpty + private String name; + + @ManyToOne() + @JoinColumn(name = "vendor_id") + @NotNull + @JsonIgnoreProperties({ "cardSets" }) + private Vendor vendor; + + private boolean parallelSet = false; + + private boolean insertSet = false; + + public String getVendorName() { + return vendor.getName(); + } +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/data/FieldPosition.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/data/FieldPosition.java new file mode 100644 index 0000000..a806e70 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/data/FieldPosition.java @@ -0,0 +1,52 @@ +package de.thpeetz.kontor.tysc.data; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.annotation.Nullable; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Index; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +@EqualsAndHashCode(callSuper=false) +@Entity +@Table(indexes = {@Index(columnList = "name, sport_id")}, + uniqueConstraints = { + @UniqueConstraint(columnNames = { "name", "sport_id" }), + @UniqueConstraint(columnNames = { "shortName", "sport_id" }) + } +) +public class FieldPosition extends AbstractEntity { + + @NotEmpty + private String name; + + @NotEmpty + private String shortName; + + @ManyToOne + @JoinColumn(name = "sport_id") + @NotNull + @JsonIgnoreProperties({ "positions" }) + private Sport sport; + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "position") + @Nullable + private List roosters; +} \ No newline at end of file diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/data/Player.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/data/Player.java new file mode 100644 index 0000000..6517959 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/data/Player.java @@ -0,0 +1,49 @@ +package de.thpeetz.kontor.tysc.data; + +import java.util.List; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.annotation.Nullable; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Index; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import jakarta.validation.constraints.NotNull; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +@EqualsAndHashCode(callSuper=false) +@Entity +@Table(indexes = { + @Index(columnList = "firstName, lastName"), + @Index(columnList = "lastName, firstName") +}, uniqueConstraints = { + @UniqueConstraint(columnNames = { "firstName", "lastName" }) +}) +public class Player extends AbstractEntity { + + @NotNull + private String firstName; + + @NotNull + private String lastName; + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "player") + @Nullable + private List roosters; + + public String getFullName() { + StringBuilder fullName = new StringBuilder(); + fullName.append(this.lastName); + fullName.append(", "); + fullName.append(this.firstName); + return fullName.toString(); + } +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/data/Rooster.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/data/Rooster.java new file mode 100644 index 0000000..b0d3a3a --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/data/Rooster.java @@ -0,0 +1,49 @@ +package de.thpeetz.kontor.tysc.data; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.persistence.Entity; +import jakarta.persistence.Index; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import jakarta.validation.constraints.NotNull; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@EqualsAndHashCode(callSuper = false) +@Entity +@Table(indexes = { @Index(columnList = "team_id, player_id, position_id") }, uniqueConstraints = { + @UniqueConstraint(name = "uniqueRooster", columnNames = { "year", "team_id", "player_id", "position_id" }) }) +public class Rooster extends AbstractEntity { + + private int year; + + @ManyToOne + @JoinColumn(name = "team_id") + @NotNull + private Team team; + + @ManyToOne + @JoinColumn(name = "player_id") + @NotNull + private Player player; + + @ManyToOne + @JoinColumn(name = "position_id") + @NotNull + private FieldPosition position; + + @Override + public String toString() { + return "Rooster{" + + "year=" + year + + ", team=" + team.getName() + + ", player=" + player.getFullName() + + ", position=" + position.getName() + + '}'; + } +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/data/Sport.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/data/Sport.java new file mode 100644 index 0000000..72635e1 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/data/Sport.java @@ -0,0 +1,53 @@ +package de.thpeetz.kontor.tysc.data; + +import java.util.LinkedList; +import java.util.List; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.annotation.Nullable; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Index; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import jakarta.validation.constraints.NotEmpty; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Getter +@Setter +@ToString +@EqualsAndHashCode(callSuper=false) +@Entity +@Table(indexes = {@Index(columnList = "name")}, + uniqueConstraints = {@UniqueConstraint(columnNames = { "name" })} +) +public class Sport extends AbstractEntity { + + @NotEmpty + @Column(unique = true) + private String name; + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "sport") + @Nullable + private List teams = new LinkedList<>(); + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "sport") + @Nullable + private List positions = new LinkedList<>(); + + public String updateName(String value) { + if (!this.getName().equals(value)) { + this.setName(value); + log.info("update name"); + return "updated " + this.getId() + " with " + value; + } + return "no changes for " + this.getId(); + } +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/data/Team.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/data/Team.java new file mode 100644 index 0000000..353da78 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/data/Team.java @@ -0,0 +1,49 @@ +package de.thpeetz.kontor.tysc.data; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.annotation.Nullable; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Index; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +@EqualsAndHashCode(callSuper=false) +@Entity +@Table(indexes = {@Index(columnList = "name")}, + uniqueConstraints = {@UniqueConstraint(columnNames = { "name" })} +) +public class Team extends AbstractEntity { + + @NotEmpty + private String name; + + @NotEmpty + private String shortName; + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "team") + @Nullable + private List roosters; + + @ManyToOne + @JoinColumn(name = "sport_id") + @NotNull + @JsonIgnoreProperties({ "teams" }) + private Sport sport; +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/data/Vendor.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/data/Vendor.java new file mode 100644 index 0000000..a7a9305 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/data/Vendor.java @@ -0,0 +1,39 @@ +package de.thpeetz.kontor.tysc.data; + +import java.util.List; + +import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.annotation.Nullable; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Index; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import jakarta.validation.constraints.NotEmpty; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +/** + * Represents a vendor entity. + */ +@Getter +@Setter +@EqualsAndHashCode(callSuper = false) +@Entity +@Table(indexes = { @Index(columnList = "name") }, uniqueConstraints = { @UniqueConstraint(columnNames = "name") }) +public class Vendor extends AbstractEntity { + + @NotEmpty + private String name; + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "vendor") + @Nullable + private List cardSets; + + @Override + public String toString() { + return "Vendor{id=" + this.getId() + ", name=" + name + '}'; + } +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/repository/CardRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/repository/CardRepository.java new file mode 100644 index 0000000..09cfc08 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/repository/CardRepository.java @@ -0,0 +1,21 @@ +package de.thpeetz.kontor.tysc.repository; + +import de.thpeetz.kontor.tysc.data.Card; +import de.thpeetz.kontor.tysc.data.CardSet; +import de.thpeetz.kontor.tysc.data.Rooster; +import de.thpeetz.kontor.tysc.data.Vendor; +import java.util.List; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface CardRepository extends JpaRepository { + + @Query("SELECT c FROM Card c WHERE c.vendor = ?1 AND c.cardSet = ?2 and c.rooster = ?3 and c.cardNumber = ?4 and c.year = ?5") + Card search(Vendor vendor, CardSet cardset, Rooster rooster, int cardNumber, int year); + + @Query("select c from Card c " + + "where str(c.cardNumber) like lower(concat('%', :searchTerm, '%')) ") + List search(@Param("searchTerm") String searchTerm); +} + diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/repository/CardSetRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/repository/CardSetRepository.java new file mode 100644 index 0000000..3bf2901 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/repository/CardSetRepository.java @@ -0,0 +1,20 @@ +package de.thpeetz.kontor.tysc.repository; + +import java.util.List; + +import de.thpeetz.kontor.tysc.data.CardSet; +import de.thpeetz.kontor.tysc.data.Vendor; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface CardSetRepository extends JpaRepository { + + List findByName(String name); + + CardSet findByNameAndVendor(String name, Vendor vendor); + + @Query("select c from CardSet c " + + "where lower(c.name) like lower(concat('%', :searchTerm, '%')) ") + List search(@Param("searchTerm") String searchTerm); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/repository/FieldPositionRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/repository/FieldPositionRepository.java new file mode 100644 index 0000000..b018173 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/repository/FieldPositionRepository.java @@ -0,0 +1,24 @@ +package de.thpeetz.kontor.tysc.repository; + +import java.util.List; + +import de.thpeetz.kontor.tysc.data.FieldPosition; +import de.thpeetz.kontor.tysc.data.Sport; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface FieldPositionRepository extends JpaRepository { + + @Query("select p from FieldPosition p " + + "where lower(p.name) like lower(concat('%', :searchTerm, '%')) ") + List search(@Param("searchTerm") String searchTerm); + + List findBySport(Sport sport); + + FieldPosition findByShortName(String searchTerm); + + List findByShortNameIgnoreCase(String shortName); + + FieldPosition findByShortNameAndSport(String shortName, Sport sport); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/repository/PlayerRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/repository/PlayerRepository.java new file mode 100644 index 0000000..2f978f2 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/repository/PlayerRepository.java @@ -0,0 +1,18 @@ +package de.thpeetz.kontor.tysc.repository; + +import java.util.List; + +import de.thpeetz.kontor.tysc.data.Player; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface PlayerRepository extends JpaRepository { + + @Query("select p from Player p " + + "where lower(p.firstName) like lower(concat('%', :searchTerm, '%')) " + + "or lower(p.lastName) like lower(concat('%', :searchTerm, '%'))") + List search(@Param("searchTerm") String searchTerm); + + Player findByFirstNameAndLastName(String firstName, String lastName); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/repository/RoosterRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/repository/RoosterRepository.java new file mode 100644 index 0000000..b707d6e --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/repository/RoosterRepository.java @@ -0,0 +1,15 @@ +package de.thpeetz.kontor.tysc.repository; + +import de.thpeetz.kontor.tysc.data.FieldPosition; +import de.thpeetz.kontor.tysc.data.Player; +import de.thpeetz.kontor.tysc.data.Rooster; +import de.thpeetz.kontor.tysc.data.Team; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +public interface RoosterRepository extends JpaRepository{ + + @Query("SELECT r FROM Rooster r WHERE r.player = ?1 AND r.team = ?2 AND r.position = ?3 AND r.year = ?4") + Rooster findByReferences(Player player, Team team, FieldPosition position, int year); +} + diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/repository/SportRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/repository/SportRepository.java new file mode 100644 index 0000000..3860a68 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/repository/SportRepository.java @@ -0,0 +1,18 @@ +package de.thpeetz.kontor.tysc.repository; + +import java.util.List; + +import de.thpeetz.kontor.tysc.data.Sport; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface SportRepository extends JpaRepository { + @Query("select s from Sport s " + + "where lower(s.name) like lower(concat('%', :searchTerm, '%')) ") + List search(@Param("searchTerm") String searchTerm); + + Sport findByName(String name); + + List findByNameIgnoreCase(String name); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/repository/TeamRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/repository/TeamRepository.java new file mode 100644 index 0000000..c0aeae8 --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/repository/TeamRepository.java @@ -0,0 +1,28 @@ +package de.thpeetz.kontor.tysc.repository; + +import java.util.List; + +import de.thpeetz.kontor.tysc.data.Team; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +/** + * The repository interface for managing teams. + */ +public interface TeamRepository extends JpaRepository { + + /** + * Searches for teams based on a search term. + * + * @param searchTerm the search term to match against team names + * @return a list of teams matching the search term + */ + @Query("select t from Team t " + + "where lower(t.name) like lower(concat('%', :searchTerm, '%')) ") + List search(@Param("searchTerm") String searchTerm); + + Team findByName(String name); + + List findByNameIgnoreCase(String name); +} diff --git a/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/repository/VendorRepository.java b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/repository/VendorRepository.java new file mode 100644 index 0000000..3195c3c --- /dev/null +++ b/kontor-data/src/main/java/de/thpeetz/kontor/data/tysc/repository/VendorRepository.java @@ -0,0 +1,18 @@ +package de.thpeetz.kontor.tysc.repository; + +import java.util.List; + +import de.thpeetz.kontor.tysc.data.Vendor; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface VendorRepository extends JpaRepository { + + @Query("select v from Vendor v where lower(v.name) like lower(concat('%', :searchTerm, '%')) ") + List search(@Param("searchTerm") String searchTerm); + + Vendor findByName(String name); + + List findByNameIgnoreCase(String name); +}