Compare commits
2 Commits
query-prov
...
8449578424
| Author | SHA1 | Date | |
|---|---|---|---|
| 8449578424 | |||
| 1adcc04efc |
47
cygnus-lib/pom.xml
Normal file
47
cygnus-lib/pom.xml
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.cygnus</groupId>
|
||||||
|
<artifactId>cygnus-parent</artifactId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<artifactId>cygnus-lib</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<name>Cygnus Shared Library</name>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>${lombok.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter</artifactId>
|
||||||
|
<version>${junit.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<annotationProcessorPaths>
|
||||||
|
<path>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>${lombok.version}</version>
|
||||||
|
</path>
|
||||||
|
</annotationProcessorPaths>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
71
cygnus-lib/src/main/java/lib/constants/ApplicationError.java
Normal file
71
cygnus-lib/src/main/java/lib/constants/ApplicationError.java
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
package lib.constants;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/** Canonical user-facing errors shared by Cygnus applications. */
|
||||||
|
public enum ApplicationError {
|
||||||
|
BAD_REQUEST(400, "HTTP-400", "Invalid request",
|
||||||
|
"Cygnus could not process the submitted request.",
|
||||||
|
"Review the supplied information and try again."),
|
||||||
|
SESSION_REQUIRED(401, "AUTH-401", "Sign in required",
|
||||||
|
"Your session is missing or has expired.",
|
||||||
|
"Sign in again to continue securely."),
|
||||||
|
ACCESS_DENIED(403, "AUTH-403", "Access denied",
|
||||||
|
"You do not have permission to open this page.",
|
||||||
|
"Contact your administrator if this feature should be available to you."),
|
||||||
|
PAGE_NOT_FOUND(404, "HTTP-404", "Page not found",
|
||||||
|
"The requested page could not be found.",
|
||||||
|
"Check the address or return to the application dashboard."),
|
||||||
|
METHOD_NOT_ALLOWED(405, "HTTP-405", "Action not allowed",
|
||||||
|
"This page does not support the requested action.",
|
||||||
|
"Return to the previous page and try an available action."),
|
||||||
|
CONFLICT(409, "HTTP-409", "Request conflict",
|
||||||
|
"The request conflicts with the current state of the data.",
|
||||||
|
"Refresh the page and try again."),
|
||||||
|
PAYLOAD_TOO_LARGE(413, "HTTP-413", "File is too large",
|
||||||
|
"The submitted content exceeds the permitted size.",
|
||||||
|
"Reduce the file size and try again."),
|
||||||
|
TOO_MANY_REQUESTS(429, "HTTP-429", "Too many requests",
|
||||||
|
"Cygnus has received too many requests in a short period.",
|
||||||
|
"Wait briefly before trying again."),
|
||||||
|
INTERNAL_SERVER_ERROR(500, "HTTP-500", "Something went wrong",
|
||||||
|
"Cygnus could not complete your request.",
|
||||||
|
"Try again. If the issue continues, share the reference ID with support."),
|
||||||
|
BAD_GATEWAY(502, "HTTP-502", "Service response unavailable",
|
||||||
|
"A required service returned an invalid response.",
|
||||||
|
"Try again shortly. If the issue continues, contact support."),
|
||||||
|
SERVICE_UNAVAILABLE(503, "HTTP-503", "Service temporarily unavailable",
|
||||||
|
"A required Cygnus service is currently unavailable.",
|
||||||
|
"Wait briefly and try again."),
|
||||||
|
GATEWAY_TIMEOUT(504, "HTTP-504", "Service response timed out",
|
||||||
|
"A required service took too long to respond.",
|
||||||
|
"Try the request again shortly.");
|
||||||
|
|
||||||
|
private final int httpStatus;
|
||||||
|
private final String code;
|
||||||
|
private final String title;
|
||||||
|
private final String message;
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
ApplicationError(
|
||||||
|
int httpStatus, String code, String title, String message, String description) {
|
||||||
|
this.httpStatus = httpStatus;
|
||||||
|
this.code = code;
|
||||||
|
this.title = title;
|
||||||
|
this.message = message;
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ApplicationError fromHttpStatus(int status) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(error -> error.httpStatus == status)
|
||||||
|
.findFirst()
|
||||||
|
.orElse(INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHttpStatus() { return httpStatus; }
|
||||||
|
public String getCode() { return code; }
|
||||||
|
public String getTitle() { return title; }
|
||||||
|
public String getMessage() { return message; }
|
||||||
|
public String getDescription() { return description; }
|
||||||
|
}
|
||||||
23
cygnus-lib/src/main/java/lib/models/CasePunching.java
Normal file
23
cygnus-lib/src/main/java/lib/models/CasePunching.java
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package lib.models;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class CasePunching {
|
||||||
|
private ErrorDetails errorDetails;
|
||||||
|
private Map<String, String> optionsl;
|
||||||
|
private Map<String, List<Option>> options;
|
||||||
|
private List<String> visibleSections;
|
||||||
|
private Integer portfolioId;
|
||||||
|
private Integer formMode;
|
||||||
|
private String userId;
|
||||||
|
private String dynamicFields;
|
||||||
|
private String dynamicHtml;
|
||||||
|
private String verificationCaseId;
|
||||||
|
private String documentCaseId;
|
||||||
|
}
|
||||||
58
cygnus-lib/src/main/java/lib/models/ErrorDetails.java
Normal file
58
cygnus-lib/src/main/java/lib/models/ErrorDetails.java
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package lib.models;
|
||||||
|
|
||||||
|
import lib.constants.ApplicationError;
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.UUID;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/** Dependency-free error information shared across Cygnus modules. */
|
||||||
|
@Getter
|
||||||
|
public final class ErrorDetails implements Serializable {
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final int httpStatus;
|
||||||
|
private final String errorCode;
|
||||||
|
private final String title;
|
||||||
|
private final String message;
|
||||||
|
private final String description;
|
||||||
|
private final String referenceId;
|
||||||
|
private final Instant timestamp;
|
||||||
|
|
||||||
|
public ErrorDetails(ApplicationError error) {
|
||||||
|
this(error.getHttpStatus(), error.getCode(), error.getTitle(),
|
||||||
|
error.getMessage(), error.getDescription(),
|
||||||
|
UUID.randomUUID().toString(), Instant.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
private ErrorDetails(
|
||||||
|
int httpStatus,
|
||||||
|
String errorCode,
|
||||||
|
String title,
|
||||||
|
String message,
|
||||||
|
String description,
|
||||||
|
String referenceId,
|
||||||
|
Instant timestamp) {
|
||||||
|
if (httpStatus < 400 || httpStatus > 599) {
|
||||||
|
throw new IllegalArgumentException("HTTP error status must be between 400 and 599");
|
||||||
|
}
|
||||||
|
this.httpStatus = httpStatus;
|
||||||
|
this.errorCode = required(errorCode, "errorCode");
|
||||||
|
this.title = required(title, "title");
|
||||||
|
this.message = required(message, "message");
|
||||||
|
this.description = description == null ? "" : description.trim();
|
||||||
|
this.referenceId = required(referenceId, "referenceId");
|
||||||
|
this.timestamp = Objects.requireNonNull(timestamp, "timestamp");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String required(String value, String name) {
|
||||||
|
if (value == null || value.isBlank()) {
|
||||||
|
throw new IllegalArgumentException(name + " is required");
|
||||||
|
}
|
||||||
|
return value.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
12
cygnus-lib/src/main/java/lib/models/Option.java
Normal file
12
cygnus-lib/src/main/java/lib/models/Option.java
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package lib.models;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class Option {
|
||||||
|
private Object value;
|
||||||
|
private String label;
|
||||||
|
private String group;
|
||||||
|
}
|
||||||
22
cygnus-lib/src/test/java/lib/models/ErrorDetailsTest.java
Normal file
22
cygnus-lib/src/test/java/lib/models/ErrorDetailsTest.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package lib.models;
|
||||||
|
|
||||||
|
import lib.constants.ApplicationError;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class ErrorDetailsTest {
|
||||||
|
@Test
|
||||||
|
void createsAReusableErrorContract() {
|
||||||
|
ErrorDetails details = new ErrorDetails(ApplicationError.ACCESS_DENIED);
|
||||||
|
assertEquals(403, details.getHttpStatus());
|
||||||
|
assertEquals("AUTH-403", details.getErrorCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void mapsHttpStatusToCanonicalError() {
|
||||||
|
assertEquals(ApplicationError.PAGE_NOT_FOUND, ApplicationError.fromHttpStatus(404));
|
||||||
|
assertEquals(ApplicationError.INTERNAL_SERVER_ERROR,
|
||||||
|
ApplicationError.fromHttpStatus(599));
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
cygnus-lib/target/classes/lib/constants/ApplicationError.class
Normal file
BIN
cygnus-lib/target/classes/lib/constants/ApplicationError.class
Normal file
Binary file not shown.
BIN
cygnus-lib/target/classes/lib/models/CasePunching.class
Normal file
BIN
cygnus-lib/target/classes/lib/models/CasePunching.class
Normal file
Binary file not shown.
BIN
cygnus-lib/target/classes/lib/models/ErrorDetails.class
Normal file
BIN
cygnus-lib/target/classes/lib/models/ErrorDetails.class
Normal file
Binary file not shown.
BIN
cygnus-lib/target/classes/lib/models/Option.class
Normal file
BIN
cygnus-lib/target/classes/lib/models/Option.class
Normal file
Binary file not shown.
BIN
cygnus-lib/target/cygnus-lib-1.0.0-SNAPSHOT.jar
Normal file
BIN
cygnus-lib/target/cygnus-lib-1.0.0-SNAPSHOT.jar
Normal file
Binary file not shown.
3
cygnus-lib/target/maven-archiver/pom.properties
Normal file
3
cygnus-lib/target/maven-archiver/pom.properties
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
artifactId=cygnus-lib
|
||||||
|
groupId=com.cygnus
|
||||||
|
version=1.0.0-SNAPSHOT
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
lib/models/ErrorDetails.class
|
||||||
|
lib/models/CasePunching.class
|
||||||
|
lib/constants/ApplicationError.class
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
/Users/maddy/Projects/cygnus/matrix/cygnus-lib/src/main/java/lib/constants/ApplicationError.java
|
||||||
|
/Users/maddy/Projects/cygnus/matrix/cygnus-lib/src/main/java/lib/models/CasePunching.java
|
||||||
|
/Users/maddy/Projects/cygnus/matrix/cygnus-lib/src/main/java/lib/models/ErrorDetails.java
|
||||||
|
/Users/maddy/Projects/cygnus/matrix/cygnus-lib/src/main/java/lib/models/Option.java
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
lib/models/ErrorDetailsTest.class
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
/Users/maddy/Projects/cygnus/matrix/cygnus-lib/src/test/java/lib/models/ErrorDetailsTest.java
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuite xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report.xsd" version="3.0.2" name="lib.models.ErrorDetailsTest" time="0.024" tests="2" errors="0" skipped="0" failures="0">
|
||||||
|
<properties>
|
||||||
|
<property name="java.specification.version" value="25"/>
|
||||||
|
<property name="sun.jnu.encoding" value="UTF-8"/>
|
||||||
|
<property name="java.class.path" value="/Users/maddy/Projects/cygnus/matrix/cygnus-lib/target/test-classes:/Users/maddy/Projects/cygnus/matrix/cygnus-lib/target/classes:/Users/maddy/.m2/repository/org/projectlombok/lombok/1.18.46/lombok-1.18.46.jar:/Users/maddy/.m2/repository/org/junit/jupiter/junit-jupiter/5.12.2/junit-jupiter-5.12.2.jar:/Users/maddy/.m2/repository/org/junit/jupiter/junit-jupiter-api/5.12.2/junit-jupiter-api-5.12.2.jar:/Users/maddy/.m2/repository/org/opentest4j/opentest4j/1.3.0/opentest4j-1.3.0.jar:/Users/maddy/.m2/repository/org/junit/platform/junit-platform-commons/1.12.2/junit-platform-commons-1.12.2.jar:/Users/maddy/.m2/repository/org/apiguardian/apiguardian-api/1.1.2/apiguardian-api-1.1.2.jar:/Users/maddy/.m2/repository/org/junit/jupiter/junit-jupiter-params/5.12.2/junit-jupiter-params-5.12.2.jar:/Users/maddy/.m2/repository/org/junit/jupiter/junit-jupiter-engine/5.12.2/junit-jupiter-engine-5.12.2.jar:/Users/maddy/.m2/repository/org/junit/platform/junit-platform-engine/1.12.2/junit-platform-engine-1.12.2.jar:"/>
|
||||||
|
<property name="java.vm.vendor" value="Homebrew"/>
|
||||||
|
<property name="sun.arch.data.model" value="64"/>
|
||||||
|
<property name="java.vendor.url" value="https://github.com/Homebrew/homebrew-core/issues"/>
|
||||||
|
<property name="os.name" value="Mac OS X"/>
|
||||||
|
<property name="java.vm.specification.version" value="25"/>
|
||||||
|
<property name="sun.java.launcher" value="SUN_STANDARD"/>
|
||||||
|
<property name="user.country" value="US"/>
|
||||||
|
<property name="sun.boot.library.path" value="/opt/homebrew/Cellar/openjdk/25.0.2/libexec/openjdk.jdk/Contents/Home/lib"/>
|
||||||
|
<property name="sun.java.command" value="/Users/maddy/Projects/cygnus/matrix/cygnus-lib/target/surefire/surefirebooter-20260801204253825_3.jar /Users/maddy/Projects/cygnus/matrix/cygnus-lib/target/surefire 2026-08-01T20-42-53_787-jvmRun1 surefire-20260801204253825_1tmp surefire_0-20260801204253825_2tmp"/>
|
||||||
|
<property name="http.nonProxyHosts" value="local|*.local|169.254/16|*.169.254/16"/>
|
||||||
|
<property name="jdk.debug" value="release"/>
|
||||||
|
<property name="surefire.test.class.path" value="/Users/maddy/Projects/cygnus/matrix/cygnus-lib/target/test-classes:/Users/maddy/Projects/cygnus/matrix/cygnus-lib/target/classes:/Users/maddy/.m2/repository/org/projectlombok/lombok/1.18.46/lombok-1.18.46.jar:/Users/maddy/.m2/repository/org/junit/jupiter/junit-jupiter/5.12.2/junit-jupiter-5.12.2.jar:/Users/maddy/.m2/repository/org/junit/jupiter/junit-jupiter-api/5.12.2/junit-jupiter-api-5.12.2.jar:/Users/maddy/.m2/repository/org/opentest4j/opentest4j/1.3.0/opentest4j-1.3.0.jar:/Users/maddy/.m2/repository/org/junit/platform/junit-platform-commons/1.12.2/junit-platform-commons-1.12.2.jar:/Users/maddy/.m2/repository/org/apiguardian/apiguardian-api/1.1.2/apiguardian-api-1.1.2.jar:/Users/maddy/.m2/repository/org/junit/jupiter/junit-jupiter-params/5.12.2/junit-jupiter-params-5.12.2.jar:/Users/maddy/.m2/repository/org/junit/jupiter/junit-jupiter-engine/5.12.2/junit-jupiter-engine-5.12.2.jar:/Users/maddy/.m2/repository/org/junit/platform/junit-platform-engine/1.12.2/junit-platform-engine-1.12.2.jar:"/>
|
||||||
|
<property name="sun.cpu.endian" value="little"/>
|
||||||
|
<property name="user.home" value="/Users/maddy"/>
|
||||||
|
<property name="user.language" value="en"/>
|
||||||
|
<property name="java.specification.vendor" value="Oracle Corporation"/>
|
||||||
|
<property name="java.version.date" value="2026-01-20"/>
|
||||||
|
<property name="java.home" value="/opt/homebrew/Cellar/openjdk/25.0.2/libexec/openjdk.jdk/Contents/Home"/>
|
||||||
|
<property name="file.separator" value="/"/>
|
||||||
|
<property name="basedir" value="/Users/maddy/Projects/cygnus/matrix/cygnus-lib"/>
|
||||||
|
<property name="java.vm.compressedOopsMode" value="Zero based"/>
|
||||||
|
<property name="line.separator" value=" "/>
|
||||||
|
<property name="java.vm.specification.vendor" value="Oracle Corporation"/>
|
||||||
|
<property name="java.specification.name" value="Java Platform API Specification"/>
|
||||||
|
<property name="apple.awt.application.name" value="ForkedBooter"/>
|
||||||
|
<property name="surefire.real.class.path" value="/Users/maddy/Projects/cygnus/matrix/cygnus-lib/target/surefire/surefirebooter-20260801204253825_3.jar"/>
|
||||||
|
<property name="sun.management.compiler" value="HotSpot 64-Bit Tiered Compilers"/>
|
||||||
|
<property name="ftp.nonProxyHosts" value="local|*.local|169.254/16|*.169.254/16"/>
|
||||||
|
<property name="java.runtime.version" value="25.0.2"/>
|
||||||
|
<property name="user.name" value="maddy"/>
|
||||||
|
<property name="stdout.encoding" value="UTF-8"/>
|
||||||
|
<property name="path.separator" value=":"/>
|
||||||
|
<property name="os.version" value="26.5.2"/>
|
||||||
|
<property name="java.runtime.name" value="OpenJDK Runtime Environment"/>
|
||||||
|
<property name="file.encoding" value="UTF-8"/>
|
||||||
|
<property name="java.vm.name" value="OpenJDK 64-Bit Server VM"/>
|
||||||
|
<property name="java.vendor.version" value="Homebrew"/>
|
||||||
|
<property name="localRepository" value="/Users/maddy/.m2/repository"/>
|
||||||
|
<property name="java.vendor.url.bug" value="https://github.com/Homebrew/homebrew-core/issues"/>
|
||||||
|
<property name="java.io.tmpdir" value="/var/folders/1l/36214rdn79755j30lcnmgsqh0000gn/T/"/>
|
||||||
|
<property name="java.version" value="25.0.2"/>
|
||||||
|
<property name="user.dir" value="/Users/maddy/Projects/cygnus/matrix/cygnus-lib"/>
|
||||||
|
<property name="os.arch" value="aarch64"/>
|
||||||
|
<property name="java.vm.specification.name" value="Java Virtual Machine Specification"/>
|
||||||
|
<property name="native.encoding" value="UTF-8"/>
|
||||||
|
<property name="java.library.path" value="/Users/maddy/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:."/>
|
||||||
|
<property name="java.vm.info" value="mixed mode, sharing"/>
|
||||||
|
<property name="stderr.encoding" value="UTF-8"/>
|
||||||
|
<property name="java.vendor" value="Homebrew"/>
|
||||||
|
<property name="java.vm.version" value="25.0.2"/>
|
||||||
|
<property name="stdin.encoding" value="UTF-8"/>
|
||||||
|
<property name="sun.io.unicode.encoding" value="UnicodeBig"/>
|
||||||
|
<property name="socksNonProxyHosts" value="local|*.local|169.254/16|*.169.254/16"/>
|
||||||
|
<property name="java.class.version" value="69.0"/>
|
||||||
|
</properties>
|
||||||
|
<testcase name="mapsHttpStatusToCanonicalError" classname="lib.models.ErrorDetailsTest" time="0.008"/>
|
||||||
|
<testcase name="createsAReusableErrorContract" classname="lib.models.ErrorDetailsTest" time="0.007"/>
|
||||||
|
</testsuite>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Test set: lib.models.ErrorDetailsTest
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.024 s -- in lib.models.ErrorDetailsTest
|
||||||
BIN
cygnus-lib/target/test-classes/lib/models/ErrorDetailsTest.class
Normal file
BIN
cygnus-lib/target/test-classes/lib/models/ErrorDetailsTest.class
Normal file
Binary file not shown.
@@ -10,7 +10,7 @@
|
|||||||
<mvc:annotation-driven/>
|
<mvc:annotation-driven/>
|
||||||
|
|
||||||
<!-- Scan for annotation based controllers -->
|
<!-- Scan for annotation based controllers -->
|
||||||
<context:component-scan base-package="matrix.nimble" />
|
<context:component-scan base-package="matrix.nimble,matrix.services" />
|
||||||
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
|
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
|
||||||
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
|
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
|
||||||
<property name="prefix" value="/WEB-INF/app/" />
|
<property name="prefix" value="/WEB-INF/app/" />
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
<link href="/matrix/css/matrix-shell-v2.css?v=7" rel="stylesheet" type="text/css" />
|
<link href="/matrix/css/matrix-shell-v2.css?v=7" rel="stylesheet" type="text/css" />
|
||||||
<link href="/matrix/css/tool-workspace-v3.css?v=2" rel="stylesheet" type="text/css" />
|
<link href="/matrix/css/tool-workspace-v3.css?v=2" rel="stylesheet" type="text/css" />
|
||||||
<link href="/matrix/css/punch-workspace-v3.css?v=1" rel="stylesheet" type="text/css" />
|
<link href="/matrix/css/punch-workspace-v3.css?v=1" rel="stylesheet" type="text/css" />
|
||||||
<link href="/matrix/css/add-cases-v4.css?v=1" rel="stylesheet" type="text/css" />
|
<link href="/matrix/css/add-cases-v4.css?v=5" rel="stylesheet" type="text/css" />
|
||||||
<script src="/matrix/js/matrix-dialog-child.js" type="text/javascript"></script>
|
<script src="/matrix/js/matrix-dialog-child.js" type="text/javascript"></script>
|
||||||
<script src="/matrix/js/bootstrap-5.3.8.bundle.min.js" defer></script>
|
<script src="/matrix/js/bootstrap-5.3.8.bundle.min.js" defer></script>
|
||||||
<script src="/matrix/js/matrix-shell-v2.js" defer></script>
|
<script src="/matrix/js/matrix-shell-v2.js" defer></script>
|
||||||
@@ -591,7 +591,7 @@
|
|||||||
<div id="section6">
|
<div id="section6">
|
||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<img class="matrix-title-icon" src="/matrix/images/othdet.png" />
|
<img class="matrix-title-icon" src="/matrix/images/edit_form.png" alt="" />
|
||||||
<span class="matrix-title-text">Other Details</span>
|
<span class="matrix-title-text">Other Details</span>
|
||||||
</div>
|
</div>
|
||||||
<!-- -->
|
<!-- -->
|
||||||
|
|||||||
@@ -3,6 +3,12 @@
|
|||||||
<%@page language="java" session="true" %>
|
<%@page language="java" session="true" %>
|
||||||
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
|
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
|
||||||
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
|
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
|
||||||
|
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
|
||||||
|
<c:set var="pageFormMode" value="${not empty model ? model.formMode : formmode}" />
|
||||||
|
<c:set var="pagePortfolioId" value="${not empty model ? model.portfolioId : portfolio_id}" />
|
||||||
|
<c:set var="pageDynamicFields" value="${not empty model ? model.dynamicFields : dynamicfields}" />
|
||||||
|
<c:set var="pageDocumentCaseId" value="${not empty model ? model.documentCaseId : duuid}" />
|
||||||
|
<c:set var="pageUserId" value="${not empty model ? model.userId : usid}" />
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
@@ -14,8 +20,8 @@
|
|||||||
<script language="javascript" src="/matrix/js/lib/jsfuncs.js" type="text/javascript"></script>
|
<script language="javascript" src="/matrix/js/lib/jsfuncs.js" type="text/javascript"></script>
|
||||||
<script language="javascript" src="/matrix/js/ui/msgdialog.js" type="text/javascript"></script>
|
<script language="javascript" src="/matrix/js/ui/msgdialog.js" type="text/javascript"></script>
|
||||||
<script language="javascript" src="/matrix/js/ui/select.js" type="text/javascript"></script>
|
<script language="javascript" src="/matrix/js/ui/select.js" type="text/javascript"></script>
|
||||||
<script language="javascript" src="/matrix/js/appjs/punching.js?ver=4" type="text/javascript"></script>
|
<script language="javascript" src="/matrix/js/appjs/punching.js?ver=6" type="text/javascript"></script>
|
||||||
<script language="javascript" src="/matrix/js/validator.js" type="text/javascript"></script>
|
<script language="javascript" src="/matrix/js/validator.js?ver=2" type="text/javascript"></script>
|
||||||
<script language="javascript" src="/matrix/js/ajax.js" type="text/javascript"></script>
|
<script language="javascript" src="/matrix/js/ajax.js" type="text/javascript"></script>
|
||||||
<script language="javascript" src="/matrix/js/ajax-dynamic-list.js?ver=1" type="text/javascript"></script>
|
<script language="javascript" src="/matrix/js/ajax-dynamic-list.js?ver=1" type="text/javascript"></script>
|
||||||
|
|
||||||
@@ -25,55 +31,64 @@
|
|||||||
<link href="/matrix/css/select.css" rel="stylesheet" type="text/css" />
|
<link href="/matrix/css/select.css" rel="stylesheet" type="text/css" />
|
||||||
<link href="/matrix/css/table.css" rel="stylesheet" type="text/css" />
|
<link href="/matrix/css/table.css" rel="stylesheet" type="text/css" />
|
||||||
<link href="/matrix/css/autocomplete.css" rel="stylesheet" type="text/css" />
|
<link href="/matrix/css/autocomplete.css" rel="stylesheet" type="text/css" />
|
||||||
<link href="/matrix/css/bootstrap-5.3.8.min.css" rel="stylesheet" type="text/css" />
|
<link href="/matrix/css/bootstrap-5.3.8.min.css" rel="stylesheet" type="text/css" />
|
||||||
<link href="/matrix/css/matrix-v2.css?v=6" rel="stylesheet" type="text/css" />
|
<link href="/matrix/css/matrix-v2.css?v=6" rel="stylesheet" type="text/css" />
|
||||||
<link href="/matrix/css/matrix-shell-v2.css?v=7" rel="stylesheet" type="text/css" />
|
<link href="/matrix/css/matrix-shell-v2.css?v=7" rel="stylesheet" type="text/css" />
|
||||||
<link href="/matrix/css/tool-workspace-v3.css?v=2" rel="stylesheet" type="text/css" />
|
<link href="/matrix/css/tool-workspace-v3.css?v=2" rel="stylesheet" type="text/css" />
|
||||||
<link href="/matrix/css/punch-workspace-v3.css?v=1" rel="stylesheet" type="text/css" />
|
<link href="/matrix/css/punch-workspace-v3.css?v=1" rel="stylesheet" type="text/css" />
|
||||||
<link href="/matrix/css/add-cases-v4.css?v=1" rel="stylesheet" type="text/css" />
|
<link href="/matrix/css/add-cases-v4.css?v=5" rel="stylesheet" type="text/css" />
|
||||||
<script src="/matrix/js/bootstrap-5.3.8.bundle.min.js" defer></script>
|
<script src="/matrix/js/bootstrap-5.3.8.bundle.min.js" defer></script>
|
||||||
<script src="/matrix/js/matrix-shell-v2.js" defer></script>
|
<script src="/matrix/js/matrix-shell-v2.js" defer></script>
|
||||||
<link href="/matrix/css/matrix-frame-dialog.css?v=6" rel="stylesheet" type="text/css" />
|
<link href="/matrix/css/matrix-frame-dialog.css?v=6" rel="stylesheet" type="text/css" />
|
||||||
<script src="/matrix/js/matrix-frame-dialog.js?v=2" defer></script>
|
<script src="/matrix/js/matrix-frame-dialog.js?v=2" defer></script>
|
||||||
<script src="/matrix/js/matrix-accessibility-v1.js?v=1" defer></script>
|
<script src="/matrix/js/matrix-accessibility-v1.js?v=1" defer></script>
|
||||||
<link href="/matrix/css/matrix-theme-v2.css?v=4" rel="stylesheet" type="text/css" />
|
<link href="/matrix/css/matrix-theme-v2.css?v=4" rel="stylesheet" type="text/css" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="matrix-v2 matrix-shell matrix-tool-workspace matrix-punch-workspace matrix-add-cases">
|
<body class="matrix-v2 matrix-shell matrix-tool-workspace matrix-punch-workspace matrix-add-cases">
|
||||||
<div id='PageFrame'>
|
<div id='PageFrame'>
|
||||||
<!-- Title Bar -->
|
<!-- Title Bar -->
|
||||||
<%@ include file="/WEB-INF/app/fragments/app-title.jspf" %>
|
<%@ include file="/WEB-INF/app/fragments/app-title.jspf" %>
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<c:if test="${formmode!=2}">
|
<c:if test="${pageFormMode!=2}">
|
||||||
<!-- Dynamic Menu -->
|
<!-- Dynamic Menu -->
|
||||||
<nav class="matrix-shell__navigation" aria-label="Primary navigation">
|
<nav class="matrix-shell__navigation" aria-label="Primary navigation">
|
||||||
<c:out value="${Sessvals.menuHtml}" escapeXml="false" />
|
<c:out value="${Sessvals.menuHtml}" escapeXml="false" />
|
||||||
</nav>
|
</nav>
|
||||||
<!-- -->
|
<!-- -->
|
||||||
</c:if>
|
</c:if>
|
||||||
<div id="formcontainer" class="matrix-tool-workspace__content">
|
<div id="formcontainer" class="matrix-tool-workspace__content">
|
||||||
<form method="post" name="casedetails" id="casedetails" >
|
<form method="post" name="casedetails" id="casedetails" >
|
||||||
<!-- Common Details (Section1) Visible for all portfolios-->
|
<!-- Common Details (Section1) Visible for all portfolios-->
|
||||||
<div>
|
<div>
|
||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<div class="title matrix-form-title">
|
<div class="title matrix-form-title">
|
||||||
<img class="matrix-title-icon" src="/matrix/images/commondet.png" align="absmiddle" />
|
<img class="matrix-title-icon" src="/matrix/images/commondet.png" align="absmiddle" />
|
||||||
<span class="matrix-title-text matrix-form-title__heading">Common Details <span id='recfound'></span></span>
|
<span class="matrix-title-text matrix-form-title__heading">Common Details <span id='recfound'></span></span>
|
||||||
<label class="matrix-form-title__field">Skip To <input type="text" class="textbox" style="width:30px" onkeypress="return NumberOnly(event)" onblur="GotoRecord(this,'recno')"></label>
|
<label class="matrix-form-title__field">Skip To <input type="text" class="textbox" style="width:50px" onkeypress="return NumberOnly(event)" onblur="GotoRecord(this,'recno')"></label>
|
||||||
<label class="matrix-form-title__field">Search By File No <input type="text" class="textbox" style="width:100px" onblur="GotoRecord(this,'query')"></label>
|
<label class="matrix-form-title__field">Search By File No <input type="text" class="textbox" style="width:150px" onblur="GotoRecord(this,'query')"></label>
|
||||||
|
|
||||||
<!-- Checkbox for AUTO CUT diabled for now -->
|
<!-- Checkbox for AUTO CUT diabled for now -->
|
||||||
<label class="matrix-form-title__check"><input type="checkbox" name="autocut" checked id="autocut" /> Auto Cut-Off</label>
|
<label class="matrix-form-title__check"><input type="checkbox" name="autocut" checked id="autocut" /> Auto Cut-Off</label>
|
||||||
<c:if test="${formmode==2}">
|
<c:if test="${pageFormMode==2}">
|
||||||
<input type="hidden" id="portfolio_id" name="portfolio_id" value="-1" />
|
<input type="hidden" id="portfolio_id" name="portfolioId" value="${pagePortfolioId}" />
|
||||||
</c:if>
|
</c:if>
|
||||||
<c:if test="${formmode!=2}">
|
<c:if test="${pageFormMode!=2}">
|
||||||
<div class="divselect matrix-form-title__end" id="divportfolio" style="width:217px;">
|
<div class="divselect matrix-form-title__end" id="divportfolio" style="width:297px;">
|
||||||
<select id="portfolio_id" name="portfolio_id" style="width:235px" onchange="SubmitForm('caseadd','_parent','casedetails')">
|
<select id="portfolio_id" name="portfolioId" style="width:315px" onchange="SubmitForm('caseadd','_parent','casedetails')">
|
||||||
<option value="-1" selected >SELECT PORTFOLIO</option>
|
<option value="-1" selected >SELECT PORTFOLIO</option>
|
||||||
<c:forEach items="${portlist}" var="port">
|
<c:choose>
|
||||||
<option value="${port[0]}">${port[1]}</option>
|
<c:when test="${not empty model}">
|
||||||
</c:forEach>
|
<c:forEach items="${model.options['portfolio.']}" var="port">
|
||||||
|
<option value="${port.value}"><c:out value="${port.label}" /></option>
|
||||||
|
</c:forEach>
|
||||||
|
</c:when>
|
||||||
|
<c:otherwise>
|
||||||
|
<c:forEach items="${portlist}" var="port">
|
||||||
|
<option value="${port[0]}"><c:out value="${port[1]}" /></option>
|
||||||
|
</c:forEach>
|
||||||
|
</c:otherwise>
|
||||||
|
</c:choose>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</c:if>
|
</c:if>
|
||||||
@@ -116,9 +131,14 @@
|
|||||||
<div class="divselect" id="divbranch" style="width:135px;">
|
<div class="divselect" id="divbranch" style="width:135px;">
|
||||||
<select id="bank_branch_id" name="bank_branch_id" style="width:153px" onblur="validate(this,'t','');">
|
<select id="bank_branch_id" name="bank_branch_id" style="width:153px" onblur="validate(this,'t','');">
|
||||||
<option value="-1" selected >SELECT</option>
|
<option value="-1" selected >SELECT</option>
|
||||||
<c:forEach items="${branchlist}" var="brnch">
|
<c:choose>
|
||||||
<option value="${brnch[0]}">${brnch[1]}</option>
|
<c:when test="${not empty model}">
|
||||||
</c:forEach>
|
<c:forEach items="${model.options}" var="option"><c:if test="${fn:startsWith(option.key, 'branch.')}">
|
||||||
|
<option value="${fn:substringAfter(option.key, 'branch.')}"><c:out value="${option.value}" /></option>
|
||||||
|
</c:if></c:forEach>
|
||||||
|
</c:when>
|
||||||
|
<c:otherwise><c:forEach items="${branchlist}" var="brnch"><option value="${brnch[0]}"><c:out value="${brnch[1]}" /></option></c:forEach></c:otherwise>
|
||||||
|
</c:choose>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -131,9 +151,10 @@
|
|||||||
<div class="divselect" id="divproduct" style="width:132px;">
|
<div class="divselect" id="divproduct" style="width:132px;">
|
||||||
<select id="product" name="product" style="width:150px" onblur="validate(this,'t','');">
|
<select id="product" name="product" style="width:150px" onblur="validate(this,'t','');">
|
||||||
<option value="-1" selected >SELECT</option>
|
<option value="-1" selected >SELECT</option>
|
||||||
<c:forEach items="${prodlist}" var="prod">
|
<c:choose>
|
||||||
<option value="${prod[0]}">${prod[1]}</option>
|
<c:when test="${not empty model}"><c:forEach items="${model.options}" var="option"><c:if test="${fn:startsWith(option.key, 'product.')}"><option value="${fn:substringAfter(option.key, 'product.')}"><c:out value="${option.value}" /></option></c:if></c:forEach></c:when>
|
||||||
</c:forEach>
|
<c:otherwise><c:forEach items="${prodlist}" var="prod"><option value="${prod[0]}"><c:out value="${prod[1]}" /></option></c:forEach></c:otherwise>
|
||||||
|
</c:choose>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -162,9 +183,10 @@
|
|||||||
<div class="divselect" id="divapptype" style="width:135px;">
|
<div class="divselect" id="divapptype" style="width:135px;">
|
||||||
<select id="apptype" name="apptype" style="width:153px" onchange="ToggleChks((this.value.toUpperCase()!='APPLICANT' && this.value.toUpperCase()!='-1'),'sradd!C0L!soadd!C0L!spadd!C0L!','!C0L!')" onblur="validate(this,'t','');">
|
<select id="apptype" name="apptype" style="width:153px" onchange="ToggleChks((this.value.toUpperCase()!='APPLICANT' && this.value.toUpperCase()!='-1'),'sradd!C0L!soadd!C0L!spadd!C0L!','!C0L!')" onblur="validate(this,'t','');">
|
||||||
<option value="-1" selected>SELECT</option>
|
<option value="-1" selected>SELECT</option>
|
||||||
<c:forEach items="${typelist}" var="type">
|
<c:choose>
|
||||||
<option value="${type[0]}">${type[1]}</option>
|
<c:when test="${not empty model}"><c:forEach items="${model.options}" var="option"><c:if test="${fn:startsWith(option.key, 'applicationType.')}"><option value="${fn:substringAfter(option.key, 'applicationType.')}"><c:out value="${option.value}" /></option></c:if></c:forEach></c:when>
|
||||||
</c:forEach>
|
<c:otherwise><c:forEach items="${typelist}" var="type"><option value="${type[0]}"><c:out value="${type[1]}" /></option></c:forEach></c:otherwise>
|
||||||
|
</c:choose>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -177,9 +199,10 @@
|
|||||||
<div class="divselect" id="divcategory" style="width:115px;">
|
<div class="divselect" id="divcategory" style="width:115px;">
|
||||||
<select id="category" name="category" style="width:133px">
|
<select id="category" name="category" style="width:133px">
|
||||||
<option value="-1" selected>SELECT</option>
|
<option value="-1" selected>SELECT</option>
|
||||||
<c:forEach items="${catlist}" var="cat">
|
<c:choose>
|
||||||
<option value="${cat[0]}">${cat[1]}</option>
|
<c:when test="${not empty model}"><c:forEach items="${model.options}" var="option"><c:if test="${fn:startsWith(option.key, 'category.')}"><option value="${fn:substringAfter(option.key, 'category.')}"><c:out value="${option.value}" /></option></c:if></c:forEach></c:when>
|
||||||
</c:forEach>
|
<c:otherwise><c:forEach items="${catlist}" var="cat"><option value="${cat[0]}"><c:out value="${cat[1]}" /></option></c:forEach></c:otherwise>
|
||||||
|
</c:choose>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -287,9 +310,10 @@
|
|||||||
<select id="rcity" name="colr_citylist" style="width:128px" onblur="HandleBlur(this)" >
|
<select id="rcity" name="colr_citylist" style="width:128px" onblur="HandleBlur(this)" >
|
||||||
<option value="-1">Select</option>
|
<option value="-1">Select</option>
|
||||||
<option value="Unknown">Unknown</option>
|
<option value="Unknown">Unknown</option>
|
||||||
<c:forEach items="${citylist}" var="city">
|
<c:choose>
|
||||||
<option value="${city[0]}">${city[1]}</option>
|
<c:when test="${not empty model}"><c:forEach items="${model.options}" var="option"><c:if test="${fn:startsWith(option.key, 'city.')}"><option value="${fn:substringAfter(option.key, 'city.')}"><c:out value="${option.value}" /></option></c:if></c:forEach></c:when>
|
||||||
</c:forEach>
|
<c:otherwise><c:forEach items="${citylist}" var="city"><option value="${city[0]}"><c:out value="${city[1]}" /></option></c:forEach></c:otherwise>
|
||||||
|
</c:choose>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -347,7 +371,7 @@
|
|||||||
<span class="matrix-title-text">Office Details</span>
|
<span class="matrix-title-text">Office Details</span>
|
||||||
<div class="divchk" id="ctrldiv">
|
<div class="divchk" id="ctrldiv">
|
||||||
<input type="checkbox" id="ov" onclick="HandleClick(this)" />OVR
|
<input type="checkbox" id="ov" onclick="HandleClick(this)" />OVR
|
||||||
<input type="checkbox" id="rco" style="display:none" onclick="HandleClick(this)" /><span id="rco">RCO</span>
|
<input type="checkbox" id="rco" style="display:none" onclick="HandleClick(this)" /><span id="rco">RCO </span>
|
||||||
<input type="checkbox" id="soadd" onclick="return FindSameDet(this,'O','ophone')" /><span id="soadd">Same Office</span>
|
<input type="checkbox" id="soadd" onclick="return FindSameDet(this,'O','ophone')" /><span id="soadd">Same Office</span>
|
||||||
<input type="checkbox" id="otv" onclick="HandleClick(this)" /><span id="otv">OTV</span>
|
<input type="checkbox" id="otv" onclick="HandleClick(this)" /><span id="otv">OTV</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -404,9 +428,10 @@
|
|||||||
<select id="ocity" name="colo_citylist" style="width:128px" onblur="HandleBlur(this)" >
|
<select id="ocity" name="colo_citylist" style="width:128px" onblur="HandleBlur(this)" >
|
||||||
<option value="-1">Select</option>
|
<option value="-1">Select</option>
|
||||||
<option value="Unknown">Unknown</option>
|
<option value="Unknown">Unknown</option>
|
||||||
<c:forEach items="${citylist}" var="city">
|
<c:choose>
|
||||||
<option value="${city[0]}">${city[1]}</option>
|
<c:when test="${not empty model}"><c:forEach items="${model.options}" var="option"><c:if test="${fn:startsWith(option.key, 'city.')}"><option value="${fn:substringAfter(option.key, 'city.')}"><c:out value="${option.value}" /></option></c:if></c:forEach></c:when>
|
||||||
</c:forEach>
|
<c:otherwise><c:forEach items="${citylist}" var="city"><option value="${city[0]}"><c:out value="${city[1]}" /></option></c:forEach></c:otherwise>
|
||||||
|
</c:choose>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -482,8 +507,8 @@
|
|||||||
<span class="matrix-title-text">Property Details</span>
|
<span class="matrix-title-text">Property Details</span>
|
||||||
<div class="divchk" id="ctrldiv">
|
<div class="divchk" id="ctrldiv">
|
||||||
<input type="checkbox" id="pv" onclick="HandleClick(this)" />PVR
|
<input type="checkbox" id="pv" onclick="HandleClick(this)" />PVR
|
||||||
<input type="checkbox" id="rcp" style="display:none" onclick="HandleClick(this)" /><span id="rcp">RCP</span>
|
<input type="checkbox" id="rcp" style="display:none" onclick="HandleClick(this)" /><span id="rcp">RCP </span>
|
||||||
<input type="checkbox" id="ocp" style="display:none" onclick="HandleClick(this)" /><span id="ocp">OCP</span>
|
<input type="checkbox" id="ocp" style="display:none" onclick="HandleClick(this)" /><span id="ocp">OCP </span>
|
||||||
<input type="checkbox" id="spadd" onclick="return FindSameDet(this,'P','ppincode')" /><span id="spadd">Same Property</span>
|
<input type="checkbox" id="spadd" onclick="return FindSameDet(this,'P','ppincode')" /><span id="spadd">Same Property</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -530,9 +555,10 @@
|
|||||||
<select id="pcity" name="colp_citylist" style="width:128px" onblur="HandleBlur(this)" >
|
<select id="pcity" name="colp_citylist" style="width:128px" onblur="HandleBlur(this)" >
|
||||||
<option value="-1">Select</option>
|
<option value="-1">Select</option>
|
||||||
<option value="Unknown">Unknown</option>
|
<option value="Unknown">Unknown</option>
|
||||||
<c:forEach items="${citylist}" var="city">
|
<c:choose>
|
||||||
<option value="${city[0]}">${city[1]}</option>
|
<c:when test="${not empty model}"><c:forEach items="${model.options}" var="option"><c:if test="${fn:startsWith(option.key, 'city.')}"><option value="${fn:substringAfter(option.key, 'city.')}"><c:out value="${option.value}" /></option></c:if></c:forEach></c:when>
|
||||||
</c:forEach>
|
<c:otherwise><c:forEach items="${citylist}" var="city"><option value="${city[0]}"><c:out value="${city[1]}" /></option></c:forEach></c:otherwise>
|
||||||
|
</c:choose>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -621,12 +647,15 @@
|
|||||||
<div id="section6">
|
<div id="section6">
|
||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<img class="matrix-title-icon" src="/matrix/images/othdet.png" />
|
<img class="matrix-title-icon" src="/matrix/images/edit_form.png" alt="" />
|
||||||
<span class="matrix-title-text">Other Details</span>
|
<span class="matrix-title-text">Other Details</span>
|
||||||
</div>
|
</div>
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<div id="FormPanel6" class="FormPanel">
|
<div id="FormPanel6" class="FormPanel">
|
||||||
${dynamichtml}
|
<c:choose>
|
||||||
|
<c:when test="${not empty model}"><c:out value="${model.dynamicHtml}" escapeXml="false" /></c:when>
|
||||||
|
<c:otherwise><c:out value="${dynamichtml}" escapeXml="false" /></c:otherwise>
|
||||||
|
</c:choose>
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
@@ -650,16 +679,22 @@
|
|||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
<input type="hidden" id="dynamicfields" name="dynamicfields" value="${dynamicfields}" />
|
<input type="hidden" id="dynamicfields" name="dynamicfields" value="${pageDynamicFields}" />
|
||||||
<input type="hidden" id="visiblecontents" name="visiblecontents" value="${visiblecontents}" />
|
<input type="hidden" id="visiblecontents" name="visiblecontents" value="${visiblecontents}" />
|
||||||
<input type="hidden" id="uuid" name="uuid" value="${duuid}" />
|
<input type="hidden" id="initial-portfolio-id" value="${pagePortfolioId}" />
|
||||||
|
<c:if test="${not empty model}">
|
||||||
|
<c:forEach items="${model.visibleSections}" var="section">
|
||||||
|
<span hidden class="model-visible-section"><c:out value="${section}" /></span>
|
||||||
|
</c:forEach>
|
||||||
|
</c:if>
|
||||||
|
<input type="hidden" id="uuid" name="uuid" value="${pageDocumentCaseId}" />
|
||||||
<input type="hidden" id="case_id" name="case_id" value="" />
|
<input type="hidden" id="case_id" name="case_id" value="" />
|
||||||
<input type="hidden" id="company_id" name="company_id" value="${Sessvals.getCompanyID()}" />
|
<input type="hidden" id="company_id" name="company_id" value="${Sessvals.getCompanyID()}" />
|
||||||
<input type="hidden" id="branch_id" name="branch_id" value="${Sessvals.getBranchID()}" />
|
<input type="hidden" id="branch_id" name="branch_id" value="${Sessvals.getBranchID()}" />
|
||||||
<input type="hidden" id="status" name="status" value="" />
|
<input type="hidden" id="status" name="status" value="" />
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<input type="hidden" id="invalidfields" value="0" />
|
<input type="hidden" id="invalidfields" value="0" />
|
||||||
<c:if test="${formmode gt 0}">
|
<c:if test="${pageFormMode gt 0}">
|
||||||
<div style="position:fixed;text-align:right;bottom:0px;width:980px;" class="buttonbar">
|
<div style="position:fixed;text-align:right;bottom:0px;width:980px;" class="buttonbar">
|
||||||
<input type="hidden" id="invalidfields" value="0" />
|
<input type="hidden" id="invalidfields" value="0" />
|
||||||
<input type="button" class="button" name="btnfirst" style="margin-left:5px;margin-top:-2px;float:left;width:80px" value="" id="btnfirst" accesskey="F" onclick="findRecord(1)" />
|
<input type="button" class="button" name="btnfirst" style="margin-left:5px;margin-top:-2px;float:left;width:80px" value="" id="btnfirst" accesskey="F" onclick="findRecord(1)" />
|
||||||
@@ -667,25 +702,40 @@
|
|||||||
<input type="button" class="button" name="btnnext" style="margin-top:-2px;float:left;width:80px" value="" id="btnnext" accesskey="N" onclick="findRecord(3)" />
|
<input type="button" class="button" name="btnnext" style="margin-top:-2px;float:left;width:80px" value="" id="btnnext" accesskey="N" onclick="findRecord(3)" />
|
||||||
<input type="button" class="button" name="btnlast" style="margin-top:-2px;float:left;width:80px" value="" id="btnlast" accesskey="L" onclick="findRecord(4)" />
|
<input type="button" class="button" name="btnlast" style="margin-top:-2px;float:left;width:80px" value="" id="btnlast" accesskey="L" onclick="findRecord(4)" />
|
||||||
<input type="button" class="button" name="btnsave" style="float:right" value="Save" id="btnsave" accesskey="S" onclick="return ValidateSubmitForm('casedetails');" />
|
<input type="button" class="button" name="btnsave" style="float:right" value="Save" id="btnsave" accesskey="S" onclick="return ValidateSubmitForm('casedetails');" />
|
||||||
<c:if test="${formmode!=2}">
|
<c:if test="${pageFormMode!=2}">
|
||||||
<input type="button" class="button" name="btnadd" style="float:right" value="Add" id="btnadd" accesskey="A" onclick="return AddNewRecord();" />
|
<input type="button" class="button" name="btnadd" style="float:right" value="Add" id="btnadd" accesskey="A" onclick="return AddNewRecord();" />
|
||||||
</c:if>
|
</c:if>
|
||||||
</div>
|
</div>
|
||||||
</c:if>
|
</c:if>
|
||||||
</form>
|
</form>
|
||||||
<input type="hidden" id="formmode" name="formmode" value="${formmode}" />
|
<input type="hidden" id="formmode" name="formmode" value="${pageFormMode}" />
|
||||||
<input type="hidden" id="usid" name="usid" value="${usid}" />
|
<input type="hidden" id="usid" name="usid" value="${pageUserId}" />
|
||||||
|
<c:if test="${not empty model.errorDetails}">
|
||||||
|
<span id="page-error-code" hidden><c:out value="${model.errorDetails.errorCode}" /></span>
|
||||||
|
<span id="page-error-message" hidden><c:out value="${model.errorDetails.message}" /></span>
|
||||||
|
</c:if>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
<!-- Page Load Javascript -->
|
<!-- Page Load Javascript -->
|
||||||
<script language="javascript" type="text/javascript">
|
<script language="javascript" type="text/javascript">
|
||||||
InitPage('${portfolio_id}','${visiblecontents}');
|
(function () {
|
||||||
|
var sectionFields = document.querySelectorAll(".model-visible-section");
|
||||||
|
if (sectionFields.length > 0) {
|
||||||
|
document.getElementById("visiblecontents").value = Array.prototype.map.call(
|
||||||
|
sectionFields, function (field) { return field.textContent; }
|
||||||
|
).join(ColDelim);
|
||||||
|
}
|
||||||
|
InitPage();
|
||||||
|
|
||||||
|
var errorCode = document.getElementById("page-error-code");
|
||||||
|
var errorMessage = document.getElementById("page-error-message");
|
||||||
|
if (errorCode && errorMessage) {
|
||||||
|
CallMessage(errorCode.textContent + ":error:" + errorMessage.textContent, 3000, 200, 300);
|
||||||
|
}
|
||||||
|
}());
|
||||||
</script>
|
</script>
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<!-- Process Message -->
|
<!-- Process Message -->
|
||||||
<c:if test="${not empty msg}">
|
|
||||||
<script language="javascript" type="text/javascript"> CallMessage('${msg}',3000,200,300); </script>
|
|
||||||
</c:if>
|
|
||||||
<!-- -->
|
<!-- -->
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<script language="javascript" src="/matrix/js/ajax.js" type="text/javascript"></script>
|
<script language="javascript" src="/matrix/js/ajax.js" type="text/javascript"></script>
|
||||||
<script language="javascript" src="/matrix/js/ajax-dynamic-list.js" type="text/javascript"></script>
|
<script language="javascript" src="/matrix/js/ajax-dynamic-list.js" type="text/javascript"></script>
|
||||||
<script language="javascript" src="/matrix/js/appjs/punchingdoc.js" type="text/javascript"></script>
|
<script language="javascript" src="/matrix/js/appjs/punchingdoc.js" type="text/javascript"></script>
|
||||||
<script language="javascript" src="/matrix/js/validator.js" type="text/javascript"></script>
|
<script language="javascript" src="/matrix/js/validator.js?ver=2" type="text/javascript"></script>
|
||||||
|
|
||||||
<link href="/matrix/css/button.css" rel="stylesheet" type="text/css" />
|
<link href="/matrix/css/button.css" rel="stylesheet" type="text/css" />
|
||||||
<link href="/matrix/css/div.css" rel="stylesheet" type="text/css" />
|
<link href="/matrix/css/div.css" rel="stylesheet" type="text/css" />
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
<link href="/matrix/css/matrix-shell-v2.css?v=7" rel="stylesheet" type="text/css" />
|
<link href="/matrix/css/matrix-shell-v2.css?v=7" rel="stylesheet" type="text/css" />
|
||||||
<link href="/matrix/css/tool-workspace-v3.css?v=2" rel="stylesheet" type="text/css" />
|
<link href="/matrix/css/tool-workspace-v3.css?v=2" rel="stylesheet" type="text/css" />
|
||||||
<link href="/matrix/css/punch-workspace-v3.css?v=1" rel="stylesheet" type="text/css" />
|
<link href="/matrix/css/punch-workspace-v3.css?v=1" rel="stylesheet" type="text/css" />
|
||||||
<link href="/matrix/css/add-cases-v4.css?v=1" rel="stylesheet" type="text/css" />
|
<link href="/matrix/css/add-cases-v4.css?v=5" rel="stylesheet" type="text/css" />
|
||||||
<script src="/matrix/js/bootstrap-5.3.8.bundle.min.js" defer></script>
|
<script src="/matrix/js/bootstrap-5.3.8.bundle.min.js" defer></script>
|
||||||
<script src="/matrix/js/matrix-shell-v2.js" defer></script>
|
<script src="/matrix/js/matrix-shell-v2.js" defer></script>
|
||||||
<link href="/matrix/css/matrix-frame-dialog.css?v=6" rel="stylesheet" type="text/css" />
|
<link href="/matrix/css/matrix-frame-dialog.css?v=6" rel="stylesheet" type="text/css" />
|
||||||
|
|||||||
@@ -1,29 +1,67 @@
|
|||||||
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
|
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
|
||||||
pageEncoding="ISO-8859-1"%>
|
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
|
||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html>
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
<meta charset="UTF-8" />
|
||||||
<script language="javascript" src="/matrix/js/lib/constants.js" type="text/javascript"></script>
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<script language="javascript" src="/matrix/js/lib/jsfuncs.js" type="text/javascript"></script>
|
<link href="<c:url value='/css/bootstrap-5.3.8.min.css' />" rel="stylesheet" />
|
||||||
<script language="javascript" src="/matrix/js/jquery1.7.2.js" type="text/javascript"></script>
|
<link href="<c:url value='/css/matrix-v2.css' />" rel="stylesheet" />
|
||||||
<script language="javascript" src="/matrix/js/ui/uifuncs.js" type="text/javascript"></script>
|
<link href="<c:url value='/css/matrix-shell-v2.css' />" rel="stylesheet" />
|
||||||
<script language="javascript" src="/matrix/js/validator.js" type="text/javascript"></script>
|
<link href="<c:url value='/css/matrix-theme-v2.css' />" rel="stylesheet" />
|
||||||
|
<script src="<c:url value='/js/matrix-shell-v2.js' />" defer></script>
|
||||||
<link href="/matrix/css/matrix.css" rel="stylesheet" type="text/css" />
|
<title>Cygnus 1.0 | <c:out value="${empty errorDetails.title ? 'Page unavailable' : errorDetails.title}" /></title>
|
||||||
<link href="/matrix/css/div.css" rel="stylesheet" type="text/css" />
|
</head>
|
||||||
<title>Cygnus 1.0 | 404 Error</title>
|
<body class="matrix-v2 matrix-shell matrix-error-page matrix-error-page--${empty errorDetails.httpStatus ? 404 : errorDetails.httpStatus}">
|
||||||
<script src="/matrix/js/matrix-accessibility-v1.js?v=1" defer></script>
|
<c:choose>
|
||||||
<link href="/matrix/css/matrix-theme-v2.css?v=4" rel="stylesheet" type="text/css" />
|
<c:when test="${not empty Sessvals and not empty Sessvals.menuHtml}">
|
||||||
</head>
|
<%@ include file="/WEB-INF/app/fragments/app-shell-header.jspf" %>
|
||||||
<body class="matrix-error-page">
|
</c:when>
|
||||||
<form method="post" name="unaccess" id="unaccess">
|
<c:otherwise>
|
||||||
<main class="matrix-error-card" role="alert" aria-labelledby="errorTitle">
|
<%@ include file="/WEB-INF/app/fragments/app-title.jspf" %>
|
||||||
<div class="matrix-error-card__code">404</div>
|
</c:otherwise>
|
||||||
<h1 id="errorTitle">Page unavailable</h1>
|
</c:choose>
|
||||||
<p>Unauthorized access or the requested page could not be found.</p>
|
|
||||||
<button type="button" class="matrix-error-card__action" onclick="SubmitForm('logout', '_parent', 'unaccess');">Return to sign in</button>
|
<main class="matrix-error-layout" id="mainContent">
|
||||||
</main>
|
<section class="matrix-error-card" role="alert" aria-labelledby="errorTitle">
|
||||||
</form>
|
<div class="matrix-error-card__status" aria-hidden="true">
|
||||||
|
<span><c:out value="${empty errorDetails.httpStatus ? 404 : errorDetails.httpStatus}" /></span>
|
||||||
|
</div>
|
||||||
|
<div class="matrix-error-card__content">
|
||||||
|
<span class="matrix-error-card__eyebrow">
|
||||||
|
Error <c:out value="${empty errorDetails.errorCode ? 'HTTP-404' : errorDetails.errorCode}" />
|
||||||
|
</span>
|
||||||
|
<h1 id="errorTitle">
|
||||||
|
<c:out value="${empty errorDetails.title ? 'Page unavailable' : errorDetails.title}" />
|
||||||
|
</h1>
|
||||||
|
<p class="matrix-error-card__message">
|
||||||
|
<c:out value="${empty errorDetails.message ? 'The requested page is unavailable.' : errorDetails.message}" />
|
||||||
|
</p>
|
||||||
|
<c:if test="${not empty errorDetails.description}">
|
||||||
|
<p class="matrix-error-card__description"><c:out value="${errorDetails.description}" /></p>
|
||||||
|
</c:if>
|
||||||
|
|
||||||
|
<div class="matrix-error-card__actions">
|
||||||
|
<c:choose>
|
||||||
|
<c:when test="${not empty Sessvals and not empty Sessvals.menuHtml}">
|
||||||
|
<form method="post" action="<c:url value='/ver/dashboard' />">
|
||||||
|
<button type="submit" class="matrix-error-card__action">Return to dashboard</button>
|
||||||
|
</form>
|
||||||
|
<button type="button" class="matrix-error-card__action matrix-error-card__action--secondary" onclick="history.back()">Go back</button>
|
||||||
|
</c:when>
|
||||||
|
<c:otherwise>
|
||||||
|
<a class="matrix-error-card__action" href="<c:url value='/ver/login' />">Return to sign in</a>
|
||||||
|
</c:otherwise>
|
||||||
|
</c:choose>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<c:if test="${not empty errorDetails.referenceId}">
|
||||||
|
<p class="matrix-error-card__reference">
|
||||||
|
Reference ID: <code><c:out value="${errorDetails.referenceId}" /></code>
|
||||||
|
</p>
|
||||||
|
</c:if>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -37,7 +37,15 @@
|
|||||||
<session-timeout>180</session-timeout>
|
<session-timeout>180</session-timeout>
|
||||||
</session-config>
|
</session-config>
|
||||||
|
|
||||||
<!-- Error Page -->
|
<!-- Error Page -->
|
||||||
|
<error-page>
|
||||||
|
<error-code>404</error-code>
|
||||||
|
<location>/ver/error</location>
|
||||||
|
</error-page>
|
||||||
|
<error-page>
|
||||||
|
<error-code>500</error-code>
|
||||||
|
<location>/ver/error</location>
|
||||||
|
</error-page>
|
||||||
<error-page>
|
<error-page>
|
||||||
<exception-type>org.springframework.web.HttpSessionRequiredException</exception-type>
|
<exception-type>org.springframework.web.HttpSessionRequiredException</exception-type>
|
||||||
<location>/matrix/index.jsp</location>
|
<location>/matrix/index.jsp</location>
|
||||||
|
|||||||
@@ -31,6 +31,12 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Legacy forms separate labels and controls with a BR. In the modern flex
|
||||||
|
layout that BR becomes an extra flex row and creates an unintended gap. */
|
||||||
|
.matrix-add-cases .matrix-form-controls .widget > br {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.matrix-add-cases .matrix-form-controls .widget[style*="display:none"] {
|
.matrix-add-cases .matrix-form-controls .widget[style*="display:none"] {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
@@ -89,3 +95,87 @@
|
|||||||
.matrix-add-cases .matrix-form-controls .widget:has(#splist),
|
.matrix-add-cases .matrix-form-controls .widget:has(#splist),
|
||||||
.matrix-add-cases .matrix-form-controls .widget:has(textarea) { grid-column: span 6; }
|
.matrix-add-cases .matrix-form-controls .widget:has(textarea) { grid-column: span 6; }
|
||||||
}
|
}
|
||||||
|
.matrix-add-cases .inputcontainer {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-add-cases .inputcontainer > input.errtxt,
|
||||||
|
.matrix-add-cases .inputcontainer > textarea.errtxt {
|
||||||
|
padding-right: 24px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-add-cases .matrix-validation-error-icon {
|
||||||
|
display: block;
|
||||||
|
margin: 0 !important;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-add-cases #section2 > .title,
|
||||||
|
.matrix-add-cases #section3 > .title,
|
||||||
|
.matrix-add-cases #section4 > .title,
|
||||||
|
.matrix-add-cases #section5 > .title,
|
||||||
|
.matrix-add-cases #section6 > .title,
|
||||||
|
.matrix-add-cases #section7 > .title {
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 6px 8px;
|
||||||
|
min-height: 38px;
|
||||||
|
height: auto !important;
|
||||||
|
padding: 5px 10px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-add-cases #section2 > .title > .matrix-title-icon,
|
||||||
|
.matrix-add-cases #section3 > .title > .matrix-title-icon,
|
||||||
|
.matrix-add-cases #section4 > .title > .matrix-title-icon,
|
||||||
|
.matrix-add-cases #section5 > .title > .matrix-title-icon,
|
||||||
|
.matrix-add-cases #section6 > .title > .matrix-title-icon,
|
||||||
|
.matrix-add-cases #section7 > .title > .matrix-title-icon {
|
||||||
|
display: block;
|
||||||
|
flex: 0 0 16px;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
margin: 0 !important;
|
||||||
|
object-fit: contain;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-add-cases #section2 > .title > .matrix-title-text,
|
||||||
|
.matrix-add-cases #section3 > .title > .matrix-title-text,
|
||||||
|
.matrix-add-cases #section4 > .title > .matrix-title-text,
|
||||||
|
.matrix-add-cases #section5 > .title > .matrix-title-text,
|
||||||
|
.matrix-add-cases #section6 > .title > .matrix-title-text,
|
||||||
|
.matrix-add-cases #section7 > .title > .matrix-title-text {
|
||||||
|
line-height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-add-cases #section2 > .title > .divchk,
|
||||||
|
.matrix-add-cases #section3 > .title > .divchk,
|
||||||
|
.matrix-add-cases #section4 > .title > .divchk,
|
||||||
|
.matrix-add-cases #section5 > .title > .divchk,
|
||||||
|
.matrix-add-cases #section7 > .title > .divchk {
|
||||||
|
position: static !important;
|
||||||
|
right: auto !important;
|
||||||
|
float: none !important;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
align-self: center;
|
||||||
|
gap: 4px;
|
||||||
|
min-height: 18px;
|
||||||
|
margin: 0 0 0 auto !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
line-height: 18px !important;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-add-cases #section2 > .title > .divchk input[type="checkbox"],
|
||||||
|
.matrix-add-cases #section3 > .title > .divchk input[type="checkbox"],
|
||||||
|
.matrix-add-cases #section4 > .title > .divchk input[type="checkbox"],
|
||||||
|
.matrix-add-cases #section5 > .title > .divchk input[type="checkbox"],
|
||||||
|
.matrix-add-cases #section7 > .title > .divchk input[type="checkbox"] {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
margin-top: 0 !important;
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|||||||
@@ -119,45 +119,103 @@ body .nav-menu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
body.matrix-error-page {
|
body.matrix-error-page {
|
||||||
display: grid;
|
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 24px;
|
|
||||||
place-items: center;
|
|
||||||
color: #263746;
|
color: #263746;
|
||||||
background: var(--matrix-theme-canvas) !important;
|
background: var(--matrix-theme-canvas) !important;
|
||||||
font-family: Arial, sans-serif;
|
font-family: Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
.matrix-error-card {
|
.matrix-error-layout {
|
||||||
width: min(100%, 480px);
|
min-height: calc(100vh - 84px);
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: clamp(24px, 5vw, 64px) 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-error-card {
|
||||||
|
width: min(100%, 760px);
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 150px minmax(0, 1fr);
|
||||||
|
overflow: hidden;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 30px;
|
|
||||||
text-align: center;
|
|
||||||
border: 1px solid var(--matrix-theme-border);
|
border: 1px solid var(--matrix-theme-border);
|
||||||
border-radius: 8px;
|
border-radius: 10px;
|
||||||
background: var(--matrix-theme-panel);
|
background: var(--matrix-theme-panel);
|
||||||
box-shadow: 0 8px 24px rgba(31, 52, 72, .12);
|
box-shadow: 0 8px 24px rgba(31, 52, 72, .12);
|
||||||
}
|
}
|
||||||
|
|
||||||
.matrix-error-card__code {
|
.matrix-error-card__status {
|
||||||
color: #b42318;
|
min-height: 290px;
|
||||||
font-size: 38px;
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
color: #fff;
|
||||||
|
background: #a4473f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-error-page--401 .matrix-error-card__status,
|
||||||
|
.matrix-error-page--403 .matrix-error-card__status {
|
||||||
|
background: #a66a19;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-error-page--404 .matrix-error-card__status,
|
||||||
|
.matrix-error-page--405 .matrix-error-card__status {
|
||||||
|
background: #376b94;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-error-card__status span {
|
||||||
|
font-size: 42px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.matrix-error-card h1 {
|
.matrix-error-card__content {
|
||||||
margin: 10px 0 6px;
|
padding: 34px 38px 28px;
|
||||||
font-size: 21px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.matrix-error-card p {
|
.matrix-error-card__eyebrow {
|
||||||
margin: 0 0 20px;
|
color: #607587;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: .08em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-error-card h1 {
|
||||||
|
margin: 8px 0 10px;
|
||||||
|
font-size: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-error-card__message {
|
||||||
|
margin: 0 0 8px;
|
||||||
|
color: #344b5e;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-error-card__description {
|
||||||
|
margin: 0;
|
||||||
color: #536779;
|
color: #536779;
|
||||||
|
line-height: 1.55;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-error-card__actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 9px;
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-error-card__actions form {
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.matrix-error-card__action {
|
.matrix-error-card__action {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
min-height: 34px;
|
min-height: 34px;
|
||||||
padding: 6px 16px;
|
padding: 6px 16px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
@@ -166,6 +224,55 @@ body.matrix-error-page {
|
|||||||
background: #245a91;
|
background: #245a91;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-error-card__action:hover,
|
||||||
|
.matrix-error-card__action:focus {
|
||||||
|
color: #fff;
|
||||||
|
background: #1d4e7d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-error-card__action--secondary {
|
||||||
|
color: #334b5e;
|
||||||
|
border-color: #aebdca;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-error-card__action--secondary:hover,
|
||||||
|
.matrix-error-card__action--secondary:focus {
|
||||||
|
color: #263746;
|
||||||
|
background: #e4edf4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-error-card__reference {
|
||||||
|
margin: 22px 0 0;
|
||||||
|
padding-top: 14px;
|
||||||
|
color: #6b7e8e;
|
||||||
|
border-top: 1px solid #d5e0e8;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-error-card__reference code {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 620px) {
|
||||||
|
.matrix-error-card {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-error-card__status {
|
||||||
|
min-height: 82px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-error-card__status span {
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix-error-card__content {
|
||||||
|
padding: 26px 24px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compact toolbars for legacy forms that place controls in their title bar. */
|
/* Compact toolbars for legacy forms that place controls in their title bar. */
|
||||||
|
|||||||
@@ -12,14 +12,25 @@ AddrElem[1]=["ov","companyname","oaddr1","oaddr2","oaddr3","olandmark","Ocolony"
|
|||||||
AddrElem[2]=["pv","paddr1","paddr2","paddr3","plandmark","Pcolony","colp","pcity","ppincode"];
|
AddrElem[2]=["pv","paddr1","paddr2","paddr3","plandmark","Pcolony","colp","pcity","ppincode"];
|
||||||
AddrElem[3]=["bankcode","bankcode","bank_branch_id","product","loanamount","apptype","contactperson","specialinst"];
|
AddrElem[3]=["bankcode","bankcode","bank_branch_id","product","loanamount","apptype","contactperson","specialinst"];
|
||||||
|
|
||||||
function InitPage(port,viscontents)
|
function InitPage()
|
||||||
{
|
{
|
||||||
centerDivBoth("formcontainer","H");
|
var portField = document.getElementById("portfolio_id");
|
||||||
|
var initialPortField = document.getElementById("initial-portfolio-id");
|
||||||
|
var visibleContentsField = document.getElementById("visiblecontents");
|
||||||
|
var port = initialPortField ? initialPortField.value : (portField ? portField.value : "-1");
|
||||||
|
var viscontents = visibleContentsField ? visibleContentsField.value : "";
|
||||||
|
if (viscontents && viscontents.slice(-ColDelim.length) !== ColDelim) {
|
||||||
|
viscontents += ColDelim;
|
||||||
|
}
|
||||||
|
|
||||||
|
centerDivBoth("formcontainer","H");
|
||||||
HideSections('rtv');
|
HideSections('rtv');
|
||||||
HideSections('otv');
|
HideSections('otv');
|
||||||
HideSections('section');
|
HideSections('section');
|
||||||
UnhideSections(viscontents,ColDelim);
|
UnhideSections(viscontents,ColDelim);
|
||||||
$("#portfolio_id").val(port);
|
if (portField) {
|
||||||
|
$(portField).val(port);
|
||||||
|
}
|
||||||
if(port>0)
|
if(port>0)
|
||||||
{
|
{
|
||||||
if(document.getElementById("ajaxmsg") !== null)
|
if(document.getElementById("ajaxmsg") !== null)
|
||||||
|
|||||||
@@ -82,39 +82,44 @@ function GetRegExp(el,ValidFormat)
|
|||||||
if(ValidFormat=='PAN'){return /^(([a-zA-Z]{5})\d{4}([a-zA-Z]{1}))$/;}
|
if(ValidFormat=='PAN'){return /^(([a-zA-Z]{5})\d{4}([a-zA-Z]{1}))$/;}
|
||||||
if(ValidFormat=='CreditCard'){return /^\d{16}$/;}
|
if(ValidFormat=='CreditCard'){return /^\d{16}$/;}
|
||||||
}
|
}
|
||||||
function highlightField(el)
|
function highlightField(el)
|
||||||
{
|
{
|
||||||
if (document.getElementById('err'+el.id))
|
if (document.getElementById('err'+el.id))
|
||||||
{
|
{
|
||||||
//nothing to do already exists
|
//nothing to do already exists
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
invalidFields=invalidFields+1;
|
invalidFields=invalidFields+1;
|
||||||
var offset=null;
|
var iconHost=el.parentNode;
|
||||||
var width=null;
|
var current=el.parentNode;
|
||||||
if(el.type=='text' || el.type=='textarea' || el.type=='password')
|
while(current && current!==document.body)
|
||||||
{
|
{
|
||||||
el.setAttribute("class", "textbox errtxt");
|
var classes=" "+(current.className || "")+" ";
|
||||||
offset=$(el).offset();
|
if(classes.indexOf(" inputcontainer ")!==-1)
|
||||||
width=el.offsetWidth;
|
{
|
||||||
}
|
iconHost=current;
|
||||||
else if(el.type=='select-one')
|
break;
|
||||||
{
|
}
|
||||||
el.parentNode.setAttribute("class", "divselect errdiv");
|
current=current.parentNode;
|
||||||
tmpel=el.parentNode;
|
}
|
||||||
offset=$(tmpel).offset();
|
if(el.type=='text' || el.type=='textarea' || el.type=='password')
|
||||||
width=tmpel.offsetWidth;
|
{
|
||||||
}
|
el.setAttribute("class", "textbox errtxt");
|
||||||
var top=parseInt(offset.top)-5;
|
}
|
||||||
var left=parseInt(offset.left)+(width-5);
|
else if(el.type=='select-one')
|
||||||
var img=document.createElement("img");
|
{
|
||||||
img.setAttribute("src","/matrix/images/exclamation.png");
|
el.parentNode.setAttribute("class", "divselect errdiv");
|
||||||
img.setAttribute("style","position:absolute;margin-left:"+left+"px;margin-top:"+top+"px;z-index:3");
|
}
|
||||||
img.setAttribute("id","err"+el.id);
|
iconHost.style.position="relative";
|
||||||
document.body.appendChild(img);
|
var img=document.createElement("img");
|
||||||
}
|
img.setAttribute("src","/matrix/images/exclamation.png");
|
||||||
}
|
img.setAttribute("class", "matrix-validation-error-icon"+(el.type=='select-one' ? " matrix-validation-error-icon--select" : ""));
|
||||||
|
img.setAttribute("style","position:absolute;right:"+(el.type=='select-one' ? "24px" : "5px")+";top:50%;width:14px;height:14px;transform:translateY(-50%);z-index:3;pointer-events:none");
|
||||||
|
img.setAttribute("id","err"+el.id);
|
||||||
|
iconHost.appendChild(img);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// DATE FORMAT VALIDATOR DD/MM/YYYY
|
// DATE FORMAT VALIDATOR DD/MM/YYYY
|
||||||
function addSlashes(el,evt)
|
function addSlashes(el,evt)
|
||||||
|
|||||||
@@ -23,6 +23,16 @@
|
|||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.cygnus</groupId>
|
||||||
|
<artifactId>cygnus-lib</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.cygnus</groupId>
|
||||||
|
<artifactId>cygnus-onprem-db</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.cygnus</groupId>
|
<groupId>com.cygnus</groupId>
|
||||||
<artifactId>cygnus-cloud-client</artifactId>
|
<artifactId>cygnus-cloud-client</artifactId>
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package matrix.nimble.controller;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import jakarta.servlet.http.HttpSession;
|
||||||
|
import lib.constants.ApplicationError;
|
||||||
|
import lib.models.ErrorDetails;
|
||||||
|
import matrix.nimble.model.Session;
|
||||||
|
import matrix.services.commons.CommonErrorService;
|
||||||
|
import matrix.services.commons.CommonService;
|
||||||
|
import org.springframework.ui.ModelMap;
|
||||||
|
|
||||||
|
/** Shared session and page-authorization workflow for authenticated controllers. */
|
||||||
|
public abstract class AbstractAuthenticatedController {
|
||||||
|
private final CommonService commonService;
|
||||||
|
private final CommonErrorService errorService;
|
||||||
|
|
||||||
|
protected AbstractAuthenticatedController(
|
||||||
|
CommonService commonService,
|
||||||
|
CommonErrorService errorService) {
|
||||||
|
this.commonService = commonService;
|
||||||
|
this.errorService = errorService;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final PageAuthorization authorizePage(
|
||||||
|
String pageRoute,
|
||||||
|
ModelMap model,
|
||||||
|
HttpSession httpSession,
|
||||||
|
HttpServletResponse response) {
|
||||||
|
Session session = commonService.getSession(httpSession);
|
||||||
|
if (session == null) {
|
||||||
|
return denied(model, response, httpSession, ApplicationError.SESSION_REQUIRED);
|
||||||
|
}
|
||||||
|
if (!commonService.hasPageAccess(session, pageRoute)) {
|
||||||
|
return denied(model, response, httpSession, ApplicationError.ACCESS_DENIED);
|
||||||
|
}
|
||||||
|
model.addAttribute(CommonService.SESSION_ATTRIBUTE, session);
|
||||||
|
return PageAuthorization.granted(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PageAuthorization denied(
|
||||||
|
ModelMap model,
|
||||||
|
HttpServletResponse response,
|
||||||
|
HttpSession httpSession,
|
||||||
|
ApplicationError error) {
|
||||||
|
String viewName = errorService.render(
|
||||||
|
model, response, httpSession, new ErrorDetails(error));
|
||||||
|
return PageAuthorization.denied(viewName);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected record PageAuthorization(Session session, String viewName) {
|
||||||
|
private static PageAuthorization granted(Session session) {
|
||||||
|
return new PageAuthorization(session, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PageAuthorization denied(String viewName) {
|
||||||
|
return new PageAuthorization(null, viewName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isGranted() {
|
||||||
|
return session != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package matrix.nimble.controller;
|
||||||
|
|
||||||
|
import jakarta.servlet.RequestDispatcher;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import jakarta.servlet.http.HttpSession;
|
||||||
|
import lib.models.ErrorDetails;
|
||||||
|
import lib.constants.ApplicationError;
|
||||||
|
import matrix.services.commons.CommonErrorService;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class ApplicationErrorController {
|
||||||
|
private final CommonErrorService errorService;
|
||||||
|
|
||||||
|
public ApplicationErrorController(CommonErrorService errorService) {
|
||||||
|
this.errorService = errorService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("error")
|
||||||
|
public String error(
|
||||||
|
ModelMap model,
|
||||||
|
HttpServletRequest request,
|
||||||
|
HttpServletResponse response,
|
||||||
|
HttpSession httpSession) {
|
||||||
|
int status = status(request);
|
||||||
|
return errorService.render(model, response, httpSession, details(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int status(HttpServletRequest request) {
|
||||||
|
Object value = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
|
||||||
|
if (value instanceof Integer status && status >= 400 && status <= 599) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
return HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ErrorDetails details(int status) {
|
||||||
|
return new ErrorDetails(ApplicationError.fromHttpStatus(status));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import matrix.nimble.cloud.identity.CloudAuthenticationException;
|
|||||||
import matrix.nimble.cloud.identity.CloudAuthenticationGateway;
|
import matrix.nimble.cloud.identity.CloudAuthenticationGateway;
|
||||||
import matrix.nimble.model.Login;
|
import matrix.nimble.model.Login;
|
||||||
import matrix.nimble.model.Session;
|
import matrix.nimble.model.Session;
|
||||||
|
import matrix.services.commons.CommonService;
|
||||||
|
|
||||||
//servlet libraries
|
//servlet libraries
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
@@ -21,9 +22,13 @@ import org.springframework.web.bind.annotation.SessionAttributes;
|
|||||||
@SessionAttributes("Sessvals")
|
@SessionAttributes("Sessvals")
|
||||||
public class SessionController {
|
public class SessionController {
|
||||||
private final CloudAuthenticationGateway cloudAuthenticationGateway;
|
private final CloudAuthenticationGateway cloudAuthenticationGateway;
|
||||||
|
private final CommonService commonService;
|
||||||
|
|
||||||
public SessionController(CloudAuthenticationGateway cloudAuthenticationGateway) {
|
public SessionController(
|
||||||
|
CloudAuthenticationGateway cloudAuthenticationGateway,
|
||||||
|
CommonService commonService) {
|
||||||
this.cloudAuthenticationGateway = cloudAuthenticationGateway;
|
this.cloudAuthenticationGateway = cloudAuthenticationGateway;
|
||||||
|
this.commonService = commonService;
|
||||||
}
|
}
|
||||||
@RequestMapping(value="login", method={RequestMethod.GET, RequestMethod.POST})
|
@RequestMapping(value="login", method={RequestMethod.GET, RequestMethod.POST})
|
||||||
public String LoginPage(ModelMap model)
|
public String LoginPage(ModelMap model)
|
||||||
@@ -42,13 +47,17 @@ public class SessionController {
|
|||||||
return "login";
|
return "login";
|
||||||
}
|
}
|
||||||
@RequestMapping(value="authenticatelogin",method=RequestMethod.POST )
|
@RequestMapping(value="authenticatelogin",method=RequestMethod.POST )
|
||||||
public String Authenticate(ModelMap model,@ModelAttribute(value="login") Login login)
|
public String Authenticate(
|
||||||
|
ModelMap model,
|
||||||
|
@ModelAttribute(value="login") Login login,
|
||||||
|
HttpSession httpSession)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
Session cloudSession = cloudAuthenticationGateway.authenticate(
|
Session cloudSession = cloudAuthenticationGateway.authenticate(
|
||||||
login.getLoginid(), login.getPassword());
|
login.getLoginid(), login.getPassword());
|
||||||
model.remove("login");
|
model.remove("login");
|
||||||
model.addAttribute("Sessvals", cloudSession);
|
model.addAttribute("Sessvals", cloudSession);
|
||||||
|
commonService.storeSession(httpSession, cloudSession);
|
||||||
return "home";
|
return "home";
|
||||||
} catch (CloudAuthenticationException exception) {
|
} catch (CloudAuthenticationException exception) {
|
||||||
login.setErrMsg(exception.reason()
|
login.setErrMsg(exception.reason()
|
||||||
|
|||||||
@@ -1,161 +0,0 @@
|
|||||||
package matrix.nimble.edp.punching.controller;
|
|
||||||
|
|
||||||
//servlet libraries
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpSession;
|
|
||||||
|
|
||||||
//spring libraries
|
|
||||||
import matrix.nimble.edp.punching.model.CaseDetails;
|
|
||||||
import matrix.nimble.model.Session;
|
|
||||||
import matrix.nimble.utilities.ModuleFunctions;
|
|
||||||
import matrix.nimble.utilities.GlobalClass;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.ui.ModelMap;
|
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.SessionAttributes;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
@SessionAttributes({"Sessvals"})
|
|
||||||
public class CasePucnhing {
|
|
||||||
@RequestMapping(value="caseadd1",method=RequestMethod.POST )
|
|
||||||
public String OpenAddCases(ModelMap model,HttpServletRequest request,@ModelAttribute(value="Sessvals") Session Sessvals)
|
|
||||||
{
|
|
||||||
CaseDetails caseDetails=new CaseDetails();
|
|
||||||
caseDetails.setFormMode(1);
|
|
||||||
caseDetails.setErrMsg("");
|
|
||||||
model.addAttribute("visibleContents","");
|
|
||||||
model.addAttribute("caseDetails",caseDetails);
|
|
||||||
model.addAttribute("branchlist",FillBranchList("0"));
|
|
||||||
model.addAttribute("prodlist",FillProductList("0"));
|
|
||||||
model.addAttribute("citylist",FillCityList("0"));
|
|
||||||
model.addAttribute("typelist",FillApptypeList("0"));
|
|
||||||
model.addAttribute("doclist",FillDocList("0"));
|
|
||||||
model.addAttribute("catlist",FillCatList("0"));
|
|
||||||
model.addAttribute("Sessvals",Sessvals);
|
|
||||||
model.addAttribute("portlist",FillPortList(Sessvals.getBranchID()));
|
|
||||||
return "edp/punching/addcases";
|
|
||||||
}
|
|
||||||
@RequestMapping(value="casesave",method=RequestMethod.POST )
|
|
||||||
public String SaveCase(ModelMap model,HttpServletRequest request,@ModelAttribute(value="Sessvals") Session Sessvals,@ModelAttribute(value="caseDetails") CaseDetails caseDet,HttpSession session)
|
|
||||||
{
|
|
||||||
String DynamicNsessVals="";
|
|
||||||
CaseDetails caseDetails=new CaseDetails();
|
|
||||||
caseDet.setErrCode("1001");
|
|
||||||
if(caseDet.getDynamicFields()!="")
|
|
||||||
{
|
|
||||||
String [] DynamicFields=caseDet.getDynamicFields().split(GlobalClass.ColDelim);
|
|
||||||
for(int indx=0;indx<DynamicFields.length;indx++)
|
|
||||||
{
|
|
||||||
//DynamicNsessVals=DynamicNsessVals+request.getParameter(DynamicFields[indx])+Delimeter.ColDelim;
|
|
||||||
caseDet.InvokeSetter("set"+DynamicFields[indx], request.getParameter(DynamicFields[indx]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(caseDet.getFormMode()==1 || caseDet.getFormMode()==2)
|
|
||||||
{
|
|
||||||
DynamicNsessVals=DynamicNsessVals+""+Sessvals.getUserID()+GlobalClass.ColDelim;
|
|
||||||
DynamicNsessVals=DynamicNsessVals+""+Sessvals.getCompanyID()+GlobalClass.ColDelim;
|
|
||||||
DynamicNsessVals=DynamicNsessVals+""+Sessvals.getBranchID();
|
|
||||||
}
|
|
||||||
if(!session.getAttribute("UUID").toString().equals(caseDet.getUUID()))
|
|
||||||
{
|
|
||||||
caseDetails.setProcessFlag(true);
|
|
||||||
caseDetails.setErrMsg("");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
caseDet.SaveDetails(DynamicNsessVals);
|
|
||||||
caseDetails.setProcessFlag(caseDet.isProcessFlag());
|
|
||||||
caseDetails.setErrMsg(caseDet.getErrMsg());
|
|
||||||
}
|
|
||||||
String VisibleContents=caseDet.getVisibleContents();
|
|
||||||
if(caseDetails.isProcessFlag())
|
|
||||||
{
|
|
||||||
String UUID=GlobalClass.GenerateUUID();
|
|
||||||
caseDetails.setUUID(UUID);
|
|
||||||
session.setAttribute("UUID", UUID);
|
|
||||||
caseDetails.setErrCode("1001");
|
|
||||||
caseDetails.setFormMode(caseDet.getFormMode());
|
|
||||||
caseDetails.setVisibleContents(VisibleContents);
|
|
||||||
caseDetails.setPortfolioId(caseDet.getPortfolioId());
|
|
||||||
caseDetails=caseDetails.DynamicHtml(caseDetails,caseDet.getPortfolioId());
|
|
||||||
caseDetails.setDynamicFields(caseDet.getDynamicFields());
|
|
||||||
VisibleContents=VisibleContents+""+caseDetails.getDynamicSection();
|
|
||||||
model.addAttribute("caseDetails",caseDetails);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
caseDet=caseDet.DynamicHtml(caseDet,caseDet.getPortfolioId());
|
|
||||||
VisibleContents=VisibleContents+""+caseDet.getDynamicSection();
|
|
||||||
model.addAttribute("caseDetails",caseDet);
|
|
||||||
}
|
|
||||||
model.addAttribute("visibleContents",VisibleContents);
|
|
||||||
model.addAttribute("branchlist",FillBranchList(caseDet.getPortfolioId()));
|
|
||||||
model.addAttribute("prodlist",FillProductList(caseDet.getPortfolioId()));
|
|
||||||
model.addAttribute("citylist",FillCityList(Sessvals.getBranchID()));
|
|
||||||
model.addAttribute("typelist",FillApptypeList(Sessvals.getBranchID()));
|
|
||||||
model.addAttribute("doclist",FillDocList(caseDet.getPortfolioId()));
|
|
||||||
model.addAttribute("catlist",FillCatList(caseDet.getPortfolioId()));
|
|
||||||
model.addAttribute("Sessvals",Sessvals);
|
|
||||||
model.addAttribute("portlist",FillPortList(Sessvals.getBranchID()));
|
|
||||||
return "edp/punching/addcases";
|
|
||||||
}
|
|
||||||
@RequestMapping(value="casedet",method=RequestMethod.POST )
|
|
||||||
public String GetRequiredData(ModelMap model,HttpServletRequest request,@ModelAttribute(value="Sessvals") Session Sessvals,@ModelAttribute(value="caseDetails") CaseDetails caseDet,HttpSession session)
|
|
||||||
{
|
|
||||||
CaseDetails caseDetails = new CaseDetails();
|
|
||||||
caseDetails.setPortfolioId(caseDet.getPortfolioId());
|
|
||||||
caseDetails.setErrCode("1001");
|
|
||||||
String UUID=GlobalClass.GenerateUUID();
|
|
||||||
caseDetails.setUUID(UUID);
|
|
||||||
session.setAttribute("UUID", UUID);
|
|
||||||
caseDetails.setFormMode(caseDet.getFormMode());
|
|
||||||
caseDetails=caseDetails.DynamicHtml(caseDetails,caseDet.getPortfolioId());
|
|
||||||
String VisibleContents=(new ModuleFunctions("1001").GetDDHashString(10, ("10"+GlobalClass.ColDelim+caseDet.getPortfolioId()).split(GlobalClass.ColDelim))).replace(GlobalClass.RowDelim, "");
|
|
||||||
caseDetails.setVisibleContents(VisibleContents);
|
|
||||||
VisibleContents=(VisibleContents+""+caseDetails.getDynamicSection()).replace(GlobalClass.ColDelim+"null", "");
|
|
||||||
model.addAttribute("visibleContents",VisibleContents);
|
|
||||||
model.addAttribute("caseDetails",caseDetails);
|
|
||||||
model.addAttribute("portlist",Sessvals.getBranchID());
|
|
||||||
model.addAttribute("branchlist",FillBranchList(caseDet.getPortfolioId()));
|
|
||||||
model.addAttribute("prodlist",FillProductList(caseDet.getPortfolioId()));
|
|
||||||
model.addAttribute("citylist",FillCityList(Sessvals.getBranchID()));
|
|
||||||
model.addAttribute("typelist",FillApptypeList(Sessvals.getBranchID()));
|
|
||||||
model.addAttribute("doclist",FillDocList(caseDet.getPortfolioId()));
|
|
||||||
model.addAttribute("catlist",FillCatList(caseDet.getPortfolioId()));
|
|
||||||
model.addAttribute("Sessvals",Sessvals);
|
|
||||||
model.addAttribute("portlist",FillPortList(Sessvals.getBranchID()));
|
|
||||||
return "edp/punching/addcases";
|
|
||||||
}
|
|
||||||
public String [][] FillPortList(String BranchId)
|
|
||||||
{
|
|
||||||
return new ModuleFunctions("1001").GetResultArray(3,(BranchId+GlobalClass.ColDelim).split(GlobalClass.ColDelim));
|
|
||||||
}
|
|
||||||
public String [][] FillCityList(String BranchID)
|
|
||||||
{
|
|
||||||
return new ModuleFunctions("1001").GetResultArray(6,BranchID.split(GlobalClass.ColDelim));
|
|
||||||
}
|
|
||||||
public String [][] FillApptypeList(String BranchID)
|
|
||||||
{
|
|
||||||
return new ModuleFunctions("1001").GetResultArray(8,BranchID.split(GlobalClass.ColDelim));
|
|
||||||
}
|
|
||||||
public String [][] FillCatList(String PortfolioID)
|
|
||||||
{
|
|
||||||
return new ModuleFunctions("1001").GetResultArray(9,PortfolioID.split(GlobalClass.ColDelim));
|
|
||||||
}
|
|
||||||
public String [][] FillDocList(String PortfolioID)
|
|
||||||
{
|
|
||||||
return new ModuleFunctions("1001").GetResultArray(7,PortfolioID.split(GlobalClass.ColDelim));
|
|
||||||
}
|
|
||||||
public String [][] FillBranchList(String PortfolioID)
|
|
||||||
{
|
|
||||||
return new ModuleFunctions("1001").GetResultArray(4,PortfolioID.split(GlobalClass.ColDelim));
|
|
||||||
}
|
|
||||||
public String [][] FillProductList(String PortfolioID)
|
|
||||||
{
|
|
||||||
return new ModuleFunctions("1001").GetResultArray(5,PortfolioID.split(GlobalClass.ColDelim));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
package matrix.nimble.edp.punching.controller;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import matrix.nimble.edp.punching.model.CaseGrid;
|
|
||||||
import matrix.nimble.model.Session;
|
|
||||||
import matrix.nimble.utilities.GlobalClass;
|
|
||||||
import matrix.nimble.utilities.ModuleFunctions;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.ui.ModelMap;
|
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
|
||||||
import org.springframework.web.bind.annotation.SessionAttributes;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
@SessionAttributes({"Sessvals"})
|
|
||||||
public class EditCasesGrid {
|
|
||||||
@RequestMapping(value="editgrid",method=RequestMethod.POST )
|
|
||||||
public String OpenEditGrid(ModelMap model,HttpServletRequest request,@ModelAttribute(value="Sessvals") Session Sessvals)
|
|
||||||
{
|
|
||||||
String [][]CaseList=null;
|
|
||||||
CaseGrid CG=new CaseGrid();
|
|
||||||
model.addAttribute("Sessvals",Sessvals);
|
|
||||||
model.addAttribute("caseList",CaseList);
|
|
||||||
model.addAttribute("caseGrid",CG);
|
|
||||||
model.addAttribute("portlist",FillPortList(Sessvals.getBranchID(),Sessvals.getUserID()));
|
|
||||||
return "edp/punching/editcases";
|
|
||||||
}
|
|
||||||
@RequestMapping(value="caselist",method=RequestMethod.POST)
|
|
||||||
public String ListCases(ModelMap model,HttpServletRequest request,@ModelAttribute(value="Sessvals") Session Sessvals,@ModelAttribute(value="caseGrid") CaseGrid caseGrid)
|
|
||||||
{
|
|
||||||
CaseGrid CG=new CaseGrid();
|
|
||||||
CG.setErrCode("1002");
|
|
||||||
CG.setPortfolioId(caseGrid.getPortfolioId());
|
|
||||||
String [][]CaseList=CG.FillCaseList(caseGrid.getPortfolioId(), Sessvals.getBranchID());
|
|
||||||
if(CG.isProcessFlag())
|
|
||||||
{
|
|
||||||
model.addAttribute("caseList",CaseList);
|
|
||||||
model.addAttribute("caseGrid",CG);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
caseGrid.setErrMsg(CG.getErrMsg());
|
|
||||||
model.addAttribute("caseList",CaseList);
|
|
||||||
model.addAttribute("caseGrid",caseGrid);
|
|
||||||
}
|
|
||||||
model.addAttribute("Sessvals",Sessvals);
|
|
||||||
model.addAttribute("portlist",FillPortList(Sessvals.getBranchID(),Sessvals.getUserID()));
|
|
||||||
return "edp/punching/editcases";
|
|
||||||
}
|
|
||||||
public String [][] FillPortList(String BranchId,String userId)
|
|
||||||
{
|
|
||||||
return new ModuleFunctions("1002").GetResultArray(249,(BranchId+GlobalClass.ColDelim+userId+GlobalClass.ColDelim).split(GlobalClass.ColDelim));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,278 +0,0 @@
|
|||||||
package matrix.nimble.edp.punching.controller;
|
|
||||||
|
|
||||||
//servlet libraries
|
|
||||||
import java.net.URLDecoder;
|
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
//spring libraries
|
|
||||||
import matrix.nimble.edp.punching.model.PunchingHandler;
|
|
||||||
import matrix.nimble.model.Session;
|
|
||||||
import matrix.nimble.utilities.CommonFunctions;
|
|
||||||
import matrix.nimble.utilities.GlobalClass;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.ui.ModelMap;
|
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.SessionAttributes;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
@SessionAttributes({"Sessvals"})
|
|
||||||
public class Punching {
|
|
||||||
@RequestMapping(value="initview",method=RequestMethod.POST )
|
|
||||||
public String InitializeScreen(ModelMap model,HttpServletRequest request,@ModelAttribute(value="Sessvals") Session Sessvals)
|
|
||||||
{
|
|
||||||
PunchingHandler PH=new PunchingHandler();
|
|
||||||
PH.setErrCode("1001");
|
|
||||||
model.addAttribute("visiblecontents","");
|
|
||||||
model.addAttribute("branchlist",null);
|
|
||||||
model.addAttribute("prodlist",null);
|
|
||||||
model.addAttribute("citylist",null);
|
|
||||||
model.addAttribute("typelist",null);
|
|
||||||
model.addAttribute("doclist",null);
|
|
||||||
model.addAttribute("catlist",null);
|
|
||||||
model.addAttribute("portfolio_id","-1");
|
|
||||||
model.addAttribute("Sessvals",Sessvals);
|
|
||||||
PH.GetDDValues(3, Sessvals.getBranchID().split(GlobalClass.ColDelim));
|
|
||||||
model.addAttribute("portlist",PH.getOptionvals());
|
|
||||||
model.addAttribute("formmode",0);
|
|
||||||
model.addAttribute("stat",true);
|
|
||||||
model.addAttribute("duuid","xxx");
|
|
||||||
model.addAttribute("msg","");
|
|
||||||
return "edp/punching/initcase";
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping(value="initdocview",method=RequestMethod.POST )
|
|
||||||
public String InitDocScreen(ModelMap model,HttpServletRequest request,@ModelAttribute(value="Sessvals") Session Sessvals)
|
|
||||||
{
|
|
||||||
|
|
||||||
PunchingHandler PH=new PunchingHandler();
|
|
||||||
PH.setErrCode("1901");
|
|
||||||
model.addAttribute("branchlist",null);
|
|
||||||
model.addAttribute("prodlist",null);
|
|
||||||
model.addAttribute("typelist",null);
|
|
||||||
model.addAttribute("doclist",null);
|
|
||||||
model.addAttribute("catlist",null);
|
|
||||||
model.addAttribute("portfolio_id","-1");
|
|
||||||
model.addAttribute("Sessvals",Sessvals);
|
|
||||||
PH.GetDDValues(240, Sessvals.getBranchID().split(GlobalClass.ColDelim));
|
|
||||||
model.addAttribute("portlist",PH.getOptionvals());
|
|
||||||
model.addAttribute("formmode",0);
|
|
||||||
model.addAttribute("stat",true);
|
|
||||||
model.addAttribute("msg","");
|
|
||||||
return "edp/punching/initdocs";
|
|
||||||
}
|
|
||||||
@RequestMapping(value="docadd",method=RequestMethod.POST )
|
|
||||||
public String PunchDocs(ModelMap model,HttpServletRequest request,@ModelAttribute(value="Sessvals") Session Sessvals)
|
|
||||||
{
|
|
||||||
String msg="";
|
|
||||||
PunchingHandler PH=new PunchingHandler();
|
|
||||||
CommonFunctions comFunc=new CommonFunctions();
|
|
||||||
PH.setErrCode("1901");
|
|
||||||
PH.setPortfolioid(request.getParameter("portfolio_id"));
|
|
||||||
PH.setProcessFlag(true);
|
|
||||||
PH.DocDynamicHtml();
|
|
||||||
if(PH.isProcessFlag())
|
|
||||||
{
|
|
||||||
model.addAttribute("dynamichtml",PH.getDynamicpanel());
|
|
||||||
model.addAttribute("dynamicfields",PH.getDynamicfields());
|
|
||||||
model.addAttribute("docdynamichtml",PH.getDocdynamicpanel());
|
|
||||||
model.addAttribute("docdynamicfields",PH.getDocdynamicfields());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
msg=PH.getErrMsg();
|
|
||||||
}
|
|
||||||
PH.GetDDValues(240, Sessvals.getBranchID().split(GlobalClass.ColDelim));
|
|
||||||
model.addAttribute("portlist",PH.getOptionvals());
|
|
||||||
PH.GetDDValues(4, PH.getPortfolioid().split(GlobalClass.ColDelim));
|
|
||||||
model.addAttribute("branchlist",PH.getOptionvals());
|
|
||||||
PH.GetDDValues(5, (Sessvals.getBranchID()+GlobalClass.ColDelim+"op.description='DOCUMENT' or op.description='APPTYPE'"+GlobalClass.ColDelim).split(GlobalClass.ColDelim));
|
|
||||||
if(PH.getOptionvals()!=null)
|
|
||||||
{
|
|
||||||
model.addAttribute("typelist",comFunc.GetSubArray("APPTYPE", 2, PH.getOptionvals()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
model.addAttribute("typelist",null);
|
|
||||||
}
|
|
||||||
PH.GetDDValues(241, PH.getPortfolioid().split(GlobalClass.ColDelim));
|
|
||||||
model.addAttribute("doclist",PH.getOptionvals());
|
|
||||||
PH.GetDDValues(70, (PH.getPortfolioid()+GlobalClass.ColDelim+"op.description='CATEGORY' or op.description='PRODUCT'"+GlobalClass.ColDelim).split(GlobalClass.ColDelim));
|
|
||||||
if(PH.getOptionvals()!=null)
|
|
||||||
{
|
|
||||||
model.addAttribute("prodlist",comFunc.GetSubArray("PRODUCT", 2, PH.getOptionvals()));
|
|
||||||
model.addAttribute("catlist",comFunc.GetSubArray("CATEGORY", 2, PH.getOptionvals()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
model.addAttribute("prodlist",null);
|
|
||||||
model.addAttribute("catlist",null);
|
|
||||||
}
|
|
||||||
model.addAttribute("portfolio_id",PH.getPortfolioid());
|
|
||||||
model.addAttribute("usid",Sessvals.getUserID());
|
|
||||||
model.addAttribute("Sessvals",Sessvals);
|
|
||||||
model.addAttribute("formmode",1);
|
|
||||||
model.addAttribute("stat",PH.isProcessFlag());
|
|
||||||
model.addAttribute("msg",msg);
|
|
||||||
return "edp/punching/initdocs";
|
|
||||||
}
|
|
||||||
@RequestMapping(value="addeditdoc",method=RequestMethod.POST )
|
|
||||||
public String AddEditDocs(@RequestParam String val0,@RequestParam String val1,@RequestParam String val2,@RequestParam String val3,@RequestParam String val4,@RequestParam String val5,@RequestParam String val6,@RequestParam String val7,@RequestParam String val8,@RequestParam String val9,@RequestParam String val10)
|
|
||||||
{
|
|
||||||
String retval="success";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
//System.out.println(URLDecoder.decode(val0,"UTF-8"));
|
|
||||||
//System.out.println(URLDecoder.decode(val1,"UTF-8"));
|
|
||||||
//System.out.println(URLDecoder.decode(val2,"UTF-8"));
|
|
||||||
//System.out.println(URLDecoder.decode(val3,"UTF-8"));
|
|
||||||
//System.out.println(URLDecoder.decode(val4,"UTF-8"));
|
|
||||||
//System.out.println(URLDecoder.decode(val6,"UTF-8"));
|
|
||||||
//System.out.println(URLDecoder.decode(val7,"UTF-8"));
|
|
||||||
//System.out.println(URLDecoder.decode(val8,"UTF-8"));
|
|
||||||
//System.out.println(URLDecoder.decode(val9,"UTF-8"));
|
|
||||||
//System.out.println(URLDecoder.decode(val10,"UTF-8"));
|
|
||||||
|
|
||||||
PunchingHandler PH=new PunchingHandler();
|
|
||||||
PH.setErrCode("1902");
|
|
||||||
PH.setProcessFlag(true);
|
|
||||||
|
|
||||||
PH.AddEditDocs(val0, val1, val2, val3, val4, val6, val7, val8, val9, val10);
|
|
||||||
|
|
||||||
}catch(Exception exce)
|
|
||||||
{
|
|
||||||
retval=exce.getMessage();
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
@RequestMapping(value="caseadd",method=RequestMethod.POST )
|
|
||||||
public String PunchCase(ModelMap model,HttpServletRequest request,@ModelAttribute(value="Sessvals") Session Sessvals)
|
|
||||||
{
|
|
||||||
String msg="";
|
|
||||||
PunchingHandler PH=new PunchingHandler();
|
|
||||||
CommonFunctions comFunc=new CommonFunctions();
|
|
||||||
PH.setErrCode("1001");
|
|
||||||
PH.setPortfolioid(request.getParameter("portfolio_id"));
|
|
||||||
PH.setProcessFlag(true);
|
|
||||||
PH.DynamicHtml("10");
|
|
||||||
if(PH.isProcessFlag())
|
|
||||||
{
|
|
||||||
model.addAttribute("dynamicfields",PH.getDynamicfields());
|
|
||||||
if(PH.isProcessFlag())
|
|
||||||
{
|
|
||||||
model.addAttribute("visiblecontents",(PH.GetVisibleSections()+""+PH.getDynamicsection()).replace("null", ""));
|
|
||||||
model.addAttribute("dynamichtml",PH.getDynamicpanel());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
msg=PH.getErrMsg();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
msg=PH.getErrMsg();
|
|
||||||
}
|
|
||||||
PH.GetDDValues(3, Sessvals.getBranchID().split(GlobalClass.ColDelim));
|
|
||||||
model.addAttribute("portlist",PH.getOptionvals());
|
|
||||||
PH.GetDDValues(4, PH.getPortfolioid().split(GlobalClass.ColDelim));
|
|
||||||
model.addAttribute("branchlist",PH.getOptionvals());
|
|
||||||
PH.GetDDValues(5, (Sessvals.getBranchID()+GlobalClass.ColDelim+"op.description='CITY' or op.description='APPTYPE'"+GlobalClass.ColDelim).split(GlobalClass.ColDelim));
|
|
||||||
if(PH.getOptionvals()!=null)
|
|
||||||
{
|
|
||||||
model.addAttribute("citylist",comFunc.GetSubArray("CITY", 2, PH.getOptionvals()));
|
|
||||||
model.addAttribute("typelist",comFunc.GetSubArray("APPTYPE", 2, PH.getOptionvals()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
model.addAttribute("citylist",null);
|
|
||||||
model.addAttribute("typelist",null);
|
|
||||||
}
|
|
||||||
PH.GetDDValues(70, (PH.getPortfolioid()+GlobalClass.ColDelim+"op.description='CATEGORY' or op.description='PRODUCT'"+GlobalClass.ColDelim).split(GlobalClass.ColDelim));
|
|
||||||
if(PH.getOptionvals()!=null)
|
|
||||||
{
|
|
||||||
model.addAttribute("prodlist",comFunc.GetSubArray("PRODUCT", 2, PH.getOptionvals()));
|
|
||||||
model.addAttribute("catlist",comFunc.GetSubArray("CATEGORY", 2, PH.getOptionvals()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
model.addAttribute("prodlist",null);
|
|
||||||
model.addAttribute("catlist",null);
|
|
||||||
}
|
|
||||||
model.addAttribute("portfolio_id",PH.getPortfolioid());
|
|
||||||
model.addAttribute("doclist",null);
|
|
||||||
model.addAttribute("usid",Sessvals.getUserID());
|
|
||||||
model.addAttribute("duuid","xxx");
|
|
||||||
model.addAttribute("Sessvals",Sessvals);
|
|
||||||
model.addAttribute("formmode",1);
|
|
||||||
model.addAttribute("stat",PH.isProcessFlag());
|
|
||||||
model.addAttribute("msg",msg);
|
|
||||||
return "edp/punching/initcase";
|
|
||||||
}
|
|
||||||
@RequestMapping(value="caseedit",method=RequestMethod.POST )
|
|
||||||
public String EditCase(ModelMap model,HttpServletRequest request,@ModelAttribute(value="Sessvals") Session Sessvals)
|
|
||||||
{
|
|
||||||
String msg="";
|
|
||||||
PunchingHandler PH=new PunchingHandler();
|
|
||||||
CommonFunctions comFunc=new CommonFunctions();
|
|
||||||
PH.setErrCode("1001");
|
|
||||||
PH.setPortfolioid(request.getParameter("PortfolioId"));
|
|
||||||
PH.setProcessFlag(true);
|
|
||||||
PH.DynamicHtml("10");
|
|
||||||
if(PH.isProcessFlag())
|
|
||||||
{
|
|
||||||
model.addAttribute("dynamicfields",PH.getDynamicfields());
|
|
||||||
if(PH.isProcessFlag())
|
|
||||||
{
|
|
||||||
model.addAttribute("visiblecontents",(PH.GetVisibleSections()+""+PH.getDynamicsection()).replace("null", ""));
|
|
||||||
model.addAttribute("dynamichtml",PH.getDynamicpanel());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
msg=PH.getErrMsg();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
msg=PH.getErrMsg();
|
|
||||||
}
|
|
||||||
PH.GetDDValues(3, Sessvals.getBranchID().split(GlobalClass.ColDelim));
|
|
||||||
model.addAttribute("portlist",PH.getOptionvals());
|
|
||||||
PH.GetDDValues(4, PH.getPortfolioid().split(GlobalClass.ColDelim));
|
|
||||||
model.addAttribute("branchlist",PH.getOptionvals());
|
|
||||||
PH.GetDDValues(5, (Sessvals.getBranchID()+GlobalClass.ColDelim+"op.description='CITY' or op.description='APPTYPE'"+GlobalClass.ColDelim).split(GlobalClass.ColDelim));
|
|
||||||
if(PH.getOptionvals()!=null)
|
|
||||||
{
|
|
||||||
model.addAttribute("citylist",comFunc.GetSubArray("CITY", 2, PH.getOptionvals()));
|
|
||||||
model.addAttribute("typelist",comFunc.GetSubArray("APPTYPE", 2, PH.getOptionvals()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
model.addAttribute("citylist",null);
|
|
||||||
model.addAttribute("typelist",null);
|
|
||||||
}
|
|
||||||
PH.GetDDValues(70, (PH.getPortfolioid()+GlobalClass.ColDelim+"op.description='CATEGORY' or op.description='PRODUCT'"+GlobalClass.ColDelim).split(GlobalClass.ColDelim));
|
|
||||||
if(PH.getOptionvals()!=null)
|
|
||||||
{
|
|
||||||
model.addAttribute("prodlist",comFunc.GetSubArray("PRODUCT", 2, PH.getOptionvals()));
|
|
||||||
model.addAttribute("catlist",comFunc.GetSubArray("CATEGORY", 2, PH.getOptionvals()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
model.addAttribute("prodlist",null);
|
|
||||||
model.addAttribute("catlist",null);
|
|
||||||
}
|
|
||||||
model.addAttribute("portfolio_id",PH.getPortfolioid());
|
|
||||||
model.addAttribute("doclist",null);
|
|
||||||
model.addAttribute("usid",Sessvals.getUserID());
|
|
||||||
model.addAttribute("Sessvals",Sessvals);
|
|
||||||
model.addAttribute("formmode",2);
|
|
||||||
model.addAttribute("duuid",request.getParameter("uuid"));
|
|
||||||
model.addAttribute("stat",PH.isProcessFlag());
|
|
||||||
model.addAttribute("msg",msg);
|
|
||||||
return "edp/punching/initcase";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
package matrix.nimble.edp.punching.controllers;
|
||||||
|
|
||||||
|
//servlet libraries
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpSession;
|
||||||
|
|
||||||
|
//spring libraries
|
||||||
|
import matrix.nimble.edp.punching.model.CaseDetails;
|
||||||
|
import matrix.nimble.model.Session;
|
||||||
|
import matrix.nimble.utilities.ModuleFunctions;
|
||||||
|
import matrix.nimble.utilities.GlobalClass;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.SessionAttributes;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
@SessionAttributes({ "Sessvals" })
|
||||||
|
public class CasePucnhing {
|
||||||
|
@RequestMapping(value = "caseadd1", method = RequestMethod.POST)
|
||||||
|
public String OpenAddCases(ModelMap model, HttpServletRequest request,
|
||||||
|
@ModelAttribute(value = "Sessvals") Session Sessvals) {
|
||||||
|
CaseDetails caseDetails = new CaseDetails();
|
||||||
|
caseDetails.setFormMode(1);
|
||||||
|
caseDetails.setErrMsg("");
|
||||||
|
model.addAttribute("visibleContents", "");
|
||||||
|
model.addAttribute("caseDetails", caseDetails);
|
||||||
|
model.addAttribute("branchlist", FillBranchList("0"));
|
||||||
|
model.addAttribute("prodlist", FillProductList("0"));
|
||||||
|
model.addAttribute("citylist", FillCityList("0"));
|
||||||
|
model.addAttribute("typelist", FillApptypeList("0"));
|
||||||
|
model.addAttribute("doclist", FillDocList("0"));
|
||||||
|
model.addAttribute("catlist", FillCatList("0"));
|
||||||
|
model.addAttribute("Sessvals", Sessvals);
|
||||||
|
model.addAttribute("portlist", FillPortList(Sessvals.getBranchID()));
|
||||||
|
return "edp/punching/addcases";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "casesave", method = RequestMethod.POST)
|
||||||
|
public String SaveCase(ModelMap model, HttpServletRequest request,
|
||||||
|
@ModelAttribute(value = "Sessvals") Session Sessvals,
|
||||||
|
@ModelAttribute(value = "caseDetails") CaseDetails caseDet, HttpSession session) {
|
||||||
|
String DynamicNsessVals = "";
|
||||||
|
CaseDetails caseDetails = new CaseDetails();
|
||||||
|
caseDet.setErrCode("1001");
|
||||||
|
if (caseDet.getDynamicFields() != "") {
|
||||||
|
String[] DynamicFields = caseDet.getDynamicFields().split(GlobalClass.ColDelim);
|
||||||
|
for (int indx = 0; indx < DynamicFields.length; indx++) {
|
||||||
|
// DynamicNsessVals=DynamicNsessVals+request.getParameter(DynamicFields[indx])+Delimeter.ColDelim;
|
||||||
|
caseDet.InvokeSetter("set" + DynamicFields[indx], request.getParameter(DynamicFields[indx]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (caseDet.getFormMode() == 1 || caseDet.getFormMode() == 2) {
|
||||||
|
DynamicNsessVals = DynamicNsessVals + "" + Sessvals.getUserID() + GlobalClass.ColDelim;
|
||||||
|
DynamicNsessVals = DynamicNsessVals + "" + Sessvals.getCompanyID() + GlobalClass.ColDelim;
|
||||||
|
DynamicNsessVals = DynamicNsessVals + "" + Sessvals.getBranchID();
|
||||||
|
}
|
||||||
|
if (!session.getAttribute("UUID").toString().equals(caseDet.getUUID())) {
|
||||||
|
caseDetails.setProcessFlag(true);
|
||||||
|
caseDetails.setErrMsg("");
|
||||||
|
} else {
|
||||||
|
caseDet.SaveDetails(DynamicNsessVals);
|
||||||
|
caseDetails.setProcessFlag(caseDet.isProcessFlag());
|
||||||
|
caseDetails.setErrMsg(caseDet.getErrMsg());
|
||||||
|
}
|
||||||
|
String VisibleContents = caseDet.getVisibleContents();
|
||||||
|
if (caseDetails.isProcessFlag()) {
|
||||||
|
String UUID = GlobalClass.GenerateUUID();
|
||||||
|
caseDetails.setUUID(UUID);
|
||||||
|
session.setAttribute("UUID", UUID);
|
||||||
|
caseDetails.setErrCode("1001");
|
||||||
|
caseDetails.setFormMode(caseDet.getFormMode());
|
||||||
|
caseDetails.setVisibleContents(VisibleContents);
|
||||||
|
caseDetails.setPortfolioId(caseDet.getPortfolioId());
|
||||||
|
caseDetails = caseDetails.DynamicHtml(caseDetails, caseDet.getPortfolioId());
|
||||||
|
caseDetails.setDynamicFields(caseDet.getDynamicFields());
|
||||||
|
VisibleContents = VisibleContents + "" + caseDetails.getDynamicSection();
|
||||||
|
model.addAttribute("caseDetails", caseDetails);
|
||||||
|
} else {
|
||||||
|
caseDet = caseDet.DynamicHtml(caseDet, caseDet.getPortfolioId());
|
||||||
|
VisibleContents = VisibleContents + "" + caseDet.getDynamicSection();
|
||||||
|
model.addAttribute("caseDetails", caseDet);
|
||||||
|
}
|
||||||
|
model.addAttribute("visibleContents", VisibleContents);
|
||||||
|
model.addAttribute("branchlist", FillBranchList(caseDet.getPortfolioId()));
|
||||||
|
model.addAttribute("prodlist", FillProductList(caseDet.getPortfolioId()));
|
||||||
|
model.addAttribute("citylist", FillCityList(Sessvals.getBranchID()));
|
||||||
|
model.addAttribute("typelist", FillApptypeList(Sessvals.getBranchID()));
|
||||||
|
model.addAttribute("doclist", FillDocList(caseDet.getPortfolioId()));
|
||||||
|
model.addAttribute("catlist", FillCatList(caseDet.getPortfolioId()));
|
||||||
|
model.addAttribute("Sessvals", Sessvals);
|
||||||
|
model.addAttribute("portlist", FillPortList(Sessvals.getBranchID()));
|
||||||
|
return "edp/punching/addcases";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "casedet", method = RequestMethod.POST)
|
||||||
|
public String GetRequiredData(ModelMap model, HttpServletRequest request,
|
||||||
|
@ModelAttribute(value = "Sessvals") Session Sessvals,
|
||||||
|
@ModelAttribute(value = "caseDetails") CaseDetails caseDet, HttpSession session) {
|
||||||
|
CaseDetails caseDetails = new CaseDetails();
|
||||||
|
caseDetails.setPortfolioId(caseDet.getPortfolioId());
|
||||||
|
caseDetails.setErrCode("1001");
|
||||||
|
String UUID = GlobalClass.GenerateUUID();
|
||||||
|
caseDetails.setUUID(UUID);
|
||||||
|
session.setAttribute("UUID", UUID);
|
||||||
|
caseDetails.setFormMode(caseDet.getFormMode());
|
||||||
|
caseDetails = caseDetails.DynamicHtml(caseDetails, caseDet.getPortfolioId());
|
||||||
|
String VisibleContents = (new ModuleFunctions("1001").GetDDHashString(10,
|
||||||
|
("10" + GlobalClass.ColDelim + caseDet.getPortfolioId()).split(GlobalClass.ColDelim)))
|
||||||
|
.replace(GlobalClass.RowDelim, "");
|
||||||
|
caseDetails.setVisibleContents(VisibleContents);
|
||||||
|
VisibleContents = (VisibleContents + "" + caseDetails.getDynamicSection())
|
||||||
|
.replace(GlobalClass.ColDelim + "null", "");
|
||||||
|
model.addAttribute("visibleContents", VisibleContents);
|
||||||
|
model.addAttribute("caseDetails", caseDetails);
|
||||||
|
model.addAttribute("portlist", Sessvals.getBranchID());
|
||||||
|
model.addAttribute("branchlist", FillBranchList(caseDet.getPortfolioId()));
|
||||||
|
model.addAttribute("prodlist", FillProductList(caseDet.getPortfolioId()));
|
||||||
|
model.addAttribute("citylist", FillCityList(Sessvals.getBranchID()));
|
||||||
|
model.addAttribute("typelist", FillApptypeList(Sessvals.getBranchID()));
|
||||||
|
model.addAttribute("doclist", FillDocList(caseDet.getPortfolioId()));
|
||||||
|
model.addAttribute("catlist", FillCatList(caseDet.getPortfolioId()));
|
||||||
|
model.addAttribute("Sessvals", Sessvals);
|
||||||
|
model.addAttribute("portlist", FillPortList(Sessvals.getBranchID()));
|
||||||
|
return "edp/punching/addcases";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[][] FillPortList(String BranchId) {
|
||||||
|
return new ModuleFunctions("1001").GetResultArray(3,
|
||||||
|
(BranchId + GlobalClass.ColDelim).split(GlobalClass.ColDelim));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[][] FillCityList(String BranchID) {
|
||||||
|
return new ModuleFunctions("1001").GetResultArray(6, BranchID.split(GlobalClass.ColDelim));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[][] FillApptypeList(String BranchID) {
|
||||||
|
return new ModuleFunctions("1001").GetResultArray(8, BranchID.split(GlobalClass.ColDelim));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[][] FillCatList(String PortfolioID) {
|
||||||
|
return new ModuleFunctions("1001").GetResultArray(9, PortfolioID.split(GlobalClass.ColDelim));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[][] FillDocList(String PortfolioID) {
|
||||||
|
return new ModuleFunctions("1001").GetResultArray(7, PortfolioID.split(GlobalClass.ColDelim));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[][] FillBranchList(String PortfolioID) {
|
||||||
|
return new ModuleFunctions("1001").GetResultArray(4, PortfolioID.split(GlobalClass.ColDelim));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[][] FillProductList(String PortfolioID) {
|
||||||
|
return new ModuleFunctions("1001").GetResultArray(5, PortfolioID.split(GlobalClass.ColDelim));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package matrix.nimble.edp.punching.controllers;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import matrix.nimble.edp.punching.model.CaseGrid;
|
||||||
|
import matrix.nimble.model.Session;
|
||||||
|
import matrix.nimble.utilities.GlobalClass;
|
||||||
|
import matrix.nimble.utilities.ModuleFunctions;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.bind.annotation.SessionAttributes;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
@SessionAttributes({ "Sessvals" })
|
||||||
|
public class EditCasesGrid {
|
||||||
|
@RequestMapping(value = "editgrid", method = RequestMethod.POST)
|
||||||
|
public String OpenEditGrid(ModelMap model, HttpServletRequest request,
|
||||||
|
@ModelAttribute(value = "Sessvals") Session Sessvals) {
|
||||||
|
String[][] CaseList = null;
|
||||||
|
CaseGrid CG = new CaseGrid();
|
||||||
|
model.addAttribute("Sessvals", Sessvals);
|
||||||
|
model.addAttribute("caseList", CaseList);
|
||||||
|
model.addAttribute("caseGrid", CG);
|
||||||
|
model.addAttribute("portlist", FillPortList(Sessvals.getBranchID(), Sessvals.getUserID()));
|
||||||
|
return "edp/punching/editcases";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "caselist", method = RequestMethod.POST)
|
||||||
|
public String ListCases(ModelMap model, HttpServletRequest request,
|
||||||
|
@ModelAttribute(value = "Sessvals") Session Sessvals,
|
||||||
|
@ModelAttribute(value = "caseGrid") CaseGrid caseGrid) {
|
||||||
|
CaseGrid CG = new CaseGrid();
|
||||||
|
CG.setErrCode("1002");
|
||||||
|
CG.setPortfolioId(caseGrid.getPortfolioId());
|
||||||
|
String[][] CaseList = CG.FillCaseList(caseGrid.getPortfolioId(), Sessvals.getBranchID());
|
||||||
|
if (CG.isProcessFlag()) {
|
||||||
|
model.addAttribute("caseList", CaseList);
|
||||||
|
model.addAttribute("caseGrid", CG);
|
||||||
|
} else {
|
||||||
|
caseGrid.setErrMsg(CG.getErrMsg());
|
||||||
|
model.addAttribute("caseList", CaseList);
|
||||||
|
model.addAttribute("caseGrid", caseGrid);
|
||||||
|
}
|
||||||
|
model.addAttribute("Sessvals", Sessvals);
|
||||||
|
model.addAttribute("portlist", FillPortList(Sessvals.getBranchID(), Sessvals.getUserID()));
|
||||||
|
return "edp/punching/editcases";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[][] FillPortList(String BranchId, String userId) {
|
||||||
|
return new ModuleFunctions("1002").GetResultArray(249,
|
||||||
|
(BranchId + GlobalClass.ColDelim + userId + GlobalClass.ColDelim).split(GlobalClass.ColDelim));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
package matrix.nimble.edp.punching.controllers;
|
||||||
|
|
||||||
|
//servlet libraries
|
||||||
|
import java.net.URLDecoder;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
//spring libraries
|
||||||
|
import matrix.nimble.edp.punching.model.PunchingHandler;
|
||||||
|
import matrix.nimble.model.Session;
|
||||||
|
import matrix.nimble.utilities.CommonFunctions;
|
||||||
|
import matrix.nimble.utilities.GlobalClass;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.SessionAttributes;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
@SessionAttributes({ "Sessvals" })
|
||||||
|
public class Punching {
|
||||||
|
|
||||||
|
@RequestMapping(value = "initdocview", method = RequestMethod.POST)
|
||||||
|
public String InitDocScreen(ModelMap model, HttpServletRequest request,
|
||||||
|
@ModelAttribute(value = "Sessvals") Session Sessvals) {
|
||||||
|
|
||||||
|
PunchingHandler PH = new PunchingHandler();
|
||||||
|
PH.setErrCode("1901");
|
||||||
|
model.addAttribute("branchlist", null);
|
||||||
|
model.addAttribute("prodlist", null);
|
||||||
|
model.addAttribute("typelist", null);
|
||||||
|
model.addAttribute("doclist", null);
|
||||||
|
model.addAttribute("catlist", null);
|
||||||
|
model.addAttribute("portfolio_id", "-1");
|
||||||
|
model.addAttribute("Sessvals", Sessvals);
|
||||||
|
PH.GetDDValues(240, Sessvals.getBranchID().split(GlobalClass.ColDelim));
|
||||||
|
model.addAttribute("portlist", PH.getOptionvals());
|
||||||
|
model.addAttribute("formmode", 0);
|
||||||
|
model.addAttribute("stat", true);
|
||||||
|
model.addAttribute("msg", "");
|
||||||
|
return "edp/punching/initdocs";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "docadd", method = RequestMethod.POST)
|
||||||
|
public String PunchDocs(ModelMap model, HttpServletRequest request,
|
||||||
|
@ModelAttribute(value = "Sessvals") Session Sessvals) {
|
||||||
|
String msg = "";
|
||||||
|
PunchingHandler PH = new PunchingHandler();
|
||||||
|
CommonFunctions comFunc = new CommonFunctions();
|
||||||
|
PH.setErrCode("1901");
|
||||||
|
PH.setPortfolioid(request.getParameter("portfolio_id"));
|
||||||
|
PH.setProcessFlag(true);
|
||||||
|
PH.DocDynamicHtml();
|
||||||
|
if (PH.isProcessFlag()) {
|
||||||
|
model.addAttribute("dynamichtml", PH.getDynamicpanel());
|
||||||
|
model.addAttribute("dynamicfields", PH.getDynamicfields());
|
||||||
|
model.addAttribute("docdynamichtml", PH.getDocdynamicpanel());
|
||||||
|
model.addAttribute("docdynamicfields", PH.getDocdynamicfields());
|
||||||
|
} else {
|
||||||
|
msg = PH.getErrMsg();
|
||||||
|
}
|
||||||
|
PH.GetDDValues(240, Sessvals.getBranchID().split(GlobalClass.ColDelim));
|
||||||
|
model.addAttribute("portlist", PH.getOptionvals());
|
||||||
|
PH.GetDDValues(4, PH.getPortfolioid().split(GlobalClass.ColDelim));
|
||||||
|
model.addAttribute("branchlist", PH.getOptionvals());
|
||||||
|
PH.GetDDValues(5,
|
||||||
|
(Sessvals.getBranchID() + GlobalClass.ColDelim + "op.description='DOCUMENT' or op.description='APPTYPE'"
|
||||||
|
+ GlobalClass.ColDelim).split(GlobalClass.ColDelim));
|
||||||
|
if (PH.getOptionvals() != null) {
|
||||||
|
model.addAttribute("typelist", comFunc.GetSubArray("APPTYPE", 2, PH.getOptionvals()));
|
||||||
|
} else {
|
||||||
|
model.addAttribute("typelist", null);
|
||||||
|
}
|
||||||
|
PH.GetDDValues(241, PH.getPortfolioid().split(GlobalClass.ColDelim));
|
||||||
|
model.addAttribute("doclist", PH.getOptionvals());
|
||||||
|
PH.GetDDValues(70,
|
||||||
|
(PH.getPortfolioid() + GlobalClass.ColDelim + "op.description='CATEGORY' or op.description='PRODUCT'"
|
||||||
|
+ GlobalClass.ColDelim).split(GlobalClass.ColDelim));
|
||||||
|
if (PH.getOptionvals() != null) {
|
||||||
|
model.addAttribute("prodlist", comFunc.GetSubArray("PRODUCT", 2, PH.getOptionvals()));
|
||||||
|
model.addAttribute("catlist", comFunc.GetSubArray("CATEGORY", 2, PH.getOptionvals()));
|
||||||
|
} else {
|
||||||
|
model.addAttribute("prodlist", null);
|
||||||
|
model.addAttribute("catlist", null);
|
||||||
|
}
|
||||||
|
model.addAttribute("portfolio_id", PH.getPortfolioid());
|
||||||
|
model.addAttribute("usid", Sessvals.getUserID());
|
||||||
|
model.addAttribute("Sessvals", Sessvals);
|
||||||
|
model.addAttribute("formmode", 1);
|
||||||
|
model.addAttribute("stat", PH.isProcessFlag());
|
||||||
|
model.addAttribute("msg", msg);
|
||||||
|
return "edp/punching/initdocs";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "addeditdoc", method = RequestMethod.POST)
|
||||||
|
public String AddEditDocs(@RequestParam String val0, @RequestParam String val1, @RequestParam String val2,
|
||||||
|
@RequestParam String val3, @RequestParam String val4, @RequestParam String val5, @RequestParam String val6,
|
||||||
|
@RequestParam String val7, @RequestParam String val8, @RequestParam String val9,
|
||||||
|
@RequestParam String val10) {
|
||||||
|
String retval = "success";
|
||||||
|
try {
|
||||||
|
// System.out.println(URLDecoder.decode(val0,"UTF-8"));
|
||||||
|
// System.out.println(URLDecoder.decode(val1,"UTF-8"));
|
||||||
|
// System.out.println(URLDecoder.decode(val2,"UTF-8"));
|
||||||
|
// System.out.println(URLDecoder.decode(val3,"UTF-8"));
|
||||||
|
// System.out.println(URLDecoder.decode(val4,"UTF-8"));
|
||||||
|
// System.out.println(URLDecoder.decode(val6,"UTF-8"));
|
||||||
|
// System.out.println(URLDecoder.decode(val7,"UTF-8"));
|
||||||
|
// System.out.println(URLDecoder.decode(val8,"UTF-8"));
|
||||||
|
// System.out.println(URLDecoder.decode(val9,"UTF-8"));
|
||||||
|
// System.out.println(URLDecoder.decode(val10,"UTF-8"));
|
||||||
|
|
||||||
|
PunchingHandler PH = new PunchingHandler();
|
||||||
|
PH.setErrCode("1902");
|
||||||
|
PH.setProcessFlag(true);
|
||||||
|
|
||||||
|
PH.AddEditDocs(val0, val1, val2, val3, val4, val6, val7, val8, val9, val10);
|
||||||
|
|
||||||
|
} catch (Exception exce) {
|
||||||
|
retval = exce.getMessage();
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
package matrix.nimble.edp.punching.controllers;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpSession;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import matrix.nimble.controller.AbstractAuthenticatedController;
|
||||||
|
import matrix.nimble.model.Session;
|
||||||
|
import matrix.services.commons.CommonService;
|
||||||
|
import matrix.services.edp.PunchingService;
|
||||||
|
import matrix.services.commons.CommonErrorService;
|
||||||
|
import lib.models.CasePunching;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
|
||||||
|
public class PunchingController extends AbstractAuthenticatedController {
|
||||||
|
private static final String INIT_VIEW_ROUTE = "initview";
|
||||||
|
private final PunchingService punchingService;
|
||||||
|
|
||||||
|
public PunchingController(CommonService commonService, CommonErrorService errorService,
|
||||||
|
PunchingService punchingService) {
|
||||||
|
super(commonService, errorService);
|
||||||
|
this.punchingService = punchingService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = INIT_VIEW_ROUTE, method = RequestMethod.POST)
|
||||||
|
public String InitializeScreen(
|
||||||
|
ModelMap model,
|
||||||
|
HttpSession httpSession,
|
||||||
|
HttpServletResponse response) {
|
||||||
|
PageAuthorization authorization = authorizePage(
|
||||||
|
INIT_VIEW_ROUTE, model, httpSession, response);
|
||||||
|
if (!authorization.isGranted()) {
|
||||||
|
return authorization.viewName();
|
||||||
|
}
|
||||||
|
Session Sessvals = authorization.session();
|
||||||
|
|
||||||
|
model.addAttribute("model", punchingService.init(
|
||||||
|
Sessvals.getBranchID(), Sessvals.getUserID(), null, "xxx"));
|
||||||
|
model.addAttribute("Sessvals", Sessvals);
|
||||||
|
return "edp/punching/initcase";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "caseadd", method = RequestMethod.POST)
|
||||||
|
public String addCase(
|
||||||
|
@ModelAttribute("model") CasePunching submitted,
|
||||||
|
ModelMap model,
|
||||||
|
HttpSession httpSession,
|
||||||
|
HttpServletResponse response) {
|
||||||
|
PageAuthorization authorization = authorizePage(
|
||||||
|
INIT_VIEW_ROUTE, model, httpSession, response);
|
||||||
|
if (!authorization.isGranted()) {
|
||||||
|
return authorization.viewName();
|
||||||
|
}
|
||||||
|
|
||||||
|
Session session = authorization.session();
|
||||||
|
model.addAttribute("model", punchingService.addCase(
|
||||||
|
submitted, session.getBranchID(), session.getUserID()));
|
||||||
|
model.addAttribute("Sessvals", session);
|
||||||
|
return "edp/punching/initcase";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "caseedit", method = RequestMethod.POST)
|
||||||
|
public String editCase(
|
||||||
|
@RequestParam("PortfolioId") Integer portfolioId,
|
||||||
|
@RequestParam("uuid") String documentCaseId,
|
||||||
|
ModelMap model,
|
||||||
|
HttpSession httpSession,
|
||||||
|
HttpServletResponse response) {
|
||||||
|
PageAuthorization authorization = authorizePage(
|
||||||
|
INIT_VIEW_ROUTE, model, httpSession, response);
|
||||||
|
if (!authorization.isGranted()) {
|
||||||
|
return authorization.viewName();
|
||||||
|
}
|
||||||
|
|
||||||
|
Session session = authorization.session();
|
||||||
|
model.addAttribute("model", punchingService.editCase(
|
||||||
|
portfolioId, documentCaseId, session.getBranchID(), session.getUserID()));
|
||||||
|
model.addAttribute("Sessvals", session);
|
||||||
|
return "edp/punching/initcase";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package matrix.nimble.query;
|
||||||
|
|
||||||
|
import com.cygnus.db.QueryDefinition;
|
||||||
|
import com.cygnus.db.QueryDefinitionProvider;
|
||||||
|
|
||||||
|
public final class CloudQueryDefinitionProvider implements QueryDefinitionProvider {
|
||||||
|
private final QueryProvider provider;
|
||||||
|
|
||||||
|
public CloudQueryDefinitionProvider(QueryProvider provider) {
|
||||||
|
this.provider = provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryDefinition get(int queryId) {
|
||||||
|
return QueryDefinition.parse(queryId, provider.getQuery(queryId));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package matrix.nimble.query;
|
||||||
|
|
||||||
|
import com.cygnus.db.CygnusDbExecutor;
|
||||||
|
import com.cygnus.db.ExecutorOptions;
|
||||||
|
import com.cygnus.db.JdbcCygnusDbExecutor;
|
||||||
|
import matrix.nimble.utilities.DatabaseConnectionPool;
|
||||||
|
import org.springframework.beans.factory.DisposableBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class ModernDbConfiguration implements DisposableBean {
|
||||||
|
private CygnusDbExecutor installed;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
CygnusDbExecutor cygnusDbExecutor(
|
||||||
|
QueryProvider queryProvider,
|
||||||
|
@Value("${CYGNUS_DB_FETCH_SIZE:250}") int fetchSize,
|
||||||
|
@Value("${CYGNUS_DB_QUERY_TIMEOUT_SECONDS:60}") int queryTimeoutSeconds) {
|
||||||
|
installed = new JdbcCygnusDbExecutor(
|
||||||
|
DatabaseConnectionPool.dataSource(),
|
||||||
|
new CloudQueryDefinitionProvider(queryProvider),
|
||||||
|
new ExecutorOptions(fetchSize, queryTimeoutSeconds));
|
||||||
|
ModernDbExecutors.install(installed);
|
||||||
|
return installed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
if (installed != null)
|
||||||
|
ModernDbExecutors.clear(installed);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package matrix.nimble.query;
|
||||||
|
|
||||||
|
import com.cygnus.db.CygnusDbExecutor;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
public final class ModernDbExecutors {
|
||||||
|
private static final AtomicReference<CygnusDbExecutor> CURRENT = new AtomicReference<>();
|
||||||
|
|
||||||
|
private ModernDbExecutors() {}
|
||||||
|
|
||||||
|
public static void install(CygnusDbExecutor executor) {
|
||||||
|
CURRENT.set(java.util.Objects.requireNonNull(executor, "executor"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CygnusDbExecutor current() {
|
||||||
|
CygnusDbExecutor executor = CURRENT.get();
|
||||||
|
if (executor == null) throw new IllegalStateException("Modern database executor is not initialized");
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clear(CygnusDbExecutor executor) {
|
||||||
|
CURRENT.compareAndSet(executor, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
public final class RedisCachingQueryProvider implements QueryProvider {
|
public final class RedisCachingQueryProvider implements QueryProvider {
|
||||||
|
|
||||||
public static final Duration QUERY_TTL = Duration.ofHours(12);
|
public static final Duration QUERY_TTL = Duration.ofHours(3);
|
||||||
private static final Logger LOGGER = Logger.getLogger(RedisCachingQueryProvider.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(RedisCachingQueryProvider.class.getName());
|
||||||
private static final int LOCK_COUNT = 64;
|
private static final int LOCK_COUNT = 64;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
package matrix.nimble.utilities;
|
package matrix.nimble.utilities;
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import com.cygnus.db.DbResult;
|
||||||
|
import com.cygnus.db.RowMapper;
|
||||||
|
import com.cygnus.db.RowView;
|
||||||
|
import com.cygnus.db.RowConsumer;
|
||||||
|
import com.cygnus.db.TransactionCallback;
|
||||||
|
import matrix.nimble.query.ModernDbExecutors;
|
||||||
|
|
||||||
public class DBFunctions {
|
public class DBFunctions {
|
||||||
private Connection con;
|
private Connection con;
|
||||||
@@ -294,7 +302,7 @@ public class DBFunctions {
|
|||||||
}
|
}
|
||||||
return DataSet;
|
return DataSet;
|
||||||
}
|
}
|
||||||
public String FetchRunQuery(int QueryCode,String Vals[])
|
public String FetchRunQuery(int QueryCode,String Vals[])
|
||||||
{
|
{
|
||||||
InitConfiguration();
|
InitConfiguration();
|
||||||
setErrMsg("");
|
setErrMsg("");
|
||||||
@@ -367,7 +375,60 @@ public class DBFunctions {
|
|||||||
{
|
{
|
||||||
return getErrMsg();
|
return getErrMsg();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DbResult<RowView> execute(int queryId, Object[] parameters) {
|
||||||
|
return ModernDbExecutors.current().execute(queryId, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> DbResult<T> execute(int queryId, Object[] parameters, Class<T> responseType) {
|
||||||
|
return ModernDbExecutors.current().execute(queryId, parameters, responseType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> List<T> query(int queryId, Object[] parameters, Class<T> responseType) {
|
||||||
|
return ModernDbExecutors.current().query(queryId, parameters, responseType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> List<T> query(int queryId, Object[] parameters, RowMapper<T> mapper) {
|
||||||
|
return ModernDbExecutors.current().query(queryId, parameters, mapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> Optional<T> queryOne(int queryId, Object[] parameters, Class<T> responseType) {
|
||||||
|
return ModernDbExecutors.current().queryOne(queryId, parameters, responseType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int insert(int queryId, Object[] parameters) {
|
||||||
|
return ModernDbExecutors.current().insert(queryId, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <K> K insert(int queryId, Object[] parameters, Class<K> generatedKeyType) {
|
||||||
|
return ModernDbExecutors.current().insert(queryId, parameters, generatedKeyType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int update(int queryId, Object[] parameters) {
|
||||||
|
return ModernDbExecutors.current().update(queryId, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int delete(int queryId, Object[] parameters) {
|
||||||
|
return ModernDbExecutors.current().delete(queryId, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T procedure(int queryId, Object[] parameters, Class<T> responseType) {
|
||||||
|
return ModernDbExecutors.current().procedure(queryId, parameters, responseType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> List<T> procedureRows(int queryId, Object[] parameters, Class<T> responseType) {
|
||||||
|
return ModernDbExecutors.current().procedureRows(queryId, parameters, responseType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> void stream(
|
||||||
|
int queryId, Object[] parameters, RowMapper<T> mapper, RowConsumer<T> consumer) {
|
||||||
|
ModernDbExecutors.current().stream(queryId, parameters, mapper, consumer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T transaction(TransactionCallback<T> callback) {
|
||||||
|
return ModernDbExecutors.current().transaction(callback);
|
||||||
|
}
|
||||||
@SuppressWarnings("finally")
|
@SuppressWarnings("finally")
|
||||||
public String QueryBuilder(String Query,String[] Val)
|
public String QueryBuilder(String Query,String[] Val)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import java.sql.SQLException;
|
|||||||
|
|
||||||
import com.zaxxer.hikari.HikariConfig;
|
import com.zaxxer.hikari.HikariConfig;
|
||||||
import com.zaxxer.hikari.HikariDataSource;
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
/** Shared, bounded JDBC connection pool for the legacy database layer. */
|
/** Shared, bounded JDBC connection pool for the legacy database layer. */
|
||||||
public final class DatabaseConnectionPool {
|
public final class DatabaseConnectionPool {
|
||||||
@@ -20,6 +21,10 @@ public final class DatabaseConnectionPool {
|
|||||||
return getDataSource().getConnection();
|
return getDataSource().getConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static DataSource dataSource() {
|
||||||
|
return getDataSource();
|
||||||
|
}
|
||||||
|
|
||||||
private static HikariDataSource getDataSource() {
|
private static HikariDataSource getDataSource() {
|
||||||
HikariDataSource current = dataSource;
|
HikariDataSource current = dataSource;
|
||||||
if (current != null) {
|
if (current != null) {
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package matrix.services.commons;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import jakarta.servlet.http.HttpSession;
|
||||||
|
import lib.models.ErrorDetails;
|
||||||
|
import matrix.nimble.model.Session;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.ui.ModelMap;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class CommonErrorService {
|
||||||
|
public static final String ERROR_ATTRIBUTE = "errorDetails";
|
||||||
|
private final CommonService commonService;
|
||||||
|
|
||||||
|
public CommonErrorService(CommonService commonService) {
|
||||||
|
this.commonService = commonService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String render(
|
||||||
|
ModelMap model,
|
||||||
|
HttpServletResponse response,
|
||||||
|
HttpSession httpSession,
|
||||||
|
ErrorDetails errorDetails) {
|
||||||
|
response.setStatus(errorDetails.getHttpStatus());
|
||||||
|
model.addAttribute(ERROR_ATTRIBUTE, errorDetails);
|
||||||
|
|
||||||
|
Session session = commonService.getSession(httpSession);
|
||||||
|
if (session != null) {
|
||||||
|
model.addAttribute(CommonService.SESSION_ATTRIBUTE, session);
|
||||||
|
}
|
||||||
|
return "error";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
package matrix.services.commons;
|
||||||
|
|
||||||
|
import com.cygnus.db.CygnusDbExecutor;
|
||||||
|
import jakarta.servlet.http.HttpSession;
|
||||||
|
import lib.models.Option;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import matrix.nimble.model.Session;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class CommonService {
|
||||||
|
public static final String SESSION_ATTRIBUTE = "Sessvals";
|
||||||
|
|
||||||
|
private static final Pattern MENU_COMMAND = Pattern.compile(
|
||||||
|
"SubmitMenuCommand\\(\\s*'([^']+)'\\s*,",
|
||||||
|
Pattern.CASE_INSENSITIVE);
|
||||||
|
|
||||||
|
private final CygnusDbExecutor dbExecutor;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public CommonService(CygnusDbExecutor dbExecutor) {
|
||||||
|
this.dbExecutor = Objects.requireNonNull(dbExecutor, "dbExecutor");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Used by the session-only unit tests. Production construction is handled
|
||||||
|
by Spring through the CygnusDbExecutor constructor above. */
|
||||||
|
public CommonService() {
|
||||||
|
this.dbExecutor = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Session getSession(HttpSession httpSession) {
|
||||||
|
if (httpSession == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Object value = httpSession.getAttribute(SESSION_ATTRIBUTE);
|
||||||
|
return value instanceof Session session ? session : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void storeSession(HttpSession httpSession, Session session) {
|
||||||
|
Objects.requireNonNull(httpSession, "httpSession");
|
||||||
|
httpSession.setAttribute(SESSION_ATTRIBUTE, Objects.requireNonNull(session, "session"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasPageAccess(HttpSession httpSession, String pageRoute) {
|
||||||
|
return hasPageAccess(getSession(httpSession), pageRoute);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasPageAccess(Session session, String pageRoute) {
|
||||||
|
if (session == null || session.getMenuHtml() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String requiredRoute = normalizeRoute(pageRoute);
|
||||||
|
if (requiredRoute.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Matcher matcher = MENU_COMMAND.matcher(session.getMenuHtml());
|
||||||
|
while (matcher.find()) {
|
||||||
|
if (normalizeRoute(matcher.group(1)).equals(requiredRoute)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String normalizeRoute(String route) {
|
||||||
|
if (route == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
String normalized = route.trim().replace('\\', '/');
|
||||||
|
int query = normalized.indexOf('?');
|
||||||
|
if (query >= 0) {
|
||||||
|
normalized = normalized.substring(0, query);
|
||||||
|
}
|
||||||
|
int fragment = normalized.indexOf('#');
|
||||||
|
if (fragment >= 0) {
|
||||||
|
normalized = normalized.substring(0, fragment);
|
||||||
|
}
|
||||||
|
while (normalized.endsWith("/")) {
|
||||||
|
normalized = normalized.substring(0, normalized.length() - 1);
|
||||||
|
}
|
||||||
|
int slash = normalized.lastIndexOf('/');
|
||||||
|
return slash >= 0 ? normalized.substring(slash + 1) : normalized;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Option> getOptions(Integer queryId, Object[] queryParams) {
|
||||||
|
if (queryId == null) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
if (dbExecutor == null) {
|
||||||
|
throw new IllegalStateException("CygnusDbExecutor is not configured");
|
||||||
|
}
|
||||||
|
Object[] parameters = queryParams == null ? new Object[0] : queryParams;
|
||||||
|
return dbExecutor.query(queryId, parameters, Option.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,195 @@
|
|||||||
|
package matrix.services.edp;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import lib.models.CasePunching;
|
||||||
|
import lib.models.ErrorDetails;
|
||||||
|
import lib.models.Option;
|
||||||
|
import lib.constants.ApplicationError;
|
||||||
|
import matrix.nimble.edp.punching.model.PunchingHandler;
|
||||||
|
import matrix.nimble.utilities.CommonFunctions;
|
||||||
|
import matrix.nimble.utilities.GlobalClass;
|
||||||
|
import matrix.services.commons.CommonService;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class PunchingService {
|
||||||
|
|
||||||
|
private static final String PORTFOLIO = "portfolio.";
|
||||||
|
private static final String BRANCH = "branch.";
|
||||||
|
private static final String PRODUCT = "product.";
|
||||||
|
private static final String CITY = "city.";
|
||||||
|
private static final String APPLICATION_TYPE = "applicationType.";
|
||||||
|
private static final String CATEGORY = "category.";
|
||||||
|
|
||||||
|
private final CommonService commonService;
|
||||||
|
|
||||||
|
public PunchingService(CommonService commonService) {
|
||||||
|
this.commonService = commonService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CasePunching init(
|
||||||
|
String branchId,
|
||||||
|
String userId,
|
||||||
|
String verificationCaseId,
|
||||||
|
String documentCaseId) {
|
||||||
|
PunchingHandler punchingHandler = new PunchingHandler();
|
||||||
|
punchingHandler.setErrCode("1001");
|
||||||
|
|
||||||
|
CasePunching casePunching = new CasePunching();
|
||||||
|
Map<String, List<Option>> options = new LinkedHashMap<>();
|
||||||
|
Short databaseBranchId = Short.valueOf(branchId.trim());
|
||||||
|
List<Option> portfolios = commonService.getOptions(
|
||||||
|
3, new Object[] { databaseBranchId, Short.valueOf((short) 1) });
|
||||||
|
|
||||||
|
addOptions(options, PORTFOLIO, portfolios);
|
||||||
|
casePunching.setOptions(Collections.unmodifiableMap(options));
|
||||||
|
casePunching.setVisibleSections(List.of());
|
||||||
|
casePunching.setPortfolioId(-1);
|
||||||
|
casePunching.setFormMode(0);
|
||||||
|
casePunching.setUserId(userId);
|
||||||
|
casePunching.setDynamicFields("");
|
||||||
|
casePunching.setDynamicHtml("");
|
||||||
|
casePunching.setVerificationCaseId(verificationCaseId);
|
||||||
|
casePunching.setDocumentCaseId(documentCaseId);
|
||||||
|
return casePunching;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CasePunching addCase(
|
||||||
|
CasePunching submitted,
|
||||||
|
String branchIds,
|
||||||
|
String userId) {
|
||||||
|
CasePunching result = new CasePunching();
|
||||||
|
result.setPortfolioId(submitted.getPortfolioId());
|
||||||
|
result.setFormMode(1);
|
||||||
|
result.setUserId(userId);
|
||||||
|
result.setVerificationCaseId(submitted.getVerificationCaseId());
|
||||||
|
result.setDocumentCaseId("xxx");
|
||||||
|
|
||||||
|
if (submitted.getPortfolioId() == null || submitted.getPortfolioId() <= 0) {
|
||||||
|
result.setOptions(Collections.emptyMap());
|
||||||
|
result.setVisibleSections(List.of());
|
||||||
|
result.setDynamicFields("");
|
||||||
|
result.setDynamicHtml("");
|
||||||
|
result.setErrorDetails(new ErrorDetails(ApplicationError.BAD_REQUEST));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
String portfolioId = submitted.getPortfolioId().toString();
|
||||||
|
PunchingHandler punchingHandler = new PunchingHandler();
|
||||||
|
CommonFunctions commonFunctions = new CommonFunctions();
|
||||||
|
punchingHandler.setErrCode("1001");
|
||||||
|
punchingHandler.setPortfolioid(portfolioId);
|
||||||
|
punchingHandler.setProcessFlag(true);
|
||||||
|
punchingHandler.DynamicHtml("10");
|
||||||
|
|
||||||
|
if (punchingHandler.isProcessFlag()) {
|
||||||
|
result.setDynamicFields(defaultString(punchingHandler.getDynamicfields()));
|
||||||
|
result.setDynamicHtml(defaultString(punchingHandler.getDynamicpanel()));
|
||||||
|
String sections = defaultString(punchingHandler.GetVisibleSections())
|
||||||
|
+ defaultString(punchingHandler.getDynamicsection());
|
||||||
|
result.setVisibleSections(toVisibleSections(sections));
|
||||||
|
} else {
|
||||||
|
result.setDynamicFields("");
|
||||||
|
result.setDynamicHtml("");
|
||||||
|
result.setVisibleSections(List.of());
|
||||||
|
result.setErrorDetails(new ErrorDetails(ApplicationError.INTERNAL_SERVER_ERROR));
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> options = new LinkedHashMap<>();
|
||||||
|
punchingHandler.GetDDValues(3, branchIds.split(GlobalClass.ColDelim));
|
||||||
|
addOptions(options, PORTFOLIO, punchingHandler.getOptionvals());
|
||||||
|
|
||||||
|
punchingHandler.GetDDValues(4, new String[] { portfolioId });
|
||||||
|
addOptions(options, BRANCH, punchingHandler.getOptionvals());
|
||||||
|
|
||||||
|
punchingHandler.GetDDValues(5,
|
||||||
|
(branchIds + GlobalClass.ColDelim
|
||||||
|
+ "op.description='CITY' or op.description='APPTYPE'"
|
||||||
|
+ GlobalClass.ColDelim).split(GlobalClass.ColDelim));
|
||||||
|
String[][] generalOptions = punchingHandler.getOptionvals();
|
||||||
|
if (generalOptions != null) {
|
||||||
|
addOptions(options, CITY,
|
||||||
|
commonFunctions.GetSubArray("CITY", 2, generalOptions));
|
||||||
|
addOptions(options, APPLICATION_TYPE,
|
||||||
|
commonFunctions.GetSubArray("APPTYPE", 2, generalOptions));
|
||||||
|
}
|
||||||
|
|
||||||
|
punchingHandler.GetDDValues(70,
|
||||||
|
(portfolioId + GlobalClass.ColDelim
|
||||||
|
+ "op.description='CATEGORY' or op.description='PRODUCT'"
|
||||||
|
+ GlobalClass.ColDelim).split(GlobalClass.ColDelim));
|
||||||
|
String[][] portfolioOptions = punchingHandler.getOptionvals();
|
||||||
|
if (portfolioOptions != null) {
|
||||||
|
addOptions(options, PRODUCT,
|
||||||
|
commonFunctions.GetSubArray("PRODUCT", 2, portfolioOptions));
|
||||||
|
addOptions(options, CATEGORY,
|
||||||
|
commonFunctions.GetSubArray("CATEGORY", 2, portfolioOptions));
|
||||||
|
}
|
||||||
|
result.setOptionsl(Collections.unmodifiableMap(options));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CasePunching editCase(
|
||||||
|
Integer portfolioId,
|
||||||
|
String documentCaseId,
|
||||||
|
String branchIds,
|
||||||
|
String userId) {
|
||||||
|
CasePunching submitted = new CasePunching();
|
||||||
|
submitted.setPortfolioId(portfolioId);
|
||||||
|
submitted.setDocumentCaseId(documentCaseId);
|
||||||
|
CasePunching result = addCase(submitted, branchIds, userId);
|
||||||
|
result.setFormMode(2);
|
||||||
|
result.setDocumentCaseId(documentCaseId);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addOptions(Map<String, String> options, String prefix, String[][] values) {
|
||||||
|
if (values == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (String[] value : values) {
|
||||||
|
if (value != null && value.length >= 2 && value[0] != null) {
|
||||||
|
options.put(prefix + value[0], value[1] == null ? "" : value[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addOptions(Map<String, List<Option>> options, String prefix, List<Option> values) {
|
||||||
|
if (values == null || values.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Option> groupOptions = options.get(prefix);
|
||||||
|
for (Option value : values) {
|
||||||
|
if (value == null || value.getValue() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (groupOptions == null) {
|
||||||
|
groupOptions = new java.util.ArrayList<>(values.size());
|
||||||
|
options.put(prefix, groupOptions);
|
||||||
|
}
|
||||||
|
groupOptions.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> toVisibleSections(String sections) {
|
||||||
|
if (sections == null || sections.isBlank()) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
return List.of(sections.split(Pattern.quote(GlobalClass.ColDelim))).stream()
|
||||||
|
.map(String::trim)
|
||||||
|
.filter(section -> !section.isEmpty() && !"null".equalsIgnoreCase(section))
|
||||||
|
.distinct()
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String defaultString(String value) {
|
||||||
|
return value == null ? "" : value;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package matrix.nimble.controller;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import matrix.nimble.model.Session;
|
||||||
|
import matrix.services.commons.CommonErrorService;
|
||||||
|
import matrix.services.commons.CommonService;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
|
import org.springframework.mock.web.MockHttpSession;
|
||||||
|
import org.springframework.ui.ModelMap;
|
||||||
|
|
||||||
|
class AbstractAuthenticatedControllerTest {
|
||||||
|
private final CommonService commonService = new CommonService();
|
||||||
|
private final TestController controller = new TestController(
|
||||||
|
commonService, new CommonErrorService(commonService));
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void grantsAConfiguredMenuRoute() {
|
||||||
|
MockHttpSession httpSession = new MockHttpSession();
|
||||||
|
Session session = sessionWithRoute("initview");
|
||||||
|
commonService.storeSession(httpSession, session);
|
||||||
|
|
||||||
|
AbstractAuthenticatedController.PageAuthorization result = controller.authorize(
|
||||||
|
"initview", new ModelMap(), httpSession, new MockHttpServletResponse());
|
||||||
|
|
||||||
|
assertTrue(result.isGranted());
|
||||||
|
assertSame(session, result.session());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void returns401ForMissingSessionAnd403ForMissingPage() {
|
||||||
|
MockHttpServletResponse noSessionResponse = new MockHttpServletResponse();
|
||||||
|
AbstractAuthenticatedController.PageAuthorization noSession = controller.authorize(
|
||||||
|
"initview", new ModelMap(), new MockHttpSession(), noSessionResponse);
|
||||||
|
assertEquals("error", noSession.viewName());
|
||||||
|
assertEquals(401, noSessionResponse.getStatus());
|
||||||
|
|
||||||
|
MockHttpSession httpSession = new MockHttpSession();
|
||||||
|
commonService.storeSession(httpSession, sessionWithRoute("dashboard"));
|
||||||
|
MockHttpServletResponse deniedResponse = new MockHttpServletResponse();
|
||||||
|
AbstractAuthenticatedController.PageAuthorization denied = controller.authorize(
|
||||||
|
"initview", new ModelMap(), httpSession, deniedResponse);
|
||||||
|
assertEquals("error", denied.viewName());
|
||||||
|
assertEquals(403, deniedResponse.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Session sessionWithRoute(String route) {
|
||||||
|
Session session = new Session();
|
||||||
|
session.setMenuHtml("<a onclick=\"SubmitMenuCommand('" + route
|
||||||
|
+ "','_parent','MenuForm','')\">Page</a>");
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class TestController extends AbstractAuthenticatedController {
|
||||||
|
private TestController(CommonService commonService, CommonErrorService errorService) {
|
||||||
|
super(commonService, errorService);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PageAuthorization authorize(
|
||||||
|
String route,
|
||||||
|
ModelMap model,
|
||||||
|
MockHttpSession session,
|
||||||
|
MockHttpServletResponse response) {
|
||||||
|
return authorizePage(route, model, session, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package matrix.nimble.query;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
import com.cygnus.db.QueryDefinitionException;
|
||||||
|
import com.cygnus.db.QueryType;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class CloudQueryDefinitionProviderTest {
|
||||||
|
@Test
|
||||||
|
void adaptsEncryptedCloudQueryProviderValueToDbDefinition() {
|
||||||
|
CloudQueryDefinitionProvider provider = new CloudQueryDefinitionProvider(
|
||||||
|
queryId -> "select!C0L!select operation_id from operation where type = ?");
|
||||||
|
|
||||||
|
var definition = provider.get(513);
|
||||||
|
assertEquals(513, definition.queryId());
|
||||||
|
assertEquals(QueryType.SELECT, definition.type());
|
||||||
|
assertEquals("select operation_id from operation where type = ?", definition.sql());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void preventsLegacyPlaceholderExecution() {
|
||||||
|
CloudQueryDefinitionProvider provider = new CloudQueryDefinitionProvider(
|
||||||
|
queryId -> "select!C0L!select * from operation where type = 'val0'");
|
||||||
|
assertThrows(QueryDefinitionException.class, () -> provider.get(513));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package matrix.services.commons;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||||
|
|
||||||
|
import lib.models.ErrorDetails;
|
||||||
|
import lib.constants.ApplicationError;
|
||||||
|
import matrix.nimble.model.Session;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
|
import org.springframework.mock.web.MockHttpSession;
|
||||||
|
import org.springframework.ui.ModelMap;
|
||||||
|
|
||||||
|
class CommonErrorServiceTest {
|
||||||
|
private final CommonService commonService = new CommonService();
|
||||||
|
private final CommonErrorService errorService = new CommonErrorService(commonService);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void appliesHttpStatusAndPreservesAnActiveSessionForTheMenu() {
|
||||||
|
MockHttpSession httpSession = new MockHttpSession();
|
||||||
|
Session session = new Session();
|
||||||
|
session.setMenuHtml("<div id='MenuBar'></div>");
|
||||||
|
commonService.storeSession(httpSession, session);
|
||||||
|
ErrorDetails details = new ErrorDetails(ApplicationError.ACCESS_DENIED);
|
||||||
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
|
ModelMap model = new ModelMap();
|
||||||
|
|
||||||
|
String view = errorService.render(model, response, httpSession, details);
|
||||||
|
|
||||||
|
assertEquals("error", view);
|
||||||
|
assertEquals(403, response.getStatus());
|
||||||
|
assertSame(details, model.get(CommonErrorService.ERROR_ATTRIBUTE));
|
||||||
|
assertSame(session, model.get(CommonService.SESSION_ATTRIBUTE));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package matrix.services.commons;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import matrix.nimble.model.Session;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.mock.web.MockHttpSession;
|
||||||
|
|
||||||
|
class CommonServiceTest {
|
||||||
|
private final CommonService service = new CommonService();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void storesAndReadsTheAuthenticatedSession() {
|
||||||
|
MockHttpSession httpSession = new MockHttpSession();
|
||||||
|
Session session = sessionWithMenu("initview");
|
||||||
|
|
||||||
|
service.storeSession(httpSession, session);
|
||||||
|
|
||||||
|
assertSame(session, service.getSession(httpSession));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void grantsOnlyAnExactMenuCommandRoute() {
|
||||||
|
Session session = sessionWithMenu("/matrix/ver/initview?source=menu");
|
||||||
|
|
||||||
|
assertTrue(service.hasPageAccess(session, "initview"));
|
||||||
|
assertFalse(service.hasPageAccess(session, "view"));
|
||||||
|
assertFalse(service.hasPageAccess(session, "initview-admin"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void deniesMissingSessionAndMissingMenu() {
|
||||||
|
assertFalse(service.hasPageAccess((Session) null, "initview"));
|
||||||
|
assertFalse(service.hasPageAccess(new Session(), "initview"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Session sessionWithMenu(String route) {
|
||||||
|
Session session = new Session();
|
||||||
|
session.setMenuHtml("<a onclick=\"SubmitMenuCommand('" + route
|
||||||
|
+ "','_parent','MenuForm','')\">Punching</a>");
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
}
|
||||||
39
cygnus-onprem-db/README.md
Normal file
39
cygnus-onprem-db/README.md
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# Cygnus On-Premises Database Core
|
||||||
|
|
||||||
|
This module executes cloud-supplied, parameterized query definitions against the
|
||||||
|
on-premises JDBC `DataSource` without creating delimiter strings or `String[][]`
|
||||||
|
result buffers.
|
||||||
|
|
||||||
|
## Query format
|
||||||
|
|
||||||
|
The query catalog value retains the operation prefix during incremental migration:
|
||||||
|
|
||||||
|
```text
|
||||||
|
select!C0L!select id, name from operation where operation_type = ? and operated_by = ?
|
||||||
|
```
|
||||||
|
|
||||||
|
Legacy `val0`, `val1`, ... placeholders are rejected by the modern executor. They
|
||||||
|
remain available through the existing `DBFunctions.FetchRunQuery` path until each
|
||||||
|
query is migrated.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```java
|
||||||
|
List<Operation> rows = dbFunctions.query(
|
||||||
|
600,
|
||||||
|
new Object[] { operationType, operatedBy },
|
||||||
|
Operation.class);
|
||||||
|
```
|
||||||
|
|
||||||
|
For maximum throughput, use an explicit mapper:
|
||||||
|
|
||||||
|
```java
|
||||||
|
List<Operation> rows = dbFunctions.query(
|
||||||
|
600,
|
||||||
|
parameters,
|
||||||
|
result -> new Operation(result.getLong("id"), result.getString("name")));
|
||||||
|
```
|
||||||
|
|
||||||
|
Large reports can use `stream(...)` so rows are consumed without retaining the
|
||||||
|
whole result in memory. PostgreSQL cursor fetching is enabled by running reads with
|
||||||
|
auto-commit disabled and the configured fetch size.
|
||||||
38
cygnus-onprem-db/pom.xml
Normal file
38
cygnus-onprem-db/pom.xml
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.cygnus</groupId>
|
||||||
|
<artifactId>cygnus-parent</artifactId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<artifactId>cygnus-onprem-db</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<name>Cygnus On-Premises Database Core</name>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter</artifactId>
|
||||||
|
<version>${junit.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.h2database</groupId>
|
||||||
|
<artifactId>h2</artifactId>
|
||||||
|
<version>2.3.232</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>3.5.4</version>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.cygnus.db;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public interface CygnusDbExecutor {
|
||||||
|
<T> DbResult<T> execute(int queryId, Object[] parameters, Class<T> responseType);
|
||||||
|
DbResult<RowView> execute(int queryId, Object[] parameters);
|
||||||
|
<T> List<T> query(int queryId, Object[] parameters, Class<T> responseType);
|
||||||
|
<T> List<T> query(int queryId, Object[] parameters, RowMapper<T> mapper);
|
||||||
|
List<RowView> query(int queryId, Object[] parameters);
|
||||||
|
<T> Optional<T> queryOne(int queryId, Object[] parameters, Class<T> responseType);
|
||||||
|
int insert(int queryId, Object[] parameters);
|
||||||
|
<K> K insert(int queryId, Object[] parameters, Class<K> generatedKeyType);
|
||||||
|
int update(int queryId, Object[] parameters);
|
||||||
|
int delete(int queryId, Object[] parameters);
|
||||||
|
<T> T procedure(int queryId, Object[] parameters, Class<T> responseType);
|
||||||
|
<T> List<T> procedureRows(int queryId, Object[] parameters, Class<T> responseType);
|
||||||
|
<T> void stream(int queryId, Object[] parameters, RowMapper<T> mapper, RowConsumer<T> consumer);
|
||||||
|
<T> T transaction(TransactionCallback<T> callback);
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.cygnus.db;
|
||||||
|
|
||||||
|
public final class DatabaseExecutionException extends RuntimeException {
|
||||||
|
private final int queryId;
|
||||||
|
|
||||||
|
public DatabaseExecutionException(int queryId, String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
this.queryId = queryId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int queryId() { return queryId; }
|
||||||
|
}
|
||||||
20
cygnus-onprem-db/src/main/java/com/cygnus/db/DbResult.java
Normal file
20
cygnus-onprem-db/src/main/java/com/cygnus/db/DbResult.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package com.cygnus.db;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public record DbResult<T>(QueryType type, List<T> rows, int affectedRows, T value) {
|
||||||
|
public DbResult {
|
||||||
|
rows = rows == null ? List.of() : List.copyOf(rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<T> optionalValue() { return Optional.ofNullable(value); }
|
||||||
|
|
||||||
|
public static <T> DbResult<T> rows(QueryType type, List<T> rows) {
|
||||||
|
return new DbResult<>(type, rows, 0, rows.isEmpty() ? null : rows.getFirst());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> DbResult<T> affected(QueryType type, int count) {
|
||||||
|
return new DbResult<>(type, List.of(), count, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.cygnus.db;
|
||||||
|
|
||||||
|
public record ExecutorOptions(int fetchSize, int queryTimeoutSeconds) {
|
||||||
|
public static final ExecutorOptions DEFAULT = new ExecutorOptions(250, 60);
|
||||||
|
|
||||||
|
public ExecutorOptions {
|
||||||
|
if (fetchSize < 0) throw new IllegalArgumentException("fetchSize cannot be negative");
|
||||||
|
if (queryTimeoutSeconds < 0) throw new IllegalArgumentException("queryTimeoutSeconds cannot be negative");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package com.cygnus.db;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
final class ImmutableRowView implements RowView {
|
||||||
|
private final Map<String, Object> values;
|
||||||
|
private final Map<String, Object> normalized;
|
||||||
|
|
||||||
|
ImmutableRowView(Map<String, Object> values) {
|
||||||
|
this.values = Collections.unmodifiableMap(new LinkedHashMap<>(values));
|
||||||
|
Map<String, Object> index = new LinkedHashMap<>();
|
||||||
|
values.forEach((name, value) -> index.put(name.toLowerCase(Locale.ROOT), value));
|
||||||
|
this.normalized = Map.copyOf(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object get(String column) {
|
||||||
|
Object value = values.get(column);
|
||||||
|
return value != null || values.containsKey(column)
|
||||||
|
? value : normalized.get(column.toLowerCase(Locale.ROOT));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T get(String column, Class<T> type) {
|
||||||
|
return ValueConverter.convert(get(column), type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> asMap() { return values; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,316 @@
|
|||||||
|
package com.cygnus.db;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
public final class JdbcCygnusDbExecutor implements CygnusDbExecutor {
|
||||||
|
private final DataSource dataSource;
|
||||||
|
private final QueryDefinitionProvider queryProvider;
|
||||||
|
private final ExecutorOptions options;
|
||||||
|
private final ParameterBinder binder = new ParameterBinder();
|
||||||
|
private final ObjectRowMapperFactory mapperFactory = new ObjectRowMapperFactory();
|
||||||
|
|
||||||
|
public JdbcCygnusDbExecutor(DataSource dataSource, QueryDefinitionProvider queryProvider) {
|
||||||
|
this(dataSource, queryProvider, ExecutorOptions.DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JdbcCygnusDbExecutor(
|
||||||
|
DataSource dataSource, QueryDefinitionProvider queryProvider, ExecutorOptions options) {
|
||||||
|
this.dataSource = java.util.Objects.requireNonNull(dataSource, "dataSource");
|
||||||
|
this.queryProvider = java.util.Objects.requireNonNull(queryProvider, "queryProvider");
|
||||||
|
this.options = java.util.Objects.requireNonNull(options, "options");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> DbResult<T> execute(int queryId, Object[] parameters, Class<T> responseType) {
|
||||||
|
QueryDefinition definition = queryProvider.get(queryId);
|
||||||
|
if (definition.type() == QueryType.SELECT) {
|
||||||
|
return withReadConnection(queryId, connection ->
|
||||||
|
executeRowsOrCount(connection, definition, parameters, responseType));
|
||||||
|
}
|
||||||
|
if (definition.type() == QueryType.PROCEDURE) {
|
||||||
|
return executeRowsOrCount(definition, parameters, responseType);
|
||||||
|
}
|
||||||
|
return DbResult.affected(definition.type(), executeUpdate(definition, parameters));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DbResult<RowView> execute(int queryId, Object[] parameters) {
|
||||||
|
return execute(queryId, parameters, RowView.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> List<T> query(int queryId, Object[] parameters, Class<T> responseType) {
|
||||||
|
return withReadConnection(queryId, connection -> query(
|
||||||
|
connection, require(queryId, QueryType.SELECT), parameters, responseType));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> List<T> query(int queryId, Object[] parameters, RowMapper<T> mapper) {
|
||||||
|
return withReadConnection(queryId, connection -> query(
|
||||||
|
connection, require(queryId, QueryType.SELECT), parameters, mapper));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<RowView> query(int queryId, Object[] parameters) {
|
||||||
|
return query(queryId, parameters, RowView.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> Optional<T> queryOne(int queryId, Object[] parameters, Class<T> responseType) {
|
||||||
|
List<T> rows = query(queryId, parameters, responseType);
|
||||||
|
if (rows.size() > 1) throw new DatabaseExecutionException(
|
||||||
|
queryId, "Expected one row but received " + rows.size(), null);
|
||||||
|
return rows.stream().findFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int insert(int queryId, Object[] parameters) {
|
||||||
|
return executeUpdate(require(queryId, QueryType.INSERT), parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <K> K insert(int queryId, Object[] parameters, Class<K> generatedKeyType) {
|
||||||
|
QueryDefinition definition = require(queryId, QueryType.INSERT);
|
||||||
|
return withConnection(queryId, connection -> {
|
||||||
|
try (PreparedStatement statement = prepare(
|
||||||
|
connection, definition, Statement.RETURN_GENERATED_KEYS)) {
|
||||||
|
binder.bind(statement, parameters);
|
||||||
|
statement.executeUpdate();
|
||||||
|
try (ResultSet keys = statement.getGeneratedKeys()) {
|
||||||
|
if (!keys.next()) throw new DatabaseExecutionException(
|
||||||
|
queryId, "Insert did not return a generated key", null);
|
||||||
|
return ValueConverter.convert(keys.getObject(1), generatedKeyType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int update(int queryId, Object[] parameters) {
|
||||||
|
return executeUpdate(require(queryId, QueryType.UPDATE), parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int delete(int queryId, Object[] parameters) {
|
||||||
|
return executeUpdate(require(queryId, QueryType.DELETE), parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T procedure(int queryId, Object[] parameters, Class<T> responseType) {
|
||||||
|
List<T> rows = procedureRows(queryId, parameters, responseType);
|
||||||
|
return rows.isEmpty() ? null : rows.getFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> List<T> procedureRows(int queryId, Object[] parameters, Class<T> responseType) {
|
||||||
|
DbResult<T> result = executeRowsOrCount(
|
||||||
|
require(queryId, QueryType.PROCEDURE), parameters, responseType);
|
||||||
|
return result.rows();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> void stream(
|
||||||
|
int queryId, Object[] parameters, RowMapper<T> mapper, RowConsumer<T> consumer) {
|
||||||
|
QueryDefinition definition = require(queryId, QueryType.SELECT);
|
||||||
|
withReadConnection(queryId, connection -> {
|
||||||
|
try (PreparedStatement statement = prepare(connection, definition);
|
||||||
|
ResultSet result = executeQuery(statement, parameters)) {
|
||||||
|
while (result.next()) consumer.accept(mapper.map(result));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T transaction(TransactionCallback<T> callback) {
|
||||||
|
try (Connection connection = dataSource.getConnection()) {
|
||||||
|
boolean autoCommit = connection.getAutoCommit();
|
||||||
|
connection.setAutoCommit(false);
|
||||||
|
try {
|
||||||
|
T result = callback.execute(new TransactionOperationsImpl(connection));
|
||||||
|
connection.commit();
|
||||||
|
return result;
|
||||||
|
} catch (Exception exception) {
|
||||||
|
try { connection.rollback(); } catch (SQLException rollback) { exception.addSuppressed(rollback); }
|
||||||
|
if (exception instanceof RuntimeException runtime) throw runtime;
|
||||||
|
throw new DatabaseExecutionException(0, "Transaction failed", exception);
|
||||||
|
} finally {
|
||||||
|
connection.setAutoCommit(autoCommit);
|
||||||
|
}
|
||||||
|
} catch (SQLException exception) {
|
||||||
|
throw new DatabaseExecutionException(0, "Unable to manage transaction", exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> DbResult<T> executeRowsOrCount(
|
||||||
|
QueryDefinition definition, Object[] parameters, Class<T> responseType) {
|
||||||
|
return withConnection(definition.queryId(), connection ->
|
||||||
|
executeRowsOrCount(connection, definition, parameters, responseType));
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> DbResult<T> executeRowsOrCount(
|
||||||
|
Connection connection,
|
||||||
|
QueryDefinition definition,
|
||||||
|
Object[] parameters,
|
||||||
|
Class<T> responseType) throws SQLException {
|
||||||
|
try (PreparedStatement statement = prepare(connection, definition)) {
|
||||||
|
binder.bind(statement, parameters);
|
||||||
|
boolean rows = statement.execute();
|
||||||
|
if (!rows) return DbResult.affected(definition.type(), statement.getUpdateCount());
|
||||||
|
try (ResultSet result = statement.getResultSet()) {
|
||||||
|
return DbResult.rows(definition.type(), map(result, responseType));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int executeUpdate(QueryDefinition definition, Object[] parameters) {
|
||||||
|
return withConnection(definition.queryId(), connection ->
|
||||||
|
executeUpdate(connection, definition, parameters));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int executeUpdate(
|
||||||
|
Connection connection, QueryDefinition definition, Object[] parameters) throws SQLException {
|
||||||
|
try (PreparedStatement statement = prepare(connection, definition)) {
|
||||||
|
binder.bind(statement, parameters);
|
||||||
|
return statement.executeUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> List<T> query(
|
||||||
|
Connection connection,
|
||||||
|
QueryDefinition definition,
|
||||||
|
Object[] parameters,
|
||||||
|
Class<T> responseType) throws SQLException {
|
||||||
|
try (PreparedStatement statement = prepare(connection, definition);
|
||||||
|
ResultSet result = executeQuery(statement, parameters)) {
|
||||||
|
return map(result, responseType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> List<T> query(
|
||||||
|
Connection connection,
|
||||||
|
QueryDefinition definition,
|
||||||
|
Object[] parameters,
|
||||||
|
RowMapper<T> mapper) throws SQLException {
|
||||||
|
try (PreparedStatement statement = prepare(connection, definition);
|
||||||
|
ResultSet result = executeQuery(statement, parameters)) {
|
||||||
|
List<T> rows = new ArrayList<>();
|
||||||
|
while (result.next()) rows.add(mapper.map(result));
|
||||||
|
return List.copyOf(rows);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> List<T> map(ResultSet result, Class<T> responseType) throws SQLException {
|
||||||
|
RowMapper<T> mapper = mapperFactory.create(responseType, result.getMetaData());
|
||||||
|
List<T> rows = new ArrayList<>();
|
||||||
|
while (result.next()) rows.add(mapper.map(result));
|
||||||
|
return List.copyOf(rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResultSet executeQuery(PreparedStatement statement, Object[] parameters) throws SQLException {
|
||||||
|
binder.bind(statement, parameters);
|
||||||
|
return statement.executeQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
private PreparedStatement prepare(Connection connection, QueryDefinition definition) throws SQLException {
|
||||||
|
PreparedStatement statement = connection.prepareStatement(
|
||||||
|
definition.sql(), ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
|
||||||
|
configure(statement);
|
||||||
|
return statement;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PreparedStatement prepare(
|
||||||
|
Connection connection, QueryDefinition definition, int generatedKeys) throws SQLException {
|
||||||
|
PreparedStatement statement = connection.prepareStatement(definition.sql(), generatedKeys);
|
||||||
|
configure(statement);
|
||||||
|
return statement;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configure(PreparedStatement statement) throws SQLException {
|
||||||
|
statement.setFetchSize(options.fetchSize());
|
||||||
|
statement.setQueryTimeout(options.queryTimeoutSeconds());
|
||||||
|
}
|
||||||
|
|
||||||
|
private QueryDefinition require(int queryId, QueryType expected) {
|
||||||
|
QueryDefinition definition = queryProvider.get(queryId);
|
||||||
|
if (definition.type() != expected) throw new QueryDefinitionException(
|
||||||
|
"Query " + queryId + " is " + definition.type() + ", not " + expected);
|
||||||
|
return definition;
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T withConnection(int queryId, SqlWork<T> work) {
|
||||||
|
try (Connection connection = dataSource.getConnection()) {
|
||||||
|
return work.execute(connection);
|
||||||
|
} catch (DatabaseExecutionException exception) {
|
||||||
|
throw exception;
|
||||||
|
} catch (Exception exception) {
|
||||||
|
throw new DatabaseExecutionException(queryId, "Database operation failed for query " + queryId, exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T withReadConnection(int queryId, SqlWork<T> work) {
|
||||||
|
try (Connection connection = dataSource.getConnection()) {
|
||||||
|
boolean autoCommit = connection.getAutoCommit();
|
||||||
|
connection.setAutoCommit(false); // PostgreSQL requires this for cursor-based fetchSize.
|
||||||
|
try {
|
||||||
|
T value = work.execute(connection);
|
||||||
|
connection.commit();
|
||||||
|
return value;
|
||||||
|
} catch (Exception exception) {
|
||||||
|
try { connection.rollback(); } catch (SQLException rollback) { exception.addSuppressed(rollback); }
|
||||||
|
if (exception instanceof RuntimeException runtime) throw runtime;
|
||||||
|
throw new DatabaseExecutionException(queryId,
|
||||||
|
"Database read failed for query " + queryId, exception);
|
||||||
|
} finally {
|
||||||
|
connection.setAutoCommit(autoCommit);
|
||||||
|
}
|
||||||
|
} catch (SQLException exception) {
|
||||||
|
throw new DatabaseExecutionException(queryId,
|
||||||
|
"Unable to manage database read for query " + queryId, exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
private interface SqlWork<T> { T execute(Connection connection) throws Exception; }
|
||||||
|
|
||||||
|
private final class TransactionOperationsImpl implements TransactionOperations {
|
||||||
|
private final Connection connection;
|
||||||
|
private TransactionOperationsImpl(Connection connection) { this.connection = connection; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> List<T> query(int queryId, Object[] parameters, Class<T> type) {
|
||||||
|
try { return JdbcCygnusDbExecutor.this.query(
|
||||||
|
connection, require(queryId, QueryType.SELECT), parameters, type); }
|
||||||
|
catch (SQLException exception) { throw failure(queryId, exception); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> Optional<T> queryOne(int queryId, Object[] parameters, Class<T> type) {
|
||||||
|
List<T> rows = query(queryId, parameters, type);
|
||||||
|
if (rows.size() > 1) throw new DatabaseExecutionException(
|
||||||
|
queryId, "Expected one row but received " + rows.size(), null);
|
||||||
|
return rows.stream().findFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public int insert(int id, Object[] values) { return updateType(id, values, QueryType.INSERT); }
|
||||||
|
@Override public int update(int id, Object[] values) { return updateType(id, values, QueryType.UPDATE); }
|
||||||
|
@Override public int delete(int id, Object[] values) { return updateType(id, values, QueryType.DELETE); }
|
||||||
|
|
||||||
|
private int updateType(int id, Object[] values, QueryType type) {
|
||||||
|
try { return executeUpdate(connection, require(id, type), values); }
|
||||||
|
catch (SQLException exception) { throw failure(id, exception); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private DatabaseExecutionException failure(int id, SQLException exception) {
|
||||||
|
return new DatabaseExecutionException(id, "Transaction operation failed for query " + id, exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
package com.cygnus.db;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.RecordComponent;
|
||||||
|
import java.sql.ResultSetMetaData;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
|
final class ObjectRowMapperFactory {
|
||||||
|
private final ConcurrentMap<Class<?>, TypeMetadata> metadataCache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
<T> RowMapper<T> create(Class<T> type, ResultSetMetaData resultMetadata) throws SQLException {
|
||||||
|
if (type == RowView.class) return result -> type.cast(rowView(result, resultMetadata));
|
||||||
|
if (isScalar(type)) return result -> ValueConverter.convert(result.getObject(1), type);
|
||||||
|
TypeMetadata typeMetadata = metadataCache.computeIfAbsent(type, this::inspect);
|
||||||
|
Map<String, Integer> columns = columns(resultMetadata);
|
||||||
|
return typeMetadata.mapper(type, columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RowView rowView(java.sql.ResultSet result, ResultSetMetaData metadata) throws SQLException {
|
||||||
|
Map<String, Object> values = new LinkedHashMap<>();
|
||||||
|
for (int column = 1; column <= metadata.getColumnCount(); column++) {
|
||||||
|
values.put(metadata.getColumnLabel(column), result.getObject(column));
|
||||||
|
}
|
||||||
|
return new ImmutableRowView(values);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TypeMetadata inspect(Class<?> type) {
|
||||||
|
try {
|
||||||
|
if (type.isRecord()) {
|
||||||
|
RecordComponent[] components = type.getRecordComponents();
|
||||||
|
Class<?>[] parameterTypes = new Class<?>[components.length];
|
||||||
|
String[] names = new String[components.length];
|
||||||
|
for (int index = 0; index < components.length; index++) {
|
||||||
|
parameterTypes[index] = components[index].getType();
|
||||||
|
names[index] = normalize(components[index].getName());
|
||||||
|
}
|
||||||
|
Constructor<?> constructor = type.getDeclaredConstructor(parameterTypes);
|
||||||
|
constructor.setAccessible(true);
|
||||||
|
return new RecordMetadata(constructor, parameterTypes, names);
|
||||||
|
}
|
||||||
|
Constructor<?> constructor = type.getDeclaredConstructor();
|
||||||
|
constructor.setAccessible(true);
|
||||||
|
List<Field> fields = new ArrayList<>();
|
||||||
|
for (Class<?> current = type; current != null && current != Object.class;
|
||||||
|
current = current.getSuperclass()) {
|
||||||
|
for (Field field : current.getDeclaredFields()) {
|
||||||
|
if (!java.lang.reflect.Modifier.isStatic(field.getModifiers())) {
|
||||||
|
field.setAccessible(true);
|
||||||
|
fields.add(field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new BeanMetadata(constructor, List.copyOf(fields));
|
||||||
|
} catch (ReflectiveOperationException exception) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Response type must be a record or have a no-argument constructor: " + type.getName(), exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Integer> columns(ResultSetMetaData metadata) throws SQLException {
|
||||||
|
Map<String, Integer> result = new LinkedHashMap<>();
|
||||||
|
for (int column = 1; column <= metadata.getColumnCount(); column++) {
|
||||||
|
result.putIfAbsent(normalize(metadata.getColumnLabel(column)), column);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String normalize(String value) {
|
||||||
|
return value.replace("_", "").toLowerCase(Locale.ROOT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isScalar(Class<?> type) {
|
||||||
|
return type.isPrimitive() || type.isEnum()
|
||||||
|
|| Number.class.isAssignableFrom(type)
|
||||||
|
|| type == String.class || type == Boolean.class || type == Character.class
|
||||||
|
|| type == java.util.UUID.class
|
||||||
|
|| type.getPackageName().equals("java.time");
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed interface TypeMetadata permits RecordMetadata, BeanMetadata {
|
||||||
|
<T> RowMapper<T> mapper(Class<T> type, Map<String, Integer> columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
private record RecordMetadata(
|
||||||
|
Constructor<?> constructor, Class<?>[] parameterTypes, String[] names) implements TypeMetadata {
|
||||||
|
@Override
|
||||||
|
public <T> RowMapper<T> mapper(Class<T> type, Map<String, Integer> columns) {
|
||||||
|
int[] indexes = new int[names.length];
|
||||||
|
for (int index = 0; index < names.length; index++) {
|
||||||
|
Integer column = columns.get(names[index]);
|
||||||
|
if (column == null) throw new IllegalArgumentException(
|
||||||
|
"Result does not contain record component: " + names[index]);
|
||||||
|
indexes[index] = column;
|
||||||
|
}
|
||||||
|
return result -> {
|
||||||
|
try {
|
||||||
|
Object[] values = new Object[indexes.length];
|
||||||
|
for (int index = 0; index < indexes.length; index++) {
|
||||||
|
values[index] = ValueConverter.convert(
|
||||||
|
result.getObject(indexes[index]), parameterTypes[index]);
|
||||||
|
}
|
||||||
|
return type.cast(constructor.newInstance(values));
|
||||||
|
} catch (ReflectiveOperationException exception) {
|
||||||
|
throw new DatabaseExecutionException(0, "Unable to map record " + type.getName(), exception);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private record BeanMetadata(Constructor<?> constructor, List<Field> fields) implements TypeMetadata {
|
||||||
|
@Override
|
||||||
|
public <T> RowMapper<T> mapper(Class<T> type, Map<String, Integer> columns) {
|
||||||
|
List<FieldBinding> bindings = fields.stream()
|
||||||
|
.map(field -> new FieldBinding(field, columns.get(normalize(field.getName()))))
|
||||||
|
.filter(binding -> binding.column() != null)
|
||||||
|
.toList();
|
||||||
|
return result -> {
|
||||||
|
try {
|
||||||
|
T instance = type.cast(constructor.newInstance());
|
||||||
|
for (FieldBinding binding : bindings) {
|
||||||
|
binding.field().set(instance, ValueConverter.convert(
|
||||||
|
result.getObject(binding.column()), binding.field().getType()));
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
} catch (ReflectiveOperationException exception) {
|
||||||
|
throw new DatabaseExecutionException(0, "Unable to map bean " + type.getName(), exception);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private record FieldBinding(Field field, Integer column) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.cygnus.db;
|
||||||
|
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
final class ParameterBinder {
|
||||||
|
void bind(PreparedStatement statement, Object[] parameters) throws SQLException {
|
||||||
|
Object[] values = parameters == null ? new Object[0] : parameters;
|
||||||
|
for (int index = 0; index < values.length; index++) {
|
||||||
|
bind(statement, index + 1, values[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bind(PreparedStatement statement, int index, Object value) throws SQLException {
|
||||||
|
if (value instanceof SqlParameter parameter) {
|
||||||
|
if (parameter.value() == null) statement.setNull(index, parameter.sqlType());
|
||||||
|
else statement.setObject(index, parameter.value(), parameter.sqlType());
|
||||||
|
} else if (value == null) {
|
||||||
|
statement.setObject(index, null);
|
||||||
|
} else if (value instanceof Instant instant) {
|
||||||
|
statement.setTimestamp(index, Timestamp.from(instant));
|
||||||
|
} else if (value instanceof LocalDate date) {
|
||||||
|
statement.setObject(index, date);
|
||||||
|
} else if (value instanceof LocalDateTime dateTime) {
|
||||||
|
statement.setObject(index, dateTime);
|
||||||
|
} else if (value instanceof OffsetDateTime dateTime) {
|
||||||
|
statement.setObject(index, dateTime);
|
||||||
|
} else if (value instanceof UUID uuid) {
|
||||||
|
statement.setObject(index, uuid);
|
||||||
|
} else if (value instanceof Enum<?> enumValue) {
|
||||||
|
statement.setString(index, enumValue.name());
|
||||||
|
} else {
|
||||||
|
statement.setObject(index, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.cygnus.db;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public record QueryDefinition(int queryId, QueryType type, String sql) {
|
||||||
|
private static final String DELIMITER = "!C0L!";
|
||||||
|
private static final Pattern LEGACY_PARAMETER = Pattern.compile("\\bval\\d+\\b");
|
||||||
|
|
||||||
|
public QueryDefinition {
|
||||||
|
if (queryId <= 0) throw new QueryDefinitionException("Query ID must be positive");
|
||||||
|
Objects.requireNonNull(type, "type");
|
||||||
|
if (sql == null || sql.isBlank()) throw new QueryDefinitionException("Query SQL is empty: " + queryId);
|
||||||
|
if (LEGACY_PARAMETER.matcher(sql).find()) {
|
||||||
|
throw new QueryDefinitionException(
|
||||||
|
"Query " + queryId + " has not been migrated to parameterized SQL");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static QueryDefinition parse(int queryId, String storedValue) {
|
||||||
|
if (storedValue == null) throw new QueryDefinitionException("Query was not found: " + queryId);
|
||||||
|
int delimiter = storedValue.indexOf(DELIMITER);
|
||||||
|
if (delimiter <= 0) throw new QueryDefinitionException("Invalid query definition: " + queryId);
|
||||||
|
return new QueryDefinition(
|
||||||
|
queryId,
|
||||||
|
QueryType.parse(storedValue.substring(0, delimiter)),
|
||||||
|
storedValue.substring(delimiter + DELIMITER.length()).trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.cygnus.db;
|
||||||
|
|
||||||
|
public final class QueryDefinitionException extends RuntimeException {
|
||||||
|
public QueryDefinitionException(String message) { super(message); }
|
||||||
|
public QueryDefinitionException(String message, Throwable cause) { super(message, cause); }
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.cygnus.db;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface QueryDefinitionProvider {
|
||||||
|
QueryDefinition get(int queryId);
|
||||||
|
}
|
||||||
15
cygnus-onprem-db/src/main/java/com/cygnus/db/QueryType.java
Normal file
15
cygnus-onprem-db/src/main/java/com/cygnus/db/QueryType.java
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package com.cygnus.db;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public enum QueryType {
|
||||||
|
SELECT, INSERT, UPDATE, DELETE, PROCEDURE;
|
||||||
|
|
||||||
|
public static QueryType parse(String value) {
|
||||||
|
try {
|
||||||
|
return valueOf(value.trim().toUpperCase(Locale.ROOT));
|
||||||
|
} catch (RuntimeException exception) {
|
||||||
|
throw new QueryDefinitionException("Unsupported query type: " + value, exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.cygnus.db;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface RowConsumer<T> {
|
||||||
|
void accept(T row) throws Exception;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.cygnus.db;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface RowMapper<T> {
|
||||||
|
T map(ResultSet resultSet) throws SQLException;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.cygnus.db;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface RowView {
|
||||||
|
Object get(String column);
|
||||||
|
<T> T get(String column, Class<T> type);
|
||||||
|
Map<String, Object> asMap();
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.cygnus.db;
|
||||||
|
|
||||||
|
public record SqlParameter(int sqlType, Object value) {
|
||||||
|
public static SqlParameter of(int sqlType, Object value) { return new SqlParameter(sqlType, value); }
|
||||||
|
public static SqlParameter nullValue(int sqlType) { return new SqlParameter(sqlType, null); }
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.cygnus.db;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface TransactionCallback<T> {
|
||||||
|
T execute(TransactionOperations operations) throws Exception;
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.cygnus.db;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public interface TransactionOperations {
|
||||||
|
<T> List<T> query(int queryId, Object[] parameters, Class<T> responseType);
|
||||||
|
<T> Optional<T> queryOne(int queryId, Object[] parameters, Class<T> responseType);
|
||||||
|
int insert(int queryId, Object[] parameters);
|
||||||
|
int update(int queryId, Object[] parameters);
|
||||||
|
int delete(int queryId, Object[] parameters);
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
package com.cygnus.db;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.sql.Date;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
final class ValueConverter {
|
||||||
|
private ValueConverter() {}
|
||||||
|
|
||||||
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
|
static <T> T convert(Object value, Class<T> target) {
|
||||||
|
if (value == null) return target.isPrimitive() ? (T) primitiveDefault(target) : null;
|
||||||
|
Class<?> boxed = box(target);
|
||||||
|
if (boxed.isInstance(value)) return (T) value;
|
||||||
|
if (boxed == String.class) return (T) value.toString();
|
||||||
|
if (Number.class.isAssignableFrom(boxed) && value instanceof Number number) {
|
||||||
|
return (T) number(number, boxed);
|
||||||
|
}
|
||||||
|
if (boxed == Boolean.class) {
|
||||||
|
if (value instanceof Number number) return (T) Boolean.valueOf(number.intValue() != 0);
|
||||||
|
return (T) Boolean.valueOf(value.toString());
|
||||||
|
}
|
||||||
|
if (boxed == Character.class) {
|
||||||
|
String text = value.toString();
|
||||||
|
if (text.isEmpty()) throw new IllegalArgumentException("Cannot convert an empty value to char");
|
||||||
|
return (T) Character.valueOf(text.charAt(0));
|
||||||
|
}
|
||||||
|
if (boxed == UUID.class) return (T) UUID.fromString(value.toString());
|
||||||
|
if (boxed == LocalDate.class && value instanceof Date date) return (T) date.toLocalDate();
|
||||||
|
if (boxed == LocalDateTime.class && value instanceof Timestamp timestamp) return (T) timestamp.toLocalDateTime();
|
||||||
|
if (boxed == Instant.class && value instanceof Timestamp timestamp) return (T) timestamp.toInstant();
|
||||||
|
if (boxed == OffsetDateTime.class && value instanceof OffsetDateTime dateTime) return (T) dateTime;
|
||||||
|
if (boxed.isEnum()) return (T) Enum.valueOf((Class<Enum>) boxed, value.toString());
|
||||||
|
throw new DatabaseExecutionException(0,
|
||||||
|
"Cannot convert " + value.getClass().getName() + " to " + target.getName(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object number(Number value, Class<?> target) {
|
||||||
|
if (target == Integer.class) return value.intValue();
|
||||||
|
if (target == Long.class) return value.longValue();
|
||||||
|
if (target == Double.class) return value.doubleValue();
|
||||||
|
if (target == Float.class) return value.floatValue();
|
||||||
|
if (target == Short.class) return value.shortValue();
|
||||||
|
if (target == Byte.class) return value.byteValue();
|
||||||
|
if (target == BigDecimal.class) return value instanceof BigDecimal decimal
|
||||||
|
? decimal : new BigDecimal(value.toString());
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Class<?> box(Class<?> type) {
|
||||||
|
if (!type.isPrimitive()) return type;
|
||||||
|
if (type == int.class) return Integer.class;
|
||||||
|
if (type == long.class) return Long.class;
|
||||||
|
if (type == double.class) return Double.class;
|
||||||
|
if (type == float.class) return Float.class;
|
||||||
|
if (type == short.class) return Short.class;
|
||||||
|
if (type == byte.class) return Byte.class;
|
||||||
|
if (type == boolean.class) return Boolean.class;
|
||||||
|
if (type == char.class) return Character.class;
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object primitiveDefault(Class<?> type) {
|
||||||
|
if (type == boolean.class) return false;
|
||||||
|
if (type == char.class) return '\0';
|
||||||
|
if (type == byte.class) return (byte) 0;
|
||||||
|
if (type == short.class) return (short) 0;
|
||||||
|
if (type == int.class) return 0;
|
||||||
|
if (type == long.class) return 0L;
|
||||||
|
if (type == float.class) return 0F;
|
||||||
|
if (type == double.class) return 0D;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
package com.cygnus.db;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import org.h2.jdbcx.JdbcDataSource;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class JdbcCygnusDbExecutorTest {
|
||||||
|
private JdbcCygnusDbExecutor executor;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() throws Exception {
|
||||||
|
JdbcDataSource dataSource = new JdbcDataSource();
|
||||||
|
dataSource.setURL("jdbc:h2:mem:cygnus;DB_CLOSE_DELAY=-1");
|
||||||
|
try (Connection connection = dataSource.getConnection(); Statement statement = connection.createStatement()) {
|
||||||
|
statement.execute("DROP TABLE IF EXISTS person");
|
||||||
|
statement.execute("CREATE TABLE person (id bigint generated by default as identity primary key, name varchar(100), active boolean)");
|
||||||
|
statement.execute("INSERT INTO person(name, active) VALUES ('Asha', true), ('Ravi', false)");
|
||||||
|
}
|
||||||
|
Map<Integer, QueryDefinition> queries = Map.of(
|
||||||
|
1, new QueryDefinition(1, QueryType.SELECT,
|
||||||
|
"select id, name from person where active = ? order by id"),
|
||||||
|
2, new QueryDefinition(2, QueryType.INSERT,
|
||||||
|
"insert into person(name, active) values (?, ?)"),
|
||||||
|
3, new QueryDefinition(3, QueryType.UPDATE,
|
||||||
|
"update person set active = ? where name = ?"),
|
||||||
|
4, new QueryDefinition(4, QueryType.DELETE,
|
||||||
|
"delete from person where name = ?"),
|
||||||
|
5, new QueryDefinition(5, QueryType.PROCEDURE, "call abs(?)"));
|
||||||
|
executor = new JdbcCygnusDbExecutor(dataSource, queries::get, new ExecutorOptions(10, 5));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void mapsSelectDirectlyToRecordsAndDynamicRows() {
|
||||||
|
var people = executor.query(1, new Object[]{true}, Person.class);
|
||||||
|
assertEquals(java.util.List.of(new Person(1L, "Asha")), people);
|
||||||
|
|
||||||
|
RowView row = executor.query(1, new Object[]{true}).getFirst();
|
||||||
|
assertEquals("Asha", row.get("NAME", String.class));
|
||||||
|
assertEquals(1L, row.get("id", Long.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void executesInsertUpdateDeleteAndGeneratedKeys() {
|
||||||
|
Long id = executor.insert(2, new Object[]{"Mira", true}, Long.class);
|
||||||
|
assertTrue(id > 0);
|
||||||
|
assertEquals(1, executor.update(3, new Object[]{false, "Mira"}));
|
||||||
|
assertEquals(1, executor.delete(4, new Object[]{"Mira"}));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void executesProcedureAndStreamsWithoutMaterializingRows() {
|
||||||
|
assertEquals(7, executor.procedure(5, new Object[]{-7}, Integer.class));
|
||||||
|
AtomicInteger count = new AtomicInteger();
|
||||||
|
executor.stream(1, new Object[]{true},
|
||||||
|
result -> new Person(result.getLong("id"), result.getString("name")),
|
||||||
|
row -> count.incrementAndGet());
|
||||||
|
assertEquals(1, count.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void rollsBackFailedTransactions() {
|
||||||
|
assertThrows(IllegalStateException.class, () -> executor.transaction(tx -> {
|
||||||
|
tx.insert(2, new Object[]{"Rollback", true});
|
||||||
|
throw new IllegalStateException("stop");
|
||||||
|
}));
|
||||||
|
assertFalse(executor.query(1, new Object[]{true}, Person.class).stream()
|
||||||
|
.anyMatch(person -> person.name().equals("Rollback")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void rejectsLegacyStringReplacementQueries() {
|
||||||
|
assertThrows(QueryDefinitionException.class, () ->
|
||||||
|
QueryDefinition.parse(513, "select!C0L!select * from person where id=val0"));
|
||||||
|
}
|
||||||
|
|
||||||
|
record Person(long id, String name) {}
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
BIN
cygnus-onprem-db/target/classes/com/cygnus/db/DbResult.class
Normal file
BIN
cygnus-onprem-db/target/classes/com/cygnus/db/DbResult.class
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
cygnus-onprem-db/target/classes/com/cygnus/db/QueryType.class
Normal file
BIN
cygnus-onprem-db/target/classes/com/cygnus/db/QueryType.class
Normal file
Binary file not shown.
BIN
cygnus-onprem-db/target/classes/com/cygnus/db/RowConsumer.class
Normal file
BIN
cygnus-onprem-db/target/classes/com/cygnus/db/RowConsumer.class
Normal file
Binary file not shown.
BIN
cygnus-onprem-db/target/classes/com/cygnus/db/RowMapper.class
Normal file
BIN
cygnus-onprem-db/target/classes/com/cygnus/db/RowMapper.class
Normal file
Binary file not shown.
BIN
cygnus-onprem-db/target/classes/com/cygnus/db/RowView.class
Normal file
BIN
cygnus-onprem-db/target/classes/com/cygnus/db/RowView.class
Normal file
Binary file not shown.
BIN
cygnus-onprem-db/target/classes/com/cygnus/db/SqlParameter.class
Normal file
BIN
cygnus-onprem-db/target/classes/com/cygnus/db/SqlParameter.class
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user