diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..e5b3b67
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,26 @@
+name: Publish package to the Maven Central Repository
+on:
+ push:
+ tags:
+ - v*
+ pull_request:
+ branches: [ main ]
+jobs:
+ publish:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - name: Set up Java
+ uses: actions/setup-java@v3
+ with:
+ java-version: '17'
+ distribution: 'adopt'
+ - name: Publish package
+ env:
+ JRELEASER_NEXUS2_USERNAME: ${{ secrets.JRELEASER_NEXUS2_USERNAME }}
+ JRELEASER_NEXUS2_PASSWORD: ${{ secrets.JRELEASER_NEXUS2_PASSWORD }}
+ JRELEASER_GPG_PASSPHRASE: ${{ secrets.JRELEASER_GPG_PASSPHRASE }}
+ JRELEASER_GPG_SECRET_KEY: ${{ secrets.JRELEASER_GPG_SECRET_KEY }}
+ JRELEASER_GPG_PUBLIC_KEY: ${{ secrets.JRELEASER_GPG_PUBLIC_KEY }}
+ JRELEASER_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: ./mvnw -Prelease -DskipTests deploy jreleaser:deploy -DaltDeploymentRepository=local::file:./target/staging-deploy
diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..cb28b0e
Binary files /dev/null and b/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..2e76e18
--- /dev/null
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
diff --git a/README.md b/README.md
index 71424c2..f015492 100644
--- a/README.md
+++ b/README.md
@@ -76,6 +76,15 @@ If you find a problem or a bug, please report it as issue. When doing so, includ
## Changelog
+ * provide the code for the involved `@Entity` classes, if possible
+ * provide the full stack trace of the error
+ * specify if you are using any particular configuration either in your `application.properties` or through annotations
+
+**0.1.2**
+- Better handling of large text fields (shown as `textarea`)
+- Added `CATEGORICAL` option to `Filterable`
+- Several bug fixes
+
**0.1.0**
- Implemented action logs
- Implemented user settings
diff --git a/mvnw b/mvnw
new file mode 100755
index 0000000..66df285
--- /dev/null
+++ b/mvnw
@@ -0,0 +1,308 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Apache Maven Wrapper startup batch script, version 3.2.0
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /usr/local/etc/mavenrc ] ; then
+ . /usr/local/etc/mavenrc
+ fi
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "$(uname)" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
+ else
+ JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=$(java-config --jre-home)
+ fi
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
+ JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="$(which javac)"
+ if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=$(which readlink)
+ if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
+ if $darwin ; then
+ javaHome="$(dirname "\"$javaExecutable\"")"
+ javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
+ else
+ javaExecutable="$(readlink -f "\"$javaExecutable\"")"
+ fi
+ javaHome="$(dirname "\"$javaExecutable\"")"
+ javaHome=$(expr "$javaHome" : '\(.*\)/bin')
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ 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
+ else
+ JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=$(cd "$wdir/.." || exit 1; pwd)
+ fi
+ # end of workaround
+ done
+ printf '%s' "$(cd "$basedir" || exit 1; pwd)"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ # Remove \r in case we run on Windows within Git Bash
+ # and check out the repository with auto CRLF management
+ # enabled. Otherwise, we may read lines that are delimited with
+ # \r\n and produce $'-Xarg\r' rather than -Xarg due to word
+ # splitting rules.
+ tr -s '\r\n' ' ' < "$1"
+ fi
+}
+
+log() {
+ if [ "$MVNW_VERBOSE" = true ]; then
+ printf '%s\n' "$1"
+ fi
+}
+
+BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
+log "$MAVEN_PROJECTBASEDIR"
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
+if [ -r "$wrapperJarPath" ]; then
+ log "Found $wrapperJarPath"
+else
+ log "Couldn't find $wrapperJarPath, downloading it ..."
+
+ if [ -n "$MVNW_REPOURL" ]; then
+ wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ else
+ wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ fi
+ while IFS="=" read -r key value; do
+ # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
+ safeValue=$(echo "$value" | tr -d '\r')
+ case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
+ esac
+ done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+ log "Downloading from: $wrapperUrl"
+
+ if $cygwin; then
+ wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
+ fi
+
+ if command -v wget > /dev/null; then
+ log "Found wget ... using wget"
+ [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ else
+ wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ log "Found curl ... using curl"
+ [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+ else
+ curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+ fi
+ else
+ log "Falling back to using Java to download"
+ javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaSource=$(cygpath --path --windows "$javaSource")
+ javaClass=$(cygpath --path --windows "$javaClass")
+ fi
+ if [ -e "$javaSource" ]; then
+ if [ ! -e "$javaClass" ]; then
+ log " - Compiling MavenWrapperDownloader.java ..."
+ ("$JAVA_HOME/bin/javac" "$javaSource")
+ fi
+ if [ -e "$javaClass" ]; then
+ log " - Running MavenWrapperDownloader.java ..."
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+# If specified, validate the SHA-256 sum of the Maven wrapper jar file
+wrapperSha256Sum=""
+while IFS="=" read -r key value; do
+ case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
+ esac
+done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+if [ -n "$wrapperSha256Sum" ]; then
+ wrapperSha256Result=false
+ if command -v sha256sum > /dev/null; then
+ if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
+ wrapperSha256Result=true
+ fi
+ elif command -v shasum > /dev/null; then
+ if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
+ wrapperSha256Result=true
+ fi
+ else
+ echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
+ echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
+ exit 1
+ fi
+ if [ $wrapperSha256Result = false ]; then
+ echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
+ echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
+ echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
+ exit 1
+ fi
+fi
+
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+# shellcheck disable=SC2086 # safe args
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ $MAVEN_DEBUG_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/pom.xml b/pom.xml
index 51b7fd1..6dae032 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,10 +13,78 @@
spring-boot-db-admin
0.1.2
spring-boot-db-admin
- Srping Boot DB Admin Dashboard
+ Srping Boot Database Admin is an auto-generated CRUD admin panel for Spring Boot apps
17
+
+
+ GPL-v3.0
+ http://www.gnu.org/licenses/gpl-3.0.txt
+
+
+
+
+
+ release
+
+
+
+ org.jreleaser
+ jreleaser-maven-plugin
+ 1.3.1
+
+
+
+ ALWAYS
+ true
+
+
+
+
+
+ ALWAYS
+ https://s01.oss.sonatype.org/service/local
+ true
+ true
+ target/staging-deploy
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.4.1
+
+
+ attach-javadoc
+
+ jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 3.2.1
+
+
+ attach-source
+
+ jar
+
+
+
+
+
+
+
+
@@ -25,12 +93,12 @@
1.3
-
-
-
-
-
-
+
+
+
+
+
+
@@ -88,13 +156,13 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/src/main/java/tech/ailef/dbadmin/external/DbAdmin.java b/src/main/java/tech/ailef/dbadmin/external/DbAdmin.java
index bbb888e..b3eae7a 100644
--- a/src/main/java/tech/ailef/dbadmin/external/DbAdmin.java
+++ b/src/main/java/tech/ailef/dbadmin/external/DbAdmin.java
@@ -53,6 +53,12 @@ public class DbAdmin {
private String modelsPackage;
+ /**
+ * Builds the DbAdmin instance by scanning the `@Entity` beans and loading
+ * the schemas.
+ * @param entityManager the entity manager
+ * @param properties the configuration properties
+ */
public DbAdmin(@Autowired EntityManager entityManager, @Autowired DbAdminProperties properties) {
this.modelsPackage = properties.getModelsPackage();
this.entityManager = entityManager;
@@ -71,7 +77,7 @@ public class DbAdmin {
/**
* Returns all the loaded schemas (i.e. entity classes)
- * @return
+ * @return the list of loaded schemas from the `@Entity` classes
*/
public List getSchemas() {
return Collections.unmodifiableList(schemas);
@@ -80,7 +86,7 @@ public class DbAdmin {
/**
* Finds a schema by its full class name
* @param className qualified class name
- * @return
+ * @return the schema with this class name
* @throws DbAdminException if corresponding schema not found
*/
public DbObjectSchema findSchemaByClassName(String className) {
@@ -92,7 +98,7 @@ public class DbAdmin {
/**
* Finds a schema by its table name
* @param tableName the table name on the database
- * @return
+ * @return the schema with this table name
* @throws DbAdminException if corresponding schema not found
*/
public DbObjectSchema findSchemaByTableName(String tableName) {
@@ -102,9 +108,9 @@ public class DbAdmin {
}
/**
- * Finds a schema by its class
- * @param klass
- * @return
+ * Finds a schema by its class object
+ * @param the `@Entity` class you want to find the schema for
+ * @return the schema for the `@Entity` class
* @throws DbAdminException if corresponding schema not found
*/
public DbObjectSchema findSchemaByClass(Class> klass) {
@@ -118,7 +124,7 @@ public class DbAdmin {
*
* If any field is not mappable, the method will throw an exception.
* @param bd
- * @return
+ * @return a schema derived from the `@Entity` class
*/
private DbObjectSchema processBeanDefinition(BeanDefinition bd) {
String fullClassName = bd.getBeanClassName();
diff --git a/src/main/java/tech/ailef/dbadmin/external/DbAdminAutoConfiguration.java b/src/main/java/tech/ailef/dbadmin/external/DbAdminAutoConfiguration.java
index 7f11371..8899a20 100644
--- a/src/main/java/tech/ailef/dbadmin/external/DbAdminAutoConfiguration.java
+++ b/src/main/java/tech/ailef/dbadmin/external/DbAdminAutoConfiguration.java
@@ -21,6 +21,10 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
import tech.ailef.dbadmin.internal.InternalDbAdminConfiguration;
+/**
+ * The configuration class that adds and configures the "internal" data source.
+ *
+ */
@ConditionalOnProperty(name = "dbadmin.enabled", matchIfMissing = true)
@ComponentScan
@EnableConfigurationProperties(DbAdminProperties.class)
@@ -56,7 +60,7 @@ public class DbAdminAutoConfiguration {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(internalDataSource());
factoryBean.setPersistenceUnitName("internal");
- factoryBean.setPackagesToScan("tech.ailef.dbadmin.internal.model"); // , "tech.ailef.dbadmin.repository");
+ factoryBean.setPackagesToScan("tech.ailef.dbadmin.internal.model");
factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
Properties properties = new Properties();
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
diff --git a/src/main/java/tech/ailef/dbadmin/external/DbAdminProperties.java b/src/main/java/tech/ailef/dbadmin/external/DbAdminProperties.java
index c2e3544..5dd458b 100644
--- a/src/main/java/tech/ailef/dbadmin/external/DbAdminProperties.java
+++ b/src/main/java/tech/ailef/dbadmin/external/DbAdminProperties.java
@@ -26,6 +26,9 @@ public class DbAdminProperties {
*/
private String modelsPackage;
+ /**
+ * Set to true when running the tests to configure the "internal" data source as in memory
+ */
private boolean testMode = false;
public boolean isEnabled() {
diff --git a/src/main/java/tech/ailef/dbadmin/external/annotations/DisplayFormat.java b/src/main/java/tech/ailef/dbadmin/external/annotations/DisplayFormat.java
index 7e7641e..7e02b04 100644
--- a/src/main/java/tech/ailef/dbadmin/external/annotations/DisplayFormat.java
+++ b/src/main/java/tech/ailef/dbadmin/external/annotations/DisplayFormat.java
@@ -13,5 +13,9 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface DisplayFormat {
+ /**
+ * The format to apply to the field's value
+ * @return
+ */
public String format() default "";
}
\ No newline at end of file
diff --git a/src/main/java/tech/ailef/dbadmin/external/annotations/Filterable.java b/src/main/java/tech/ailef/dbadmin/external/annotations/Filterable.java
index cbcf71e..4d90bf0 100644
--- a/src/main/java/tech/ailef/dbadmin/external/annotations/Filterable.java
+++ b/src/main/java/tech/ailef/dbadmin/external/annotations/Filterable.java
@@ -16,5 +16,9 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Filterable {
+ /**
+ * The type of filter (DEFAULT or CATEGORICAL)
+ * @return
+ */
public FilterableType type() default FilterableType.DEFAULT;
}
\ No newline at end of file
diff --git a/src/main/java/tech/ailef/dbadmin/external/annotations/FilterableType.java b/src/main/java/tech/ailef/dbadmin/external/annotations/FilterableType.java
index 79cf09b..d38bc63 100644
--- a/src/main/java/tech/ailef/dbadmin/external/annotations/FilterableType.java
+++ b/src/main/java/tech/ailef/dbadmin/external/annotations/FilterableType.java
@@ -1,5 +1,24 @@
package tech.ailef.dbadmin.external.annotations;
+/**
+ * Type of filters that can be used in the faceted search.
+ *
+ */
public enum FilterableType {
- DEFAULT, CATEGORICAL;
+ /**
+ * The default filter provides a list of standard operators
+ * customized to the field type (e.g. greater than/less than/equals for numbers,
+ * after/before/equals for dates, contains/equals for strings, etc...), with,
+ * if applicable, an autocomplete form if the field references a foreign key.
+ */
+ DEFAULT,
+ /**
+ * The categorical filter provides the full list of possible values
+ * for the field, rendered as a list of clickable items (that will
+ * filter for equality). This provides a better UX if the field can take
+ * a limited number of values and it's more convenient to have them all
+ * on screen rather than typing them.
+ */
+ CATEGORICAL;
+
}
diff --git a/src/main/java/tech/ailef/dbadmin/external/controller/DownloadController.java b/src/main/java/tech/ailef/dbadmin/external/controller/DownloadController.java
index 36c8863..f46edce 100644
--- a/src/main/java/tech/ailef/dbadmin/external/controller/DownloadController.java
+++ b/src/main/java/tech/ailef/dbadmin/external/controller/DownloadController.java
@@ -37,6 +37,13 @@ public class DownloadController {
private DbAdmin dbAdmin;
+ /**
+ * Serve a binary field as an image
+ * @param className
+ * @param fieldName
+ * @param id
+ * @return
+ */
@GetMapping(value="/{className}/{fieldName}/{id}/image", produces = MediaType.IMAGE_JPEG_VALUE)
@ResponseBody
public ResponseEntity serveImage(@PathVariable String className,
@@ -58,6 +65,16 @@ public class DownloadController {
}
+ /**
+ * Serve a binary field as a file. This tries to detect the file type using Tika
+ * in order to serve the file with a plausible extension, since we don't have
+ * any meta-data about what was originally uploaded and it is not feasible to
+ * store it (it could be modified on another end and we wouldn't be aware of it).
+ * @param className
+ * @param fieldName
+ * @param id
+ * @return
+ */
@GetMapping("/{className}/{fieldName}/{id}")
@ResponseBody
public ResponseEntity serveFile(@PathVariable String className,
diff --git a/src/main/java/tech/ailef/dbadmin/external/controller/GlobalController.java b/src/main/java/tech/ailef/dbadmin/external/controller/GlobalController.java
index dc52283..8ba6162 100644
--- a/src/main/java/tech/ailef/dbadmin/external/controller/GlobalController.java
+++ b/src/main/java/tech/ailef/dbadmin/external/controller/GlobalController.java
@@ -36,7 +36,6 @@ public class GlobalController {
/**
* The baseUrl as specified in the properties file by the user
- * @param request
* @return
*/
@ModelAttribute("baseUrl")
@@ -44,11 +43,21 @@ public class GlobalController {
return props.getBaseUrl();
}
+ /**
+ * The full request URL, not including the query string
+ * @param request
+ * @return
+ */
@ModelAttribute("requestUrl")
public String getRequestUrl(HttpServletRequest request) {
return request.getRequestURI();
}
+ /**
+ * The UserConfiguration object used to retrieve values specified
+ * in the settings table.
+ * @return
+ */
@ModelAttribute("userConf")
public UserConfiguration getUserConf() {
return userConf;
diff --git a/src/main/java/tech/ailef/dbadmin/external/controller/rest/AutocompleteController.java b/src/main/java/tech/ailef/dbadmin/external/controller/rest/AutocompleteController.java
index 7f42dca..9817fa4 100644
--- a/src/main/java/tech/ailef/dbadmin/external/controller/rest/AutocompleteController.java
+++ b/src/main/java/tech/ailef/dbadmin/external/controller/rest/AutocompleteController.java
@@ -28,6 +28,12 @@ public class AutocompleteController {
@Autowired
private DbAdminRepository repository;
+ /**
+ * Returns a list of entities from a given table that match an input query.
+ * @param className
+ * @param query
+ * @return
+ */
@GetMapping("/{className}")
public ResponseEntity> autocomplete(@PathVariable String className, @RequestParam String query) {
DbObjectSchema schema = dbAdmin.findSchemaByClassName(className);
diff --git a/src/main/java/tech/ailef/dbadmin/external/dbmapping/CustomJpaRepository.java b/src/main/java/tech/ailef/dbadmin/external/dbmapping/CustomJpaRepository.java
index 702d725..90b32ef 100644
--- a/src/main/java/tech/ailef/dbadmin/external/dbmapping/CustomJpaRepository.java
+++ b/src/main/java/tech/ailef/dbadmin/external/dbmapping/CustomJpaRepository.java
@@ -80,6 +80,51 @@ public class CustomJpaRepository extends SimpleJpaRepository {
.setFirstResult((page - 1) * pageSize).getResultList();
}
+
+ @SuppressWarnings("unchecked")
+ public int update(DbObjectSchema schema, Map params, Map files) {
+ CriteriaBuilder cb = entityManager.getCriteriaBuilder();
+
+ CriteriaUpdate update = cb.createCriteriaUpdate(schema.getJavaClass());
+
+ Root root = update.from(schema.getJavaClass());
+
+ for (DbField field : schema.getSortedFields()) {
+ if (field.isPrimaryKey()) continue;
+
+ boolean keepValue = params.getOrDefault("__keep_" + field.getName(), "off").equals("on");
+ if (keepValue) continue;
+
+ String stringValue = params.get(field.getName());
+ Object value = null;
+ if (stringValue != null && stringValue.isBlank()) stringValue = null;
+ if (stringValue != null) {
+ value = field.getType().parseValue(stringValue);
+ } else {
+ try {
+ MultipartFile file = files.get(field.getName());
+ if (file != null) {
+ if (file.isEmpty()) value = null;
+ else value = file.getBytes();
+ }
+ } catch (IOException e) {
+ throw new DbAdminException(e);
+ }
+ }
+
+ if (field.getConnectedSchema() != null)
+ value = field.getConnectedSchema().getJpaRepository().findById(value).get();
+
+ update.set(root.get(field.getJavaName()), value);
+ }
+
+ String pkName = schema.getPrimaryKey().getJavaName();
+ update.where(cb.equal(root.get(pkName), params.get(schema.getPrimaryKey().getName())));
+
+ Query query = entityManager.createQuery(update);
+ return query.executeUpdate();
+ }
+
@SuppressWarnings("unchecked")
private List buildPredicates(String q, Set queryFilters,
CriteriaBuilder cb, Path root) {
@@ -155,48 +200,4 @@ public class CustomJpaRepository extends SimpleJpaRepository {
}
return finalPredicates;
}
-
- @SuppressWarnings("unchecked")
- public int update(DbObjectSchema schema, Map params, Map files) {
- CriteriaBuilder cb = entityManager.getCriteriaBuilder();
-
- CriteriaUpdate update = cb.createCriteriaUpdate(schema.getJavaClass());
-
- Root root = update.from(schema.getJavaClass());
-
- for (DbField field : schema.getSortedFields()) {
- if (field.isPrimaryKey()) continue;
-
- boolean keepValue = params.getOrDefault("__keep_" + field.getName(), "off").equals("on");
- if (keepValue) continue;
-
- String stringValue = params.get(field.getName());
- Object value = null;
- if (stringValue != null && stringValue.isBlank()) stringValue = null;
- if (stringValue != null) {
- value = field.getType().parseValue(stringValue);
- } else {
- try {
- MultipartFile file = files.get(field.getName());
- if (file != null) {
- if (file.isEmpty()) value = null;
- else value = file.getBytes();
- }
- } catch (IOException e) {
- throw new DbAdminException(e);
- }
- }
-
- if (field.getConnectedSchema() != null)
- value = field.getConnectedSchema().getJpaRepository().findById(value).get();
-
- update.set(root.get(field.getJavaName()), value);
- }
-
- String pkName = schema.getPrimaryKey().getJavaName();
- update.where(cb.equal(root.get(pkName), params.get(schema.getPrimaryKey().getName())));
-
- Query query = entityManager.createQuery(update);
- return query.executeUpdate();
- }
}
diff --git a/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbAdminRepository.java b/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbAdminRepository.java
index d8d802d..6f22b46 100644
--- a/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbAdminRepository.java
+++ b/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbAdminRepository.java
@@ -256,7 +256,6 @@ public class DbAdminRepository {
* Delete a specific object
* @param schema
* @param id
- * @return
*/
@SuppressWarnings("unchecked")
@Transactional("transactionManager")
diff --git a/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbField.java b/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbField.java
index 6e5d4c5..2161958 100644
--- a/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbField.java
+++ b/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbField.java
@@ -13,13 +13,25 @@ import tech.ailef.dbadmin.external.annotations.Filterable;
import tech.ailef.dbadmin.external.annotations.FilterableType;
public class DbField {
+ /**
+ * The inferred name of this field on the database
+ */
protected String dbName;
+ /**
+ * The name of this field in the Java code (instance variable)
+ */
protected String javaName;
+ /**
+ * The type of this field
+ */
protected DbFieldType type;
@JsonIgnore
+ /**
+ * The primitive Field object from the Class
+ */
protected Field field;
/**
@@ -29,12 +41,25 @@ public class DbField {
@JsonIgnore
private Class> connectedType;
+ /**
+ * Whether this field is a primary key
+ */
private boolean primaryKey;
+ /**
+ * Whether this field is nullable
+ */
private boolean nullable;
+ /**
+ * The optional format to apply to this field, if the `@DisplayFormat`
+ * annotation has been applied.
+ */
private String format;
+ /**
+ * The schema this field belongs to
+ */
@JsonIgnore
private DbObjectSchema schema;
diff --git a/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbFieldType.java b/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbFieldType.java
index 8cf1634..3f4eaaf 100644
--- a/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbFieldType.java
+++ b/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbFieldType.java
@@ -14,6 +14,9 @@ import jakarta.persistence.OneToOne;
import tech.ailef.dbadmin.external.dto.CompareOperator;
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
+/**
+ * The list of supported field types
+ */
public enum DbFieldType {
INTEGER {
@Override
@@ -27,7 +30,6 @@ public enum DbFieldType {
}
@Override
-
public Class> getJavaClass() {
return Integer.class;
}
diff --git a/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbFieldValue.java b/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbFieldValue.java
index 6575818..bea6da3 100644
--- a/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbFieldValue.java
+++ b/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbFieldValue.java
@@ -4,6 +4,10 @@ import java.util.Objects;
import com.fasterxml.jackson.annotation.JsonIgnore;
+/**
+ * Wrapper for the value of a field
+ *
+ */
public class DbFieldValue {
private Object value;
diff --git a/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbObject.java b/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbObject.java
index 0da11bc..42021b9 100644
--- a/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbObject.java
+++ b/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbObject.java
@@ -15,9 +15,19 @@ import tech.ailef.dbadmin.external.annotations.DisplayName;
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
import tech.ailef.dbadmin.external.misc.Utils;
+/**
+ * Wrapper for all objects retrieved from the database.
+ *
+ */
public class DbObject {
+ /**
+ * The instance of the object, i.e. an instance of the `@Entity` class
+ */
private Object instance;
+ /**
+ * The schema this object belongs to
+ */
private DbObjectSchema schema;
public DbObject(Object instance, DbObjectSchema schema) {
diff --git a/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbObjectSchema.java b/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbObjectSchema.java
index 6b389bd..4ef961a 100644
--- a/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbObjectSchema.java
+++ b/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbObjectSchema.java
@@ -22,6 +22,11 @@ import tech.ailef.dbadmin.external.annotations.ComputedColumn;
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
import tech.ailef.dbadmin.external.misc.Utils;
+/**
+ * A class that represents a table/`@Entity` as reconstructed from the
+ * JPA annotations found on its fields.
+ *
+ */
public class DbObjectSchema {
/**
* All the fields in this table. The fields include all the
@@ -54,6 +59,13 @@ public class DbObjectSchema {
*/
private String tableName;
+ /**
+ * Initializes this schema for the specific `@Entity` class.
+ * Determines the table name from the `@Table` annotation and also
+ * which methods are `@ComputedColumn`s
+ * @param klass the `@Entity` class
+ * @param dbAdmin the DbAdmin instance
+ */
public DbObjectSchema(Class> klass, DbAdmin dbAdmin) {
this.dbAdmin = dbAdmin;
this.entityClass = klass;
@@ -83,48 +95,103 @@ public class DbObjectSchema {
}
}
+ /**
+ * Returns the DbAdmin instance
+ * @return the DbAdmin instance
+ */
public DbAdmin getDbAdmin() {
return dbAdmin;
}
+ /**
+ * Returns the Java class for the underlying `@Entity` this schema
+ * corresponds to
+ * @return the Java class for the `@Entity` this schema corresponds to
+ */
@JsonIgnore
public Class> getJavaClass() {
return entityClass;
}
+ /**
+ * Returns the name of the Java class for the underlying `@Entity` this schema
+ * corresponds to
+ * @return the name of the Java class for the `@Entity` this schema corresponds to
+ */
@JsonIgnore
public String getClassName() {
return entityClass.getName();
}
+ /**
+ * Returns an unmodifiable list of all the fields in the schema
+ * @return an unmodifiable list of all the fields in the schema
+ */
public List getFields() {
return Collections.unmodifiableList(fields);
}
+ /**
+ * Get a field by its Java name, i.e. the name of the instance variable
+ * in the `@Entity` class
+ * @param name name of the instance variable
+ * @return the DbField if found, null otherwise
+ */
public DbField getFieldByJavaName(String name) {
return fields.stream().filter(f -> f.getJavaName().equals(name)).findFirst().orElse(null);
}
+ /**
+ * Get a field by its database name, i.e. the name of the column corresponding
+ * to the field
+ * @param name name of the column
+ * @return the DbField if found, null otherwise
+ */
public DbField getFieldByName(String name) {
return fields.stream().filter(f -> f.getName().equals(name)).findFirst().orElse(null);
}
+ /**
+ * Adds a field to this schema. This is used by the DbAdmin instance
+ * during initialization and it's not supposed to be called afterwards
+ * @param f the DbField to add
+ */
public void addField(DbField f) {
fields.add(f);
}
-
+
+ /**
+ * Returns the underlying CustomJpaRepository
+ * @return
+ */
public CustomJpaRepository getJpaRepository() {
return jpaRepository;
}
+ /**
+ * Sets the underlying CustomJpaRepository
+ * @param jpaRepository
+ */
public void setJpaRepository(CustomJpaRepository jpaRepository) {
this.jpaRepository = jpaRepository;
}
+ /**
+ * Returns the inferred table name for this schema
+ * @return
+ */
public String getTableName() {
return tableName;
}
+ /**
+ * Returns a sorted list of physical fields (i.e., fields that correspond to
+ * a column in the table as opposed to fields that are just present as
+ * instance variables, like relationship fields). Sorted alphabetically
+ * with priority to the primary key.
+ *
+ * @return
+ */
@JsonIgnore
public List getSortedFields() {
return getFields().stream()
@@ -146,6 +213,10 @@ public class DbObjectSchema {
}).collect(Collectors.toList());
}
+ /**
+ * Returns the list of relationship fields
+ * @return
+ */
public List getRelationshipFields() {
List res = getFields().stream().filter(f -> {
return f.getPrimitiveField().getAnnotation(OneToMany.class) != null
@@ -154,6 +225,11 @@ public class DbObjectSchema {
return res;
}
+ /**
+ * Returns the list of ManyToMany fields owned by this class (i.e. they
+ * do not have "mappedBy")
+ * @return
+ */
public List getManyToManyOwnedFields() {
List res = getFields().stream().filter(f -> {
ManyToMany anno = f.getPrimitiveField().getAnnotation(ManyToMany.class);
@@ -162,6 +238,10 @@ public class DbObjectSchema {
return res;
}
+ /**
+ * Returns the DbField which serves as the primary key for this schema
+ * @return
+ */
@JsonIgnore
public DbField getPrimaryKey() {
Optional pk = fields.stream().filter(f -> f.isPrimaryKey()).findFirst();
@@ -171,21 +251,37 @@ public class DbObjectSchema {
throw new RuntimeException("No primary key defined on " + entityClass.getName() + " (table `" + tableName + "`)");
}
+ /**
+ * Returns the names of the `@ComputedColumn`s in this schema
+ * @return
+ */
public List getComputedColumnNames() {
return computedColumns.keySet().stream().sorted().toList();
}
+ /**
+ * Returns the method for the given `@ComputedColumn` name
+ * @param name the name of the `@ComputedColumn`
+ * @return the corresponding instance method if found, null otherwise
+ */
public Method getComputedColumn(String name) {
return computedColumns.get(name);
}
+ /**
+ * Returns the list of fields that are `@Filterable`
+ * @return
+ */
public List getFilterableFields() {
return getSortedFields().stream().filter(f -> {
- return !f.isBinary() && !f.isPrimaryKey()
- && f.isFilterable();
+ return !f.isBinary() && !f.isPrimaryKey() && f.isFilterable();
}).toList();
}
+ /**
+ * Returns all the data in this schema, as `DbObject`s
+ * @return
+ */
public List findAll() {
List> r = jpaRepository.findAll();
return r.stream().map(o -> new DbObject(o, this)).toList();
diff --git a/src/main/java/tech/ailef/dbadmin/external/dto/AutocompleteSearchResult.java b/src/main/java/tech/ailef/dbadmin/external/dto/AutocompleteSearchResult.java
index a714bd0..7701972 100644
--- a/src/main/java/tech/ailef/dbadmin/external/dto/AutocompleteSearchResult.java
+++ b/src/main/java/tech/ailef/dbadmin/external/dto/AutocompleteSearchResult.java
@@ -2,6 +2,11 @@ package tech.ailef.dbadmin.external.dto;
import tech.ailef.dbadmin.external.dbmapping.DbObject;
+/**
+ * An object to hold autocomplete results returned from the
+ * respective AutocompleteController
+ *
+ */
public class AutocompleteSearchResult {
private Object id;
diff --git a/src/main/java/tech/ailef/dbadmin/external/dto/CompareOperator.java b/src/main/java/tech/ailef/dbadmin/external/dto/CompareOperator.java
index fbeb373..bc75990 100644
--- a/src/main/java/tech/ailef/dbadmin/external/dto/CompareOperator.java
+++ b/src/main/java/tech/ailef/dbadmin/external/dto/CompareOperator.java
@@ -1,5 +1,9 @@
package tech.ailef.dbadmin.external.dto;
+/**
+ * A list of operators that are used in faceted search.
+ *
+ */
public enum CompareOperator {
GT {
@Override
diff --git a/src/main/java/tech/ailef/dbadmin/external/dto/LogsSearchRequest.java b/src/main/java/tech/ailef/dbadmin/external/dto/LogsSearchRequest.java
index e766731..3d66a3a 100644
--- a/src/main/java/tech/ailef/dbadmin/external/dto/LogsSearchRequest.java
+++ b/src/main/java/tech/ailef/dbadmin/external/dto/LogsSearchRequest.java
@@ -3,19 +3,45 @@ package tech.ailef.dbadmin.external.dto;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
+/**
+ * A client request for the Action logs page where
+ * several filtering parameters are present
+ *
+ */
public class LogsSearchRequest {
+ /**
+ * The table name to filter on
+ */
private String table;
+ /**
+ * The action type to filter on (EDIT, CREATE, DELETE, ANY)
+ */
private String actionType;
+ /**
+ * The item id to filter on.
+ */
private String itemId;
+ /**
+ * The requested page
+ */
private int page;
+ /**
+ * The requested page size
+ */
private int pageSize;
+ /**
+ * The requested sort key
+ */
private String sortKey;
+ /**
+ * The requested sort order
+ */
private String sortOrder;
public String getTable() {
@@ -80,6 +106,10 @@ public class LogsSearchRequest {
+ page + ", pageSize=" + pageSize + ", sortKey=" + sortKey + ", sortOrder=" + sortOrder + "]";
}
+ /**
+ * Build a Spring PageRequest object from the parameters in this request
+ * @return a Spring PageRequest object
+ */
public PageRequest toPageRequest() {
int actualPage = page - 1 < 0 ? 0 : page - 1;
int actualPageSize = pageSize <= 0 ? 50 : pageSize;
diff --git a/src/main/java/tech/ailef/dbadmin/external/dto/PaginatedResult.java b/src/main/java/tech/ailef/dbadmin/external/dto/PaginatedResult.java
index 2b22fda..d389fab 100644
--- a/src/main/java/tech/ailef/dbadmin/external/dto/PaginatedResult.java
+++ b/src/main/java/tech/ailef/dbadmin/external/dto/PaginatedResult.java
@@ -2,9 +2,19 @@ package tech.ailef.dbadmin.external.dto;
import java.util.List;
+/**
+ * A wrapper class that holds info about the current pagination and one page
+ * of returned result.
+ */
public class PaginatedResult {
+ /**
+ * The pagination settings used to produce this output
+ */
private PaginationInfo pagination;
+ /**
+ * The list of results in the current page
+ */
private List results;
public PaginatedResult(PaginationInfo pagination, List page) {
diff --git a/src/main/java/tech/ailef/dbadmin/external/dto/QueryFilter.java b/src/main/java/tech/ailef/dbadmin/external/dto/QueryFilter.java
index 9449516..1f252c6 100644
--- a/src/main/java/tech/ailef/dbadmin/external/dto/QueryFilter.java
+++ b/src/main/java/tech/ailef/dbadmin/external/dto/QueryFilter.java
@@ -29,6 +29,10 @@ public class QueryFilter {
return value;
}
+ /**
+ * Provides a readable version of this query filter, customized
+ * based on field type and/or operator.
+ */
@Override
public String toString() {
if (value != null && !value.toString().isBlank()) {
diff --git a/src/main/java/tech/ailef/dbadmin/external/exceptions/DbAdminException.java b/src/main/java/tech/ailef/dbadmin/external/exceptions/DbAdminException.java
index 4c97285..1953c3e 100644
--- a/src/main/java/tech/ailef/dbadmin/external/exceptions/DbAdminException.java
+++ b/src/main/java/tech/ailef/dbadmin/external/exceptions/DbAdminException.java
@@ -1,5 +1,9 @@
package tech.ailef.dbadmin.external.exceptions;
+/**
+ * Generic top-level exception for everything thrown by us
+ *
+ */
public class DbAdminException extends RuntimeException {
private static final long serialVersionUID = 8120227031645804467L;
diff --git a/src/main/java/tech/ailef/dbadmin/external/misc/Utils.java b/src/main/java/tech/ailef/dbadmin/external/misc/Utils.java
index 7fcfc93..24ec730 100644
--- a/src/main/java/tech/ailef/dbadmin/external/misc/Utils.java
+++ b/src/main/java/tech/ailef/dbadmin/external/misc/Utils.java
@@ -1,6 +1,7 @@
package tech.ailef.dbadmin.external.misc;
import java.util.ArrayList;
+
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -13,7 +14,38 @@ import tech.ailef.dbadmin.external.dto.CompareOperator;
import tech.ailef.dbadmin.external.dto.QueryFilter;
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
+/**
+ * Collection of utility functions used across the project
+ *
+ */
public interface Utils {
+ /**
+ * Converts snake case to camel case
+ * @param text
+ * @return
+ */
+ public static String snakeToCamel(String text) {
+ boolean shouldConvertNextCharToLower = true;
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < text.length(); i++) {
+ char currentChar = text.charAt(i);
+ if (currentChar == '_') {
+ shouldConvertNextCharToLower = false;
+ } else if (shouldConvertNextCharToLower) {
+ builder.append(Character.toLowerCase(currentChar));
+ } else {
+ builder.append(Character.toUpperCase(currentChar));
+ shouldConvertNextCharToLower = true;
+ }
+ }
+ return builder.toString();
+ }
+
+ /**
+ * Convers camel case to snake case
+ * @param v
+ * @return
+ */
public static String camelToSnake(String v) {
if (Character.isUpperCase(v.charAt(0))) {
v = Character.toLowerCase(v.charAt(0)) + v.substring(1);
@@ -23,6 +55,12 @@ public interface Utils {
}
+ /**
+ * Converts a set of query filters applied with the faceted search feature
+ * to a multi value map
+ * @param filters
+ * @return
+ */
public static MultiValueMap computeParams(Set filters) {
MultiValueMap r = new LinkedMultiValueMap<>();
if (filters == null)
@@ -41,6 +79,13 @@ public interface Utils {
return r;
}
+ /**
+ * Converts a multi value map of parameters containing query filters applied
+ * with the faceted search feature into a set of QueryFilter objects
+ * @param schema
+ * @param params
+ * @return
+ */
public static Set computeFilters(DbObjectSchema schema, MultiValueMap params) {
if (params == null)
return new HashSet<>();
@@ -85,20 +130,4 @@ public interface Utils {
return "?" + String.join("&", paramValues);
}
- public static String snakeToCamel(String text) {
- boolean shouldConvertNextCharToLower = true;
- StringBuilder builder = new StringBuilder();
- for (int i = 0; i < text.length(); i++) {
- char currentChar = text.charAt(i);
- if (currentChar == '_') {
- shouldConvertNextCharToLower = false;
- } else if (shouldConvertNextCharToLower) {
- builder.append(Character.toLowerCase(currentChar));
- } else {
- builder.append(Character.toUpperCase(currentChar));
- shouldConvertNextCharToLower = true;
- }
- }
- return builder.toString();
- }
}